diff --git a/.claude/skills/agentic-merge-reference-impl/SKILL.md b/.claude/skills/agentic-merge-reference-impl/SKILL.md
new file mode 100644
index 000000000..421ea147b
--- /dev/null
+++ b/.claude/skills/agentic-merge-reference-impl/SKILL.md
@@ -0,0 +1,7 @@
+---
+name: agentic-merge-reference-impl
+description: Merge reference implementation changes from the official Copilot SDK into this Java SDK.
+license: MIT
+---
+
+Follow instructions in the [agentic-merge-reference-impl prompt](../../../.github/prompts/agentic-merge-reference-impl.prompt.md) to merge reference implementation changes from the official Copilot SDK into this Java SDK.
diff --git a/.claude/skills/agentic-merge-upstream/SKILL.md b/.claude/skills/agentic-merge-upstream/SKILL.md
deleted file mode 100644
index 32428db89..000000000
--- a/.claude/skills/agentic-merge-upstream/SKILL.md
+++ /dev/null
@@ -1,7 +0,0 @@
----
-name: agentic-merge-upstream
-description: Merge upstream changes from the official Copilot SDK into this Java SDK.
-license: MIT
----
-
-Follow instructions in the [agentic-merge-upstream prompt](../../../.github/prompts/agentic-merge-upstream.prompt.md) to merge upstream changes from the official Copilot SDK into this Java SDK.
\ No newline at end of file
diff --git a/.gitattributes b/.gitattributes
index c1965c216..adb3de78e 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1 +1,2 @@
-.github/workflows/*.lock.yml linguist-generated=true merge=ours
\ No newline at end of file
+.github/workflows/*.lock.yml linguist-generated=true merge=ours
+src/generated/java/** eol=lf linguist-generated=true
diff --git a/.github/actions/setup-copilot/action.yml b/.github/actions/setup-copilot/action.yml
index dcc99b8a7..1288a1d89 100644
--- a/.github/actions/setup-copilot/action.yml
+++ b/.github/actions/setup-copilot/action.yml
@@ -4,15 +4,36 @@ outputs:
cli-path:
description: "Path to the Copilot CLI executable"
value: ${{ steps.cli-path.outputs.path }}
+ cli-version:
+ description: "Pinned @github/copilot version installed (read from pom.xml)"
+ value: ${{ steps.cli-version.outputs.version }}
runs:
using: "composite"
steps:
- - uses: actions/setup-node@v6
+ - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v6
with:
node-version: 22
- - name: Install Copilot CLI
- run: npm install -g @github/copilot
+ - name: Read pinned @github/copilot version from pom.xml
+ id: cli-version
shell: bash
+ # The version is the SINGLE SOURCE OF TRUTH for the Copilot CLI version
+ # used across all CI paths. It is kept in sync with the reference
+ # implementation pinned in .lastmerge by
+ # .github/scripts/reference-impl-sync/sync-cli-version-from-reference-impl.sh.
+ run: |
+ PROP="readonly-copilot-sdk-ref-impl-version-from-lastmerge-file-updated-by-reference-impl-sync"
+ VERSION=$(sed -n "s|.*<${PROP}>\(.*\)${PROP}>.*|\1|p" pom.xml | head -n 1 | tr -d '[:space:]')
+ if [[ -z "$VERSION" || "$VERSION" == "PRIMER_TO_REPLACE" ]]; then
+ echo "::error::Could not read pinned @github/copilot version from pom.xml property <${PROP}>" >&2
+ exit 1
+ fi
+ echo "Pinned @github/copilot version: $VERSION"
+ echo "version=$VERSION" >> "$GITHUB_OUTPUT"
+ - name: Install Copilot CLI (pinned to pom.xml version)
+ shell: bash
+ env:
+ CLI_VERSION: ${{ steps.cli-version.outputs.version }}
+ run: npm install -g "@github/copilot@${CLI_VERSION}"
- name: Set CLI path
id: cli-path
run: echo "path=$(which copilot)" >> $GITHUB_OUTPUT
diff --git a/.github/agents/agentic-workflows.agent.md b/.github/agents/agentic-workflows.agent.md
index 3cf66a3b2..e8f499139 100644
--- a/.github/agents/agentic-workflows.agent.md
+++ b/.github/agents/agentic-workflows.agent.md
@@ -1,7 +1,8 @@
---
name: Agentic Workflows
description: GitHub Agentic Workflows (gh-aw) - Create, debug, and upgrade AI-powered workflows with intelligent prompt routing
-infer: false
+user-invocable: true
+disable-model-invocation: true
---
# GitHub Agentic Workflows Agent
diff --git a/.github/aw/actions-lock.json b/.github/aw/actions-lock.json
index d81867b96..8bf544f4d 100644
--- a/.github/aw/actions-lock.json
+++ b/.github/aw/actions-lock.json
@@ -1,10 +1,25 @@
{
"entries": {
+ "actions/checkout@v6.0.2": {
+ "repo": "actions/checkout",
+ "version": "v6.0.2",
+ "sha": "de0fac2e4500dabe0009e67214ff5f5447ce83dd"
+ },
+ "actions/download-artifact@v8.0.1": {
+ "repo": "actions/download-artifact",
+ "version": "v8.0.1",
+ "sha": "3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c"
+ },
"actions/github-script@v8": {
"repo": "actions/github-script",
"version": "v8",
"sha": "ed597411d8f924073f98dfc5c65a23a2325f34cd"
},
+ "actions/github-script@v9": {
+ "repo": "actions/github-script",
+ "version": "v9",
+ "sha": "373c709c69115d41ff229c7e5df9f8788daa9553"
+ },
"actions/setup-java@v4": {
"repo": "actions/setup-java",
"version": "v4",
@@ -15,6 +30,21 @@
"version": "v4",
"sha": "49933ea5288caeca8642d1e84afbd3f7d6820020"
},
+ "actions/upload-artifact@v7.0.1": {
+ "repo": "actions/upload-artifact",
+ "version": "v7.0.1",
+ "sha": "043fb46d1a93c77aae656e7c1c64a875d1fc6a0a"
+ },
+ "github/gh-aw-actions/setup-cli@v0.68.3": {
+ "repo": "github/gh-aw-actions/setup-cli",
+ "version": "v0.68.3",
+ "sha": "ba90f2186d7ad780ec640f364005fa24e797b360"
+ },
+ "github/gh-aw-actions/setup@v0.68.3": {
+ "repo": "github/gh-aw-actions/setup",
+ "version": "v0.68.3",
+ "sha": "ba90f2186d7ad780ec640f364005fa24e797b360"
+ },
"github/gh-aw/actions/setup@v0.51.6": {
"repo": "github/gh-aw/actions/setup",
"version": "v0.51.6",
diff --git a/.github/badges/jacoco.svg b/.github/badges/jacoco.svg
index 8ef59f460..16199628b 100644
--- a/.github/badges/jacoco.svg
+++ b/.github/badges/jacoco.svg
@@ -12,7 +12,7 @@
coveragecoverage
- 87.5%
- 87.5%
+ 81.5%
+ 81.5%
diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md
index d7dafb081..7b304f267 100644
--- a/.github/copilot-instructions.md
+++ b/.github/copilot-instructions.md
@@ -9,7 +9,7 @@ These instructions guide GitHub Copilot when assisting with this repository. The
- **Tech Stack**: Java 17+, Maven, Jackson for JSON, JUnit for testing
- **Purpose**: Provide a Java SDK for programmatic control of GitHub Copilot CLI
- **Architecture**: JSON-RPC client communicating with Copilot CLI over stdio
-- **Key Goals**: Maintain parity with upstream .NET SDK while following Java idioms
+- **Key Goals**: Maintain parity with reference implementation .NET SDK while following Java idioms
## Build & Test Commands
@@ -77,7 +77,7 @@ mvn test -Dtest=CopilotClientTest
- `com.github.copilot.sdk` - Core classes (CopilotClient, CopilotSession, JsonRpcClient)
- `com.github.copilot.sdk.json` - DTOs, request/response types, handler interfaces (SessionConfig, MessageOptions, ToolDefinition, etc.)
-- `com.github.copilot.sdk.events` - Event types for session streaming (AssistantMessageEvent, SessionIdleEvent, ToolExecutionStartEvent, etc.)
+- `com.github.copilot.sdk.generated` - Generated event types for session streaming (SessionEvent, AssistantMessageEvent, SessionIdleEvent, ToolExecutionStartEvent, etc.)
### Test Infrastructure
@@ -85,13 +85,13 @@ Tests use the official copilot-sdk test harness from `https://github.com/github/
- **E2ETestContext** - Manages test environment with CapiProxy for deterministic API responses
- **CapiProxy** - Node.js-based replaying proxy using YAML snapshots from `test/snapshots/`
-- Test snapshots are stored in the upstream repo's `test/snapshots/` directory
+- Test snapshots are stored in the reference implementation repo's `test/snapshots/` directory
## Key Conventions
-### Upstream Merging
+### Reference Implementation Merging
-This SDK tracks the official .NET implementation at `github/copilot-sdk`. The `.lastmerge` file contains the last merged upstream commit hash. Use the `agentic-merge-upstream` skill (see `.github/prompts/agentic-merge-upstream.prompt.md`) to port changes.
+This SDK tracks the official .NET implementation at `github/copilot-sdk`. The `.lastmerge` file contains the last merged reference implementation commit hash. Use the `agentic-merge-reference-impl` skill (see `.github/prompts/agentic-merge-reference-impl.prompt.md`) to port changes.
When porting from .NET:
- Adapt to Java idioms, don't copy C# patterns directly
@@ -104,7 +104,7 @@ When porting from .NET:
- 4-space indentation (enforced by Spotless with Eclipse formatter)
- Fluent setter pattern for configuration classes (e.g., `new SessionConfig().setModel("gpt-5").setTools(tools)`)
- Public APIs require Javadoc (enforced by Checkstyle, except `json` and `events` packages)
-- Pre-commit hook runs `mvn spotless:check` - enable with: `git config core.hooksPath .githooks`
+- Pre-commit hook runs `mvn spotless:check` - Must be manually enabled with: `git config core.hooksPath .githooks`, except in the Copilot coding agent environment. This hook is explicitly enabled in the Copilot coding agent environment. See [copilot-setup-steps.yml](workflows/copilot-setup-steps.yml).
### Handler Pattern
@@ -213,13 +213,17 @@ Test method names are converted to lowercase snake_case for snapshot filenames t
### What NOT to Modify
+- **DO NOT** edit, create, or delete any file under `src/generated/java/` — these are **auto-generated** by `scripts/codegen/java.ts` and will be overwritten. To update generated code, run `mvn generate-sources -Pcodegen` or trigger the `update-copilot-dependency.yml` workflow.
+ If you need to get a new version of the schemas, run `mvn generate-sources -Pupdate-schemas-from-npm-artifact` before running the code generator.
- **DO NOT** edit `.github/agents/` directory - these contain instructions for other agents
- **DO NOT** modify `target/` directory - this contains build artifacts
- **DO NOT** edit `pom.xml` dependencies without careful consideration - this SDK has minimal dependencies by design
- **DO NOT** change the Jackson version without testing against all serialization patterns
-- **DO NOT** modify test snapshots in `target/copilot-sdk/test/snapshots/` - these come from upstream
+- **DO NOT** modify test snapshots in `target/copilot-sdk/test/snapshots/` - these come from reference implementation
- **DO NOT** alter the Eclipse formatter configuration in `pom.xml` without team consensus
- **DO NOT** remove or skip Checkstyle or Spotless checks
+- **YOU MUST ALWAYS** run `gh aw compile ` after editing any `.github/workflows/*.md` agentic workflow source file to regenerate the corresponding `.lock.yml`. The lock file contains a content hash of the frontmatter — any edit to the `.md` without recompiling will cause the workflow to fail at runtime with a "lock file out of sync" error.
+- **DO NOT** edit `.github/workflows/*.lock.yml` directly — these are auto-generated by `gh aw compile` from the `.md` source files.
### Security Guidelines
@@ -244,6 +248,18 @@ This SDK is designed to be **lightweight with minimal dependencies**:
5. Check for security vulnerabilities
6. Get team approval for non-trivial additions
+## Pre-commit Hooks and Formatting (Coding Agent)
+
+The repository has a pre-commit hook (`.githooks/pre-commit`) that is **automatically enabled** in the Copilot coding agent environment via `copilot-setup-steps.yml`. The hook runs `mvn spotless:check` on any commit that includes changes under `src/`.
+
+**If a commit fails due to the pre-commit hook:**
+
+1. Run `mvn spotless:apply` to auto-fix formatting issues.
+2. Re-stage the changed files with `git add -u`.
+3. Retry the commit.
+
+**Best practice:** Always run `mvn spotless:apply` before committing Java source changes to avoid hook failures in the first place. If you forget and the hook rejects the commit, follow the three steps above and continue.
+
## Commit and PR Guidelines
### Commit Messages
@@ -266,7 +282,7 @@ This SDK is designed to be **lightweight with minimal dependencies**:
- Include tests for new functionality
- Update documentation if adding/changing public APIs
- Reference related issues using `#issue-number`
-- For upstream merges, follow the `agentic-merge-upstream` skill workflow
+- For reference implementation merges, follow the `agentic-merge-reference-impl` skill workflow
## Development Workflow
@@ -287,12 +303,12 @@ The release process is automated via the `publish-maven.yml` GitHub Actions work
- Converts the `## [Unreleased]` section to `## [version] - date`
- Creates a new empty `## [Unreleased]` section at the top
- Updates version comparison links at the bottom of CHANGELOG.md
- - Injects the upstream SDK commit hash (from `.lastmerge`) as a `> **Upstream sync:**` blockquote in both the new `[Unreleased]` section and the released version section
+ - Injects the reference implementation SDK commit hash (from `.lastmerge`) as a `> **Reference implementation sync:**` blockquote in both the new `[Unreleased]` section and the released version section
-2. **Upstream Sync Tracking**: Each release records which commit from the official `github/copilot-sdk` it is synced to:
+2. **Reference Implementation Sync Tracking**: Each release records which commit from the official `github/copilot-sdk` it is synced to:
- The `.lastmerge` file is read during the release workflow
- The commit hash is injected into `CHANGELOG.md` under the release heading
- - Format: `> **Upstream sync:** [\`github/copilot-sdk@SHORT_HASH\`](link-to-commit)`
+ - Format: `> **Reference implementation sync:** [\`github/copilot-sdk@SHORT_HASH\`](link-to-commit)`
3. **Documentation Updates**: README.md and jbang-example.java are updated with the new version.
@@ -304,3 +320,4 @@ The release process is automated via the `publish-maven.yml` GitHub Actions work
5. **Rollback**: If the release fails, the documentation commit is automatically reverted
The workflow is triggered manually via workflow_dispatch with optional version parameters.
+
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index c77d00796..04d5ab5f4 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -1,12 +1,34 @@
-# To get started with Dependabot version updates, you'll need to specify which
-# package ecosystems to update and where the package manifests are located.
-# Please see the documentation for all configuration options:
-# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
-
version: 2
updates:
- - package-ecosystem: "" # See documentation for possible values
- directory: "/" # Location of package manifests
+ - package-ecosystem: "github-actions"
+ directory: "/"
schedule:
interval: "weekly"
+ ignore:
+ # gh-aw generated files — action SHAs are managed by `gh aw compile`
+ # via .github/aw/actions-lock.json, not by Dependabot.
+ # Dependabot's find-and-replace breaks lockfile metadata headers.
+ - dependency-name: "actions/github-script"
+ - dependency-name: "github/gh-aw-actions"
+ # Major version bumps may have breaking changes and must be
+ # evaluated and applied manually.
+ - dependency-name: "*"
+ update-types: ["version-update:semver-major"]
+ groups:
+ github-actions:
+ patterns:
+ - "*"
+ - package-ecosystem: "maven"
+ directory: "/"
+ schedule:
+ interval: "weekly"
+ ignore:
+ # Major version bumps often drop Java 17 support or have breaking
+ # API changes. These must be evaluated and applied manually.
+ - dependency-name: "*"
+ update-types: ["version-update:semver-major"]
+ groups:
+ maven-deps:
+ patterns:
+ - "*"
diff --git a/.github/prompts/agentic-merge-upstream.prompt.md b/.github/prompts/agentic-merge-reference-impl.prompt.md
similarity index 64%
rename from .github/prompts/agentic-merge-upstream.prompt.md
rename to .github/prompts/agentic-merge-reference-impl.prompt.md
index c1d2c54a0..88cc2bdfe 100644
--- a/.github/prompts/agentic-merge-upstream.prompt.md
+++ b/.github/prompts/agentic-merge-reference-impl.prompt.md
@@ -1,15 +1,52 @@
-# Merge Upstream SDK Changes
-
-You are an expert Java developer tasked with porting changes from the official Copilot SDK (primarily the .NET implementation) to this Java SDK.
+# Merge Reference Implementation SDK Changes
+
+You are an expert Java developer tasked with porting changes from the reference implementation of the Copilot SDK (primarily the .NET implementation) to this Java SDK.
+
+## ❌❌❌ ABSOLUTE PROHIBITION: DO NOT TOUCH GENERATED CODE ❌❌❌
+
+> ### 🚫 THE FILES UNDER `src/generated/java/` ARE FORBIDDEN 🚫
+>
+> **NEVER, UNDER ANY CIRCUMSTANCES, MODIFY ANY FILE IN `src/generated/java/`.**
+>
+> These files are AUTO-GENERATED by `scripts/codegen/java.ts` and MUST NOT be hand-edited.
+> They are regenerated automatically when the `@github/copilot` npm package version is updated.
+>
+> ❌ DO NOT edit `src/generated/java/**/*.java`
+> ❌ DO NOT create new files in `src/generated/java/`
+> ❌ DO NOT delete files from `src/generated/java/`
+> ❌ DO NOT "fix" or "improve" generated code — it will be overwritten
+>
+> **IF ANY CHANGE YOU NEED TO MAKE REQUIRES TOUCHING `src/generated/java/`:**
+>
+> 1. **STOP IMMEDIATELY** — do not make the change
+> 2. **FAIL the agentic sync** — do not attempt to work around this restriction
+> 3. **Push an explanatory commit** with a message such as:
+> ```
+> SYNC BLOCKED: Required change needs generated code update
+>
+> The reference implementation change '' requires updates
+> to the generated RPC/event types in src/generated/java/. These files
+> cannot be hand-edited — they must be regenerated.
+>
+> ACTION REQUIRED: Re-run the update-copilot-dependency.yml workflow
+> to update the @github/copilot npm package and regenerate the Java
+> source files before this sync can be completed.
+> ```
+> 4. **Document in the PR body** which reference implementation changes were blocked and why
+> 5. **Do NOT attempt to work around this restriction** by making equivalent changes elsewhere
+>
+> The correct way to update generated code is:
+> - Trigger the `update-copilot-dependency.yml` workflow with the new `@github/copilot` version
+> - That workflow updates `package.json`, regenerates all files in `src/generated/java/`, and opens a PR
## ⚠️ IMPORTANT: Java SDK Design Takes Priority
-**The current design and architecture of the Java SDK is the priority.** When porting changes from upstream:
+**The current design and architecture of the Java SDK is the priority.** When porting changes from the reference implementation:
-1. **Adapt, don't copy** - Translate upstream features to fit the Java SDK's existing patterns, naming conventions, and architecture
+1. **Adapt, don't copy** - Translate reference implementation features to fit the Java SDK's existing patterns, naming conventions, and architecture
2. **Preserve Java idioms** - The Java SDK should feel natural to Java developers, not like a C# port
3. **Maintain consistency** - New code must match the existing codebase style and structure
-4. **Evaluate before porting** - Not every upstream change needs to be ported; some may not be applicable or may conflict with Java SDK design decisions
+4. **Evaluate before porting** - Not every reference implementation change needs to be ported; some may not be applicable or may conflict with Java SDK design decisions
Before making any changes, **read and understand the existing Java SDK implementation** to ensure new code integrates seamlessly.
@@ -19,50 +56,50 @@ The `.github/scripts/` directory contains helper scripts that automate the repea
| Script | Purpose |
|---|---|
-| `.github/scripts/upstream-sync/merge-upstream-start.sh` | Creates branch, updates CLI, clones upstream, reads `.lastmerge`, prints commit summary |
-| `.github/scripts/upstream-sync/merge-upstream-diff.sh` | Detailed diff analysis grouped by area (`.NET src`, tests, snapshots, docs, etc.) |
-| `.github/scripts/upstream-sync/merge-upstream-finish.sh` | Runs format + test + build, updates `.lastmerge`, commits, pushes branch |
+| `.github/scripts/reference-impl-sync/merge-reference-impl-start.sh` | Creates branch, updates CLI, clones reference implementation, reads `.lastmerge`, prints commit summary |
+| `.github/scripts/reference-impl-sync/merge-reference-impl-diff.sh` | Detailed diff analysis grouped by area (`.NET src`, tests, snapshots, docs, etc.) |
+| `.github/scripts/reference-impl-sync/merge-reference-impl-finish.sh` | Runs format + test + build, updates `.lastmerge`, commits, pushes branch |
| `.github/scripts/build/format-and-test.sh` | Standalone `spotless:apply` + `mvn clean verify` (useful during porting too) |
-All scripts write/read a `.merge-env` file (git-ignored) to share state (branch name, upstream dir, last-merge commit).
+All scripts write/read a `.merge-env` file (git-ignored) to share state (branch name, reference-impl dir, last-merge commit).
## Workflow Overview
-1. Run `./.github/scripts/upstream-sync/merge-upstream-start.sh` (creates branch, clones upstream, shows summary)
-2. Run `./.github/scripts/upstream-sync/merge-upstream-diff.sh` (analyze changes)
+1. Run `./.github/scripts/reference-impl-sync/merge-reference-impl-start.sh` (creates branch, clones reference implementation, shows summary)
+2. Run `./.github/scripts/reference-impl-sync/merge-reference-impl-diff.sh` (analyze changes)
3. Update README with minimum CLI version requirement
-4. Identify upstream changes to port
+4. Identify reference implementation changes to port
5. Apply changes to Java SDK (commit as you go)
-6. Port/adjust tests from upstream changes
+6. Port/adjust tests from reference implementation changes
7. Run `./.github/scripts/build/format-and-test.sh` frequently while porting
8. Build the package
-9. Update documentation (**required for every user-facing upstream change**)
-10. Run `./.github/scripts/upstream-sync/merge-upstream-finish.sh` (final test + push) and finalize Pull Request (see note below about coding agent vs. manual workflow)
+9. Update documentation (**required for every user-facing reference implementation change**)
+10. Run `./.github/scripts/reference-impl-sync/merge-reference-impl-finish.sh` (final test + push) and finalize Pull Request (see note below about coding agent vs. manual workflow)
11. Perform final review before handing off
---
-## Step 1: Initialize Upstream Sync
+## Step 1: Initialize Reference Implementation Sync
-Run the start script to create a branch, update the CLI, clone the upstream repo, and see a summary of new commits:
+Run the start script to create a branch, update the CLI, clone the reference implementation repo, and see a summary of new commits:
```bash
-./.github/scripts/upstream-sync/merge-upstream-start.sh
+./.github/scripts/reference-impl-sync/merge-reference-impl-start.sh
```
This writes a `.merge-env` file used by the other scripts. It outputs:
- The branch name created
- The Copilot CLI version
-- The upstream dir path
-- A short log of upstream commits since `.lastmerge`
+- The reference-impl dir path
+- A short log of reference implementation commits since `.lastmerge`
-## Step 2: Analyze Upstream Changes
+## Step 2: Analyze reference implementation Changes
Run the diff script for a detailed breakdown by area:
```bash
-./.github/scripts/upstream-sync/merge-upstream-diff.sh # stat only
-./.github/scripts/upstream-sync/merge-upstream-diff.sh --full # full diffs
+./.github/scripts/reference-impl-sync/merge-reference-impl-diff.sh # stat only
+./.github/scripts/reference-impl-sync/merge-reference-impl-diff.sh --full # full diffs
```
The diff script groups changes into: .NET source, .NET tests, test snapshots, documentation, protocol/config, Go/Node.js/Python SDKs, and other files.
@@ -80,13 +117,13 @@ git commit -m "Update Copilot CLI minimum version requirement"
## Step 4: Identify Changes to Port
-Using the output from `merge-upstream-diff.sh`, focus on:
+Using the output from `merge-reference-impl-diff.sh`, focus on:
- `dotnet/src/` - Primary reference implementation
- `dotnet/test/` - Test cases to port
- `docs/` - Documentation updates
- `sdk-protocol-version.json` - Protocol version changes
-For each change in the upstream diff, determine:
+For each change in the reference implementation diff, determine:
1. **New Features**: New methods, classes, or capabilities added to the SDK
2. **Bug Fixes**: Corrections to existing functionality
@@ -96,12 +133,12 @@ For each change in the upstream diff, determine:
### Key Files to Compare
-| Upstream (.NET) | Java SDK Equivalent |
+| reference implementation (.NET) | Java SDK Equivalent |
|------------------------------------|--------------------------------------------------------|
| `dotnet/src/Client.cs` | `src/main/java/com/github/copilot/sdk/CopilotClient.java` |
| `dotnet/src/Session.cs` | `src/main/java/com/github/copilot/sdk/CopilotSession.java` |
| `dotnet/src/Types.cs` | `src/main/java/com/github/copilot/sdk/types/*.java` |
-| `dotnet/src/Generated/*.cs` | `src/main/java/com/github/copilot/sdk/types/*.java` |
+| `dotnet/src/Generated/*.cs` | ❌ **DO NOT TOUCH** `src/generated/java/**` — see top of this file |
| `dotnet/test/*.cs` | `src/test/java/com/github/copilot/sdk/*Test.java` |
| `docs/getting-started.md` | `README.md` and `src/site/markdown/*.md` |
| `docs/*.md` (new files) | `src/site/markdown/*.md` + update `src/site/site.xml` |
@@ -111,6 +148,10 @@ For each change in the upstream diff, determine:
## Step 5: Apply Changes to Java SDK
+> ### ❌❌❌ REMINDER: `src/generated/java/` IS FORBIDDEN ❌❌❌
+> Any change that requires modifying `src/generated/java/` MUST stop the sync.
+> See the **ABSOLUTE PROHIBITION** section at the top of this file for required actions.
+
When porting changes:
### ⚠️ Priority: Preserve Java SDK Design
@@ -121,7 +162,7 @@ Before modifying any code:
2. **Identify the Java equivalent approach** - Don't replicate C# patterns; find the idiomatic Java way
3. **Check for existing abstractions** - The Java SDK may already have mechanisms that differ from .NET
4. **Preserve backward compatibility** - Existing API signatures should not break unless absolutely necessary
-5. **When in doubt, match existing code** - Follow what's already in the Java SDK, not the upstream
+5. **When in doubt, match existing code** - Follow what's already in the Java SDK, not the reference implementation
### Commit Changes Incrementally
@@ -130,12 +171,12 @@ Before modifying any code:
```bash
# After porting a feature or fix, commit with a descriptive message
git add
-git commit -m "Port from upstream"
+git commit -m "Port from the reference implementation"
# Example commits:
-# git commit -m "Port new authentication flow from upstream"
-# git commit -m "Add new message types from upstream protocol update"
-# git commit -m "Port bug fix for session handling from upstream"
+# git commit -m "Port new authentication flow from the reference implementation"
+# git commit -m "Add new message types from the reference implementation protocol update"
+# git commit -m "Port bug fix for session handling from the reference implementation"
```
This creates a clear history of changes that can be reviewed in the Pull Request.
@@ -170,19 +211,19 @@ Follow the existing Java SDK patterns:
- Use Java records for DTOs where appropriate
- Follow the existing package structure under `com.github.copilot.sdk`
- Maintain backward compatibility when possible
-- **Match the style of surrounding code** - Consistency with existing code is more important than upstream patterns
+- **Match the style of surrounding code** - Consistency with existing code is more important than reference implementation patterns
- **Prefer existing abstractions** - If the Java SDK already solves a problem differently than .NET, keep the Java approach
## Step 6: Port Tests
-After porting implementation changes, **always check for new or updated tests** in the upstream repository:
+After porting implementation changes, **always check for new or updated tests** in the reference implementation repository:
### Check for New Tests
```bash
cd "$TEMP_DIR/copilot-sdk"
-git diff "$LAST_MERGE_COMMIT"..origin/main --stat -- dotnet/test/
-git diff "$LAST_MERGE_COMMIT"..origin/main --stat -- test/snapshots/
+git diff "$LAST_REFERENCE_IMPL_COMMIT"..origin/main --stat -- dotnet/test/
+git diff "$LAST_REFERENCE_IMPL_COMMIT"..origin/main --stat -- test/snapshots/
```
### Port Test Cases
@@ -196,7 +237,7 @@ For each new or modified test file in `dotnet/test/`:
### Test File Mapping
-| Upstream Test (.NET) | Java SDK Test |
+| reference implementation Test (.NET) | Java SDK Test |
|-----------------------------|--------------------------------------------------------|
| `dotnet/test/AskUserTests.cs` | `src/test/java/com/github/copilot/sdk/AskUserTest.java` |
| `dotnet/test/HooksTests.cs` | `src/test/java/com/github/copilot/sdk/HooksTest.java` |
@@ -205,11 +246,11 @@ For each new or modified test file in `dotnet/test/`:
### Test Snapshot Compatibility
-New test snapshots are stored in `test/snapshots/` in the upstream repository. These snapshots are automatically cloned during the Maven build process.
+New test snapshots are stored in `test/snapshots/` in the reference implementation repository. These snapshots are automatically cloned during the Maven build process.
If tests fail with errors like `TypeError: Cannot read properties of undefined`, the test harness may not yet support the new RPC methods. In this case:
-1. **Mark tests as `@Disabled`** with a clear reason (e.g., `@Disabled("Requires test harness update with X support - see upstream PR #NNN")`)
+1. **Mark tests as `@Disabled`** with a clear reason (e.g., `@Disabled("Requires test harness update with X support - see reference implementation PR #NNN")`)
2. **Document the dependency** in the test class Javadoc
3. **Enable tests later** once the harness is updated
@@ -266,7 +307,7 @@ Verify:
## Step 9: Update Documentation
-**Documentation is critical for new features.** Every new feature ported from upstream must be documented before the merge is complete.
+**Documentation is critical for new features.** Every new feature ported from the reference implementation must be documented before the merge is complete.
Review and complete this documentation checklist before proceeding to Step 10.
If you determine no docs changes are needed, document that decision and rationale in the PR body under a clear heading (for example, `Documentation Impact`).
@@ -328,31 +369,31 @@ Ensure consistency across all documentation files:
Run the finish script which updates `.lastmerge`, runs a final build, and pushes the branch:
```bash
-./.github/scripts/upstream-sync/merge-upstream-finish.sh # full format + test + push
-./.github/scripts/upstream-sync/merge-upstream-finish.sh --skip-tests # if tests already passed
+./.github/scripts/reference-impl-sync/merge-reference-impl-finish.sh # full format + test + push
+./.github/scripts/reference-impl-sync/merge-reference-impl-finish.sh --skip-tests # if tests already passed
```
### PR Handling: Coding Agent vs. Manual Workflow
-**If running as a Copilot coding agent** (triggered via GitHub issue assignment by the weekly sync workflow), a pull request has **already been created automatically** for you. Do NOT create a new one. Just push your commits to the current branch — the existing PR will be updated. Add the `upstream-sync` label to the existing PR by running this command in a terminal:
+**If running as a Copilot coding agent** (triggered via GitHub issue assignment by the weekly sync workflow), a pull request has **already been created automatically** for you. Do NOT create a new one. Just push your commits to the current branch — the existing PR will be updated. Add the `reference-impl-sync` label to the existing PR by running this command in a terminal:
```bash
-gh pr edit --add-label "upstream-sync"
+gh pr edit --add-label "reference-impl-sync"
```
-> **No-changes scenario (coding agent only):** If after analyzing the upstream diff there are no relevant changes to port to the Java SDK, push an empty commit with a message explaining why no changes were needed, so the PR reflects the analysis outcome. The repository maintainer will close the PR and issue manually.
+> **No-changes scenario (coding agent only):** If after analyzing the reference implementation diff there are no relevant changes to port to the Java SDK, push an empty commit with a message explaining why no changes were needed, so the PR reflects the analysis outcome. The repository maintainer will close the PR and issue manually.
**If running manually** (e.g., from VS Code via the reusable prompt), create the Pull Request using `gh` CLI or the GitHub MCP tool. Then add the label:
```bash
-gh pr create --base main --title "Merge upstream SDK changes (YYYY-MM-DD)" --body-file /dev/stdin <<< "$PR_BODY"
-gh pr edit --add-label "upstream-sync"
+gh pr create --base main --title "Merge reference implementation SDK changes (YYYY-MM-DD)" --body-file /dev/stdin <<< "$PR_BODY"
+gh pr edit --add-label "reference-impl-sync"
```
The PR body should include:
-1. **Title**: `Merge upstream SDK changes (YYYY-MM-DD)`
+1. **Title**: `Merge reference implementation SDK changes (YYYY-MM-DD)`
2. **Body** with:
- - Summary of upstream commits analyzed (with count and commit range)
+ - Summary of reference implementation commits analyzed (with count and commit range)
- Table of changes ported (commit hash + description)
- List of changes intentionally not ported (with reasons)
- Verification status (test count, build status)
@@ -360,13 +401,13 @@ The PR body should include:
### PR Body Template
```markdown
-## Upstream Merge
+## Reference Implementation Merge
Ports changes from the official Copilot SDK ([github/copilot-sdk](https://github.com/github/copilot-sdk)) since last merge (``→``).
-### Upstream commits analyzed (N commits)
+### Reference implementation commits analyzed (N commits)
-- Brief description of each upstream change and whether it was ported or not
+- Brief description of each reference implementation change and whether it was ported or not
### Changes ported
@@ -400,14 +441,15 @@ Before finishing:
## Checklist
+- [ ] ❌ **VERIFIED: No files in `src/generated/java/` were modified** (if any were needed, sync was stopped per ABSOLUTE PROHIBITION above)
- [ ] New branch created from `main`
- [ ] Copilot CLI updated to latest version
- [ ] README.md updated with minimum CLI version requirement
-- [ ] Upstream repository cloned
+- [ ] reference implementation repository cloned
- [ ] Diff analyzed between `.lastmerge` commit and HEAD
- [ ] New features/fixes identified
- [ ] Changes ported to Java SDK following conventions
-- [ ] **New/updated tests ported from upstream** (check `dotnet/test/` and `test/snapshots/`)
+- [ ] **New/updated tests ported from the reference implementation** (check `dotnet/test/` and `test/snapshots/`)
- [ ] Tests marked `@Disabled` if harness doesn't support new features yet
- [ ] Changes committed incrementally with descriptive messages
- [ ] `mvn test` passes
@@ -418,22 +460,24 @@ Before finishing:
- [ ] `src/site/markdown/documentation.md` updated for new basic usage
- [ ] `src/site/markdown/advanced.md` updated for new advanced features
- [ ] Javadoc added/updated for new public APIs
-- [ ] If no documentation files were changed for user-facing upstream changes, PR body explicitly explains why documentation changes were not needed
+- [ ] If no documentation files were changed for user-facing reference implementation changes, PR body explicitly explains why documentation changes were not needed
- [ ] `src/site/site.xml` updated if new documentation pages were added
- [ ] `.lastmerge` file updated with new commit hash
- [ ] Branch pushed to remote
- [ ] **Pull Request finalized** (coding agent: push to existing PR; manual: create via `mcp_github_create_pull_request`)
-- [ ] **`upstream-sync` label added** to the PR via `mcp_github_add_issue_labels`
+- [ ] **`reference-impl-sync` label added** to the PR via `mcp_github_add_issue_labels`
- [ ] PR URL provided to user
---
## Notes
-- The upstream SDK is at: `https://github.com/github/copilot-sdk.git`
+- ❌❌❌ **`src/generated/java/` IS FORBIDDEN** — NEVER modify generated files; re-run `update-copilot-dependency.yml` instead ❌❌❌
+- The reference implementation SDK is at: `https://github.com/github/copilot-sdk.git`
- Primary reference implementation is in `dotnet/` folder
- This Java SDK targets Java 17+
- Uses Jackson for JSON processing
- Uses JUnit 5 for testing
-- **Java SDK design decisions take precedence over upstream patterns**
-- **Adapt upstream changes to fit Java idioms, not the other way around**
+- **Java SDK design decisions take precedence over reference implementation patterns**
+- **Adapt reference implementation changes to fit Java idioms, not the other way around**
+
diff --git a/.github/prompts/coding-agent-merge-instructions.md b/.github/prompts/coding-agent-merge-instructions.md
deleted file mode 100644
index 1c18e1f5f..000000000
--- a/.github/prompts/coding-agent-merge-instructions.md
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
-
-Follow the agentic-merge-upstream prompt at .github/prompts/agentic-merge-upstream.prompt.md
-to port upstream changes to the Java SDK.
-
-Use the utility scripts in .github/scripts/ subfolders for initialization, diffing, formatting, and testing.
-Commit changes incrementally. Update .lastmerge when done.
-
-IMPORTANT: A pull request has already been created automatically for you — do NOT create a new
-one. Push your commits to the current branch, and the existing PR will be updated.
-
-Add the 'upstream-sync' label to the existing PR by running this command in a terminal:
-
- gh pr edit --add-label "upstream-sync"
-
-If after analyzing the upstream diff there are no relevant changes to port to the Java SDK,
-push an empty commit with a message explaining why no changes were needed, so the PR reflects
-the analysis outcome. The repository maintainer will close the PR and issue manually.
diff --git a/.github/prompts/coding-agent-merge-reference-impl-instructions.md b/.github/prompts/coding-agent-merge-reference-impl-instructions.md
new file mode 100644
index 000000000..5ae1621db
--- /dev/null
+++ b/.github/prompts/coding-agent-merge-reference-impl-instructions.md
@@ -0,0 +1,33 @@
+
+
+
+Follow the agentic-merge-reference-impl prompt at .github/prompts/agentic-merge-reference-impl.prompt.md
+to port reference implementation changes to the Java SDK.
+
+Use the utility scripts in .github/scripts/ subfolders for initialization, diffing, formatting, and testing.
+Commit changes incrementally. Update .lastmerge when done.
+
+IMPORTANT: A pull request has already been created automatically for you — do NOT create a new
+one. Push your commits to the current branch, and the existing PR will be updated.
+
+Add the 'reference-impl-sync' label to the existing PR by running this command in a terminal:
+
+ gh pr edit --add-label "reference-impl-sync"
+
+If after analyzing the reference implementation diff there are no relevant changes to port to the Java SDK,
+push an empty commit with a message explaining why no changes were needed, so the PR reflects
+the analysis outcome. The repository maintainer will close the PR and issue manually.
+
+❌❌❌ ABSOLUTE PROHIBITION ❌❌❌
+
+NEVER MODIFY ANY FILE UNDER src/generated/java/ — THESE FILES ARE AUTO-GENERATED AND FORBIDDEN.
+
+If any change requires modifying src/generated/java/:
+1. STOP IMMEDIATELY — do not make the change
+2. FAIL the sync with an explanatory commit message
+3. Instruct the maintainer to re-run update-copilot-dependency.yml to regenerate these files
+
+See the ABSOLUTE PROHIBITION section in .github/prompts/agentic-merge-reference-impl.prompt.md
+for the full required procedure and commit message template.
+
+❌❌❌ END ABSOLUTE PROHIBITION ❌❌❌
diff --git a/.github/scripts/upstream-sync/merge-upstream-diff.sh b/.github/scripts/reference-impl-sync/merge-reference-impl-diff.sh
similarity index 86%
rename from .github/scripts/upstream-sync/merge-upstream-diff.sh
rename to .github/scripts/reference-impl-sync/merge-reference-impl-diff.sh
index ee61b6ffc..8ff870103 100755
--- a/.github/scripts/upstream-sync/merge-upstream-diff.sh
+++ b/.github/scripts/reference-impl-sync/merge-reference-impl-diff.sh
@@ -1,8 +1,8 @@
#!/usr/bin/env bash
# ──────────────────────────────────────────────────────────────
-# merge-upstream-diff.sh
+# merge-reference-impl-diff.sh
#
-# Generates a detailed diff analysis of upstream changes since
+# Generates a detailed diff analysis of reference implementation changes since
# the last merge, grouped by area of interest:
# • .NET source (primary reference)
# • .NET tests
@@ -10,10 +10,10 @@
# • Documentation
# • Protocol / config files
#
-# Usage: ./.github/scripts/upstream-sync/merge-upstream-diff.sh [--full]
+# Usage: ./.github/scripts/reference-impl-sync/merge-reference-impl-diff.sh [--full]
# --full Show actual diffs, not just stats
#
-# Requires: .merge-env written by merge-upstream-start.sh
+# Requires: .merge-env written by merge-reference-impl-start.sh
# ──────────────────────────────────────────────────────────────
set -euo pipefail
@@ -21,7 +21,7 @@ ROOT_DIR="$(cd "$(dirname "$0")/../../.." && pwd)"
ENV_FILE="$ROOT_DIR/.merge-env"
if [[ ! -f "$ENV_FILE" ]]; then
- echo "❌ $ENV_FILE not found. Run ./.github/scripts/upstream-sync/merge-upstream-start.sh first."
+ echo "❌ $ENV_FILE not found. Run ./.github/scripts/reference-impl-sync/merge-reference-impl-start.sh first."
exit 1
fi
@@ -33,13 +33,13 @@ if [[ "${1:-}" == "--full" ]]; then
SHOW_FULL=true
fi
-cd "$UPSTREAM_DIR"
+cd "$REFERENCE_IMPL_DIR"
git fetch origin main 2>/dev/null
RANGE="$LAST_MERGE_COMMIT..origin/main"
echo "════════════════════════════════════════════════════════════"
-echo " Upstream diff analysis: $RANGE"
+echo " Reference implementation diff analysis: $RANGE"
echo "════════════════════════════════════════════════════════════"
# ── Commit log ────────────────────────────────────────────────
@@ -82,5 +82,5 @@ section "Other files" "README.md" "CONTRIBUTING.md" "SECURIT
echo "════════════════════════════════════════════════════════════"
echo " To see full diffs: $0 --full"
echo " To see a specific path:"
-echo " cd $UPSTREAM_DIR && git diff $RANGE -- "
+echo " cd $REFERENCE_IMPL_DIR && git diff $RANGE -- "
echo "════════════════════════════════════════════════════════════"
diff --git a/.github/scripts/reference-impl-sync/merge-reference-impl-finish.sh b/.github/scripts/reference-impl-sync/merge-reference-impl-finish.sh
new file mode 100755
index 000000000..2dda8da07
--- /dev/null
+++ b/.github/scripts/reference-impl-sync/merge-reference-impl-finish.sh
@@ -0,0 +1,81 @@
+#!/usr/bin/env bash
+# ──────────────────────────────────────────────────────────────
+# merge-reference-impl-finish.sh
+#
+# Finalises a reference implementation merge:
+# 1. Runs format + test + build (via format-and-test.sh)
+# 2. Updates .lastmerge to reference implementation HEAD
+# 3. Syncs the @github/copilot version property in pom.xml from the
+# cloned reference implementation's nodejs/package.json
+# 4. Syncs scripts/codegen/package.json to the same @github/copilot
+# version so the code generator uses matching schemas
+# 5. Commits the .lastmerge + pom.xml + codegen package updates
+# 6. Pushes the branch to origin
+#
+# Usage: ./.github/scripts/reference-impl-sync/merge-reference-impl-finish.sh
+# ./.github/scripts/reference-impl-sync/merge-reference-impl-finish.sh --skip-tests
+#
+# Requires: .merge-env written by merge-reference-impl-start.sh
+# ──────────────────────────────────────────────────────────────
+set -euo pipefail
+
+ROOT_DIR="$(cd "$(dirname "$0")/../../.." && pwd)"
+ENV_FILE="$ROOT_DIR/.merge-env"
+
+if [[ ! -f "$ENV_FILE" ]]; then
+ echo "❌ $ENV_FILE not found. Run ./.github/scripts/reference-impl-sync/merge-reference-impl-start.sh first."
+ exit 1
+fi
+
+# shellcheck source=/dev/null
+source "$ENV_FILE"
+
+SKIP_TESTS=false
+if [[ "${1:-}" == "--skip-tests" ]]; then
+ SKIP_TESTS=true
+fi
+
+cd "$ROOT_DIR"
+
+# ── 1. Format, test, build ───────────────────────────────────
+if $SKIP_TESTS; then
+ echo "▸ Formatting only (tests skipped)…"
+ mvn spotless:apply
+ mvn clean package -DskipTests
+else
+ echo "▸ Running format + test + build…"
+ "$ROOT_DIR/.github/scripts/build/format-and-test.sh"
+fi
+
+# ── 2. Update .lastmerge ─────────────────────────────────────
+echo "▸ Updating .lastmerge…"
+NEW_COMMIT=$(cd "$REFERENCE_IMPL_DIR" && git rev-parse origin/main)
+echo "$NEW_COMMIT" > "$ROOT_DIR/.lastmerge"
+
+# ── 2b. Sync pom.xml @github/copilot version ─────────────────
+# Keeps the canonical CLI version in pom.xml aligned with what the
+# reference implementation pinned in .lastmerge depends on.
+echo "▸ Syncing @github/copilot version in pom.xml from reference implementation…"
+"$ROOT_DIR/.github/scripts/reference-impl-sync/sync-cli-version-from-reference-impl.sh" "$REFERENCE_IMPL_DIR"
+
+# ── 2c. Sync scripts/codegen @github/copilot version ─────────
+# Keeps scripts/codegen/package.json in lockstep so the code generator
+# uses schemas from the same CLI version that the tests run against.
+# This eliminates the gap where Dependabot could race ahead of the
+# reference implementation sync.
+echo "▸ Syncing @github/copilot version in scripts/codegen/package.json…"
+"$ROOT_DIR/.github/scripts/reference-impl-sync/sync-codegen-version.sh" "$REFERENCE_IMPL_DIR"
+
+git add .lastmerge pom.xml scripts/codegen/package.json scripts/codegen/package-lock.json
+git commit -m "Update .lastmerge to $NEW_COMMIT, sync pom.xml CLI version, and update scripts/codegen @github/copilot version"
+
+# ── 3. Push branch ───────────────────────────────────────────
+echo "▸ Pushing branch $BRANCH_NAME to origin…"
+git push -u origin "$BRANCH_NAME"
+
+echo ""
+echo "✅ Branch pushed. Next step:"
+echo " Create a Pull Request (base: main, head: $BRANCH_NAME)"
+echo ""
+echo " Suggested title: Merge reference implementation SDK changes ($(date +%Y-%m-%d))"
+echo " Don't forget to add the 'reference-impl-sync' label."
diff --git a/.github/scripts/upstream-sync/merge-upstream-start.sh b/.github/scripts/reference-impl-sync/merge-reference-impl-start.sh
similarity index 68%
rename from .github/scripts/upstream-sync/merge-upstream-start.sh
rename to .github/scripts/reference-impl-sync/merge-reference-impl-start.sh
index 755361cd1..76408e4ec 100755
--- a/.github/scripts/upstream-sync/merge-upstream-start.sh
+++ b/.github/scripts/reference-impl-sync/merge-reference-impl-start.sh
@@ -1,15 +1,15 @@
#!/usr/bin/env bash
# ──────────────────────────────────────────────────────────────
-# merge-upstream-start.sh
+# merge-reference-impl-start.sh
#
-# Prepares the workspace for an upstream merge:
+# Prepares the workspace for a reference implementation merge:
# 1. Creates a dated branch from main
# 2. Updates Copilot CLI and records the new version
-# 3. Clones the upstream copilot-sdk repo into a temp dir
+# 3. Clones the reference implementation copilot-sdk repo into a temp dir
# 4. Reads .lastmerge and prints a short summary of new commits
#
-# Usage: ./.github/scripts/upstream-sync/merge-upstream-start.sh
-# Output: Exports UPSTREAM_DIR and LAST_MERGE_COMMIT to a
+# Usage: ./.github/scripts/reference-impl-sync/merge-reference-impl-start.sh
+# Output: Exports REFERENCE_IMPL_DIR and LAST_MERGE_COMMIT to a
# .merge-env file so other scripts can source it.
# ──────────────────────────────────────────────────────────────
set -euo pipefail
@@ -17,7 +17,7 @@ set -euo pipefail
ROOT_DIR="$(cd "$(dirname "$0")/../../.." && pwd)"
cd "$ROOT_DIR"
-UPSTREAM_REPO="https://github.com/github/copilot-sdk.git"
+REFERENCE_IMPL_REPO="https://github.com/github/copilot-sdk.git"
ENV_FILE="$ROOT_DIR/.merge-env"
# ── 1. Create branch (or reuse existing) ─────────────────────
@@ -33,7 +33,7 @@ else
echo "▸ Ensuring main is up to date…"
git pull origin main
- BRANCH_NAME="merge-upstream-$(date +%Y%m%d)"
+ BRANCH_NAME="merge-reference-impl-$(date +%Y%m%d)"
echo "▸ Creating branch: $BRANCH_NAME"
git checkout -b "$BRANCH_NAME"
fi
@@ -49,11 +49,11 @@ else
CLI_VERSION="UNKNOWN"
fi
-# ── 3. Clone upstream ────────────────────────────────────────
+# ── 3. Clone reference implementation ────────────────────────────────────────
TEMP_DIR=$(mktemp -d)
-UPSTREAM_DIR="$TEMP_DIR/copilot-sdk"
-echo "▸ Cloning upstream into $UPSTREAM_DIR …"
-git clone --depth=200 "$UPSTREAM_REPO" "$UPSTREAM_DIR"
+REFERENCE_IMPL_DIR="$TEMP_DIR/copilot-sdk"
+echo "▸ Cloning reference implementation into $REFERENCE_IMPL_DIR …"
+git clone --depth=200 "$REFERENCE_IMPL_REPO" "$REFERENCE_IMPL_DIR"
# ── 4. Read last merge commit ────────────────────────────────
if [[ ! -f "$ROOT_DIR/.lastmerge" ]]; then
@@ -61,21 +61,21 @@ if [[ ! -f "$ROOT_DIR/.lastmerge" ]]; then
exit 1
fi
LAST_MERGE_COMMIT=$(tr -d '[:space:]' < "$ROOT_DIR/.lastmerge")
-echo "▸ Last merged upstream commit: $LAST_MERGE_COMMIT"
+echo "▸ Last merged reference implementation commit: $LAST_MERGE_COMMIT"
# Quick summary
echo ""
-echo "── Upstream commits since last merge ──"
-(cd "$UPSTREAM_DIR" && git fetch origin main && \
+echo "── Reference implementation commits since last merge ──"
+(cd "$REFERENCE_IMPL_DIR" && git fetch origin main && \
git log --oneline "$LAST_MERGE_COMMIT"..origin/main) || \
echo " (could not generate log – the commit may have been rebased)"
echo ""
# ── 5. Write env file for other scripts ──────────────────────
cat > "$ENV_FILE" <
+#
+# This keeps the canonical Copilot CLI version (declared in pom.xml)
+# in sync with whatever the reference implementation pinned in
+# .lastmerge depends on. All workflows that install the Copilot CLI
+# (build-test.yml — implicitly via cloned SDK, run-smoke-test.yml and
+# update-copilot-dependency.yml — via the setup-copilot action) read
+# this single property so every CI path uses the same CLI version.
+#
+# Usage:
+# ./sync-cli-version-from-reference-impl.sh
+#
+# Or, when invoked from merge-reference-impl-finish.sh, sources
+# REFERENCE_IMPL_DIR from the .merge-env file.
+# ──────────────────────────────────────────────────────────────
+set -euo pipefail
+
+# Locate the repo root by walking up from this script until we find a pom.xml.
+# This is resilient to the script being moved to a different depth under
+# .github/scripts/ in the future.
+find_repo_root() {
+ local dir
+ dir="$(cd "$(dirname "$0")" && pwd)"
+ while [[ "$dir" != "/" ]]; do
+ if [[ -f "$dir/pom.xml" ]]; then
+ echo "$dir"
+ return 0
+ fi
+ dir="$(dirname "$dir")"
+ done
+ echo "❌ Could not locate repo root (no pom.xml found above $(dirname "$0"))" >&2
+ return 1
+}
+ROOT_DIR="$(find_repo_root)"
+
+REFERENCE_IMPL_DIR="${1:-${REFERENCE_IMPL_DIR:-}}"
+if [[ -z "$REFERENCE_IMPL_DIR" ]]; then
+ echo "❌ Usage: $0 " >&2
+ echo " or set REFERENCE_IMPL_DIR in the environment." >&2
+ exit 1
+fi
+
+PKG_JSON="$REFERENCE_IMPL_DIR/nodejs/package.json"
+if [[ ! -f "$PKG_JSON" ]]; then
+ echo "❌ Cannot find $PKG_JSON" >&2
+ exit 1
+fi
+
+# node is always available since the reference implementation uses npm.
+CLI_VERSION=$(node -e \
+ "const fs=require('fs');const p=JSON.parse(fs.readFileSync(process.argv[1],'utf8'));const v=(p.dependencies&&p.dependencies['@github/copilot'])||(p.devDependencies&&p.devDependencies['@github/copilot']);process.stdout.write(v||'');" \
+ "$PKG_JSON")
+
+if [[ -z "$CLI_VERSION" ]]; then
+ echo "❌ Could not extract @github/copilot version from $PKG_JSON" >&2
+ exit 1
+fi
+
+POM="$ROOT_DIR/pom.xml"
+PROP="readonly-copilot-sdk-ref-impl-version-from-lastmerge-file-updated-by-reference-impl-sync"
+
+if ! grep -q "<${PROP}>" "$POM"; then
+ echo "❌ Property <${PROP}> not found in $POM" >&2
+ exit 1
+fi
+
+# Use a portable sed invocation (works on both BSD/macOS and GNU/Linux).
+TMP="$(mktemp)"
+sed -E "s|<${PROP}>[^<]*${PROP}>|<${PROP}>${CLI_VERSION}${PROP}>|" "$POM" > "$TMP"
+mv "$TMP" "$POM"
+
+echo "▸ Updated pom.xml: <${PROP}> = ${CLI_VERSION}"
diff --git a/.github/scripts/reference-impl-sync/sync-codegen-version.sh b/.github/scripts/reference-impl-sync/sync-codegen-version.sh
new file mode 100755
index 000000000..09e182bb2
--- /dev/null
+++ b/.github/scripts/reference-impl-sync/sync-codegen-version.sh
@@ -0,0 +1,71 @@
+#!/usr/bin/env bash
+# ──────────────────────────────────────────────────────────────
+# sync-codegen-version.sh
+#
+# Updates the @github/copilot dependency in scripts/codegen/package.json
+# to match the version used by the reference implementation. This keeps
+# the code generator schemas in lockstep with the CLI version used for
+# testing, eliminating the gap where Dependabot could race ahead.
+#
+# Usage:
+# ./sync-codegen-version.sh
+#
+# Or, when invoked from merge-reference-impl-finish.sh, the directory
+# is passed as $1.
+# ──────────────────────────────────────────────────────────────
+set -euo pipefail
+
+# Locate the repo root by walking up from this script until we find a pom.xml.
+find_repo_root() {
+ local dir
+ dir="$(cd "$(dirname "$0")" && pwd)"
+ while [[ "$dir" != "/" ]]; do
+ if [[ -f "$dir/pom.xml" ]]; then
+ echo "$dir"
+ return 0
+ fi
+ dir="$(dirname "$dir")"
+ done
+ echo "❌ Could not locate repo root (no pom.xml found above $(dirname "$0"))" >&2
+ return 1
+}
+ROOT_DIR="$(find_repo_root)"
+
+REFERENCE_IMPL_DIR="${1:-${REFERENCE_IMPL_DIR:-}}"
+if [[ -z "$REFERENCE_IMPL_DIR" ]]; then
+ echo "❌ Usage: $0 " >&2
+ echo " or set REFERENCE_IMPL_DIR in the environment." >&2
+ exit 1
+fi
+
+PKG_JSON="$REFERENCE_IMPL_DIR/nodejs/package.json"
+if [[ ! -f "$PKG_JSON" ]]; then
+ echo "❌ Cannot find $PKG_JSON" >&2
+ exit 1
+fi
+
+# Extract the @github/copilot version from the reference implementation.
+CLI_VERSION=$(node -e \
+ "const fs=require('fs');const p=JSON.parse(fs.readFileSync(process.argv[1],'utf8'));const v=(p.dependencies&&p.dependencies['@github/copilot'])||(p.devDependencies&&p.devDependencies['@github/copilot']);process.stdout.write(v||'');" \
+ "$PKG_JSON")
+
+if [[ -z "$CLI_VERSION" ]]; then
+ echo "❌ Could not extract @github/copilot version from $PKG_JSON" >&2
+ exit 1
+fi
+
+CODEGEN_DIR="$ROOT_DIR/scripts/codegen"
+CODEGEN_PKG="$CODEGEN_DIR/package.json"
+
+if [[ ! -f "$CODEGEN_PKG" ]]; then
+ echo "❌ Cannot find $CODEGEN_PKG" >&2
+ exit 1
+fi
+
+# Update scripts/codegen/package.json with the new version and regenerate the lock file.
+# Intentionally omit --save-exact to preserve the version specifier used by the reference
+# implementation (e.g. a caret range like '^1.0.36-0' rather than an exact pin '1.0.36-0').
+echo "▸ Updating scripts/codegen/package.json: @github/copilot → ${CLI_VERSION}"
+cd "$CODEGEN_DIR"
+npm install "@github/copilot@${CLI_VERSION}"
+echo "▸ Updated scripts/codegen to @github/copilot@${CLI_VERSION}"
diff --git a/.github/scripts/release/update-changelog.sh b/.github/scripts/release/update-changelog.sh
index a18d35b02..ff35dec72 100755
--- a/.github/scripts/release/update-changelog.sh
+++ b/.github/scripts/release/update-changelog.sh
@@ -2,24 +2,24 @@
set -e
# Script to update CHANGELOG.md during release process
-# Usage: ./update-changelog.sh [upstream-hash]
+# Usage: ./update-changelog.sh [reference-impl-hash]
# Example: ./update-changelog.sh 1.0.8
# Example: ./update-changelog.sh 1.0.8 05e3c46c8c23130c9c064dc43d00ec78f7a75eab
if [ -z "$1" ]; then
echo "Error: Version argument required"
- echo "Usage: $0 [upstream-hash]"
+ echo "Usage: $0 [reference-impl-hash]"
exit 1
fi
VERSION="$1"
-UPSTREAM_HASH="${2:-}"
+REFERENCE_IMPL_HASH="${2:-}"
CHANGELOG_FILE="${CHANGELOG_FILE:-CHANGELOG.md}"
RELEASE_DATE=$(date +%Y-%m-%d)
echo "Updating CHANGELOG.md for version ${VERSION} (${RELEASE_DATE})"
-if [ -n "$UPSTREAM_HASH" ]; then
- echo " Upstream SDK sync: ${UPSTREAM_HASH:0:7}"
+if [ -n "$REFERENCE_IMPL_HASH" ]; then
+ echo " Reference implementation SDK sync: ${REFERENCE_IMPL_HASH:0:7}"
fi
# Check if CHANGELOG.md exists
@@ -38,7 +38,7 @@ fi
TEMP_FILE=$(mktemp)
# Process the CHANGELOG
-awk -v version="$VERSION" -v date="$RELEASE_DATE" -v upstream_hash="$UPSTREAM_HASH" '
+awk -v version="$VERSION" -v date="$RELEASE_DATE" -v REFERENCE_IMPL_HASH="$REFERENCE_IMPL_HASH" '
BEGIN {
unreleased_found = 0
content_found = 0
@@ -65,26 +65,26 @@ links_section && repo_url == "" && /^\[[0-9]+\.[0-9]+\.[0-9]+(-java\.[0-9]+)?\]:
if (!unreleased_found) {
print "## [Unreleased]"
print ""
- if (upstream_hash != "") {
- short_hash = substr(upstream_hash, 1, 7)
- print "> **Upstream sync:** [`github/copilot-sdk@" short_hash "`](https://github.com/github/copilot-sdk/commit/" upstream_hash ")"
+ if (REFERENCE_IMPL_HASH != "") {
+ short_hash = substr(REFERENCE_IMPL_HASH, 1, 7)
+ print "> **Reference implementation sync:** [`github/copilot-sdk@" short_hash "`](https://github.com/github/copilot-sdk/commit/" REFERENCE_IMPL_HASH ")"
print ""
}
print "## [" version "] - " date
- if (upstream_hash != "") {
+ if (REFERENCE_IMPL_HASH != "") {
print ""
- print "> **Upstream sync:** [`github/copilot-sdk@" short_hash "`](https://github.com/github/copilot-sdk/commit/" upstream_hash ")"
+ print "> **Reference implementation sync:** [`github/copilot-sdk@" short_hash "`](https://github.com/github/copilot-sdk/commit/" REFERENCE_IMPL_HASH ")"
}
unreleased_found = 1
- skip_old_upstream = 1
+ skip_old_reference_impl = 1
next
}
}
-# Skip the old upstream sync line and surrounding blank lines from the previous [Unreleased] section
-skip_old_upstream && /^[[:space:]]*$/ { next }
-skip_old_upstream && /^> \*\*Upstream sync:\*\*/ { next }
-skip_old_upstream && !/^[[:space:]]*$/ && !/^> \*\*Upstream sync:\*\*/ { skip_old_upstream = 0 }
+# Skip the old Reference implementation sync line and surrounding blank lines from the previous [Unreleased] section
+skip_old_reference_impl && /^[[:space:]]*$/ { next }
+skip_old_reference_impl && /^> \*\*Reference implementation sync:\*\*/ { next }
+skip_old_reference_impl && !/^[[:space:]]*$/ && !/^> \*\*Reference implementation sync:\*\*/ { skip_old_reference_impl = 0 }
# Capture the first version link to get the previous version
links_section && first_version_link == "" && /^\[[0-9]+\.[0-9]+\.[0-9]+(-java\.[0-9]+)?\]:/ {
@@ -119,3 +119,4 @@ echo "✓ CHANGELOG.md updated successfully"
echo " - Added version ${VERSION} with date ${RELEASE_DATE}"
echo " - Created new [Unreleased] section"
echo " - Updated version comparison links"
+
diff --git a/.github/scripts/upstream-sync/merge-upstream-finish.sh b/.github/scripts/upstream-sync/merge-upstream-finish.sh
deleted file mode 100755
index 1663ef259..000000000
--- a/.github/scripts/upstream-sync/merge-upstream-finish.sh
+++ /dev/null
@@ -1,63 +0,0 @@
-#!/usr/bin/env bash
-# ──────────────────────────────────────────────────────────────
-# merge-upstream-finish.sh
-#
-# Finalises an upstream merge:
-# 1. Runs format + test + build (via format-and-test.sh)
-# 2. Updates .lastmerge to upstream HEAD
-# 3. Commits the .lastmerge update
-# 4. Pushes the branch to origin
-#
-# Usage: ./.github/scripts/upstream-sync/merge-upstream-finish.sh
-# ./.github/scripts/upstream-sync/merge-upstream-finish.sh --skip-tests
-#
-# Requires: .merge-env written by merge-upstream-start.sh
-# ──────────────────────────────────────────────────────────────
-set -euo pipefail
-
-ROOT_DIR="$(cd "$(dirname "$0")/../../.." && pwd)"
-ENV_FILE="$ROOT_DIR/.merge-env"
-
-if [[ ! -f "$ENV_FILE" ]]; then
- echo "❌ $ENV_FILE not found. Run ./.github/scripts/upstream-sync/merge-upstream-start.sh first."
- exit 1
-fi
-
-# shellcheck source=/dev/null
-source "$ENV_FILE"
-
-SKIP_TESTS=false
-if [[ "${1:-}" == "--skip-tests" ]]; then
- SKIP_TESTS=true
-fi
-
-cd "$ROOT_DIR"
-
-# ── 1. Format, test, build ───────────────────────────────────
-if $SKIP_TESTS; then
- echo "▸ Formatting only (tests skipped)…"
- mvn spotless:apply
- mvn clean package -DskipTests
-else
- echo "▸ Running format + test + build…"
- "$ROOT_DIR/.github/scripts/build/format-and-test.sh"
-fi
-
-# ── 2. Update .lastmerge ─────────────────────────────────────
-echo "▸ Updating .lastmerge…"
-NEW_COMMIT=$(cd "$UPSTREAM_DIR" && git rev-parse origin/main)
-echo "$NEW_COMMIT" > "$ROOT_DIR/.lastmerge"
-
-git add .lastmerge
-git commit -m "Update .lastmerge to $NEW_COMMIT"
-
-# ── 3. Push branch ───────────────────────────────────────────
-echo "▸ Pushing branch $BRANCH_NAME to origin…"
-git push -u origin "$BRANCH_NAME"
-
-echo ""
-echo "✅ Branch pushed. Next step:"
-echo " Create a Pull Request (base: main, head: $BRANCH_NAME)"
-echo ""
-echo " Suggested title: Merge upstream SDK changes ($(date +%Y-%m-%d))"
-echo " Don't forget to add the 'upstream-sync' label."
diff --git a/.github/skills/agentic-merge-reference-impl/SKILL.md b/.github/skills/agentic-merge-reference-impl/SKILL.md
new file mode 100644
index 000000000..43addbac4
--- /dev/null
+++ b/.github/skills/agentic-merge-reference-impl/SKILL.md
@@ -0,0 +1,7 @@
+---
+name: agentic-merge-reference-impl
+description: Merge reference implementation changes from the official Copilot SDK into this Java SDK.
+license: MIT
+---
+
+Follow instructions in the [agentic-merge-reference-impl prompt](../../prompts/agentic-merge-reference-impl.prompt.md) to merge reference implementation changes from the official Copilot SDK into this Java SDK.
diff --git a/.github/skills/agentic-merge-upstream/SKILL.md b/.github/skills/agentic-merge-upstream/SKILL.md
deleted file mode 100644
index 14301c27d..000000000
--- a/.github/skills/agentic-merge-upstream/SKILL.md
+++ /dev/null
@@ -1,7 +0,0 @@
----
-name: agentic-merge-upstream
-description: Merge upstream changes from the official Copilot SDK into this Java SDK.
-license: MIT
----
-
-Follow instructions in the [agentic-merge-upstream prompt](../../prompts/agentic-merge-upstream.prompt.md) to merge upstream changes from the official Copilot SDK into this Java SDK.
\ No newline at end of file
diff --git a/.github/templates/index.html b/.github/templates/index.html
index 9975d79b8..d273ad074 100644
--- a/.github/templates/index.html
+++ b/.github/templates/index.html
@@ -6,7 +6,7 @@
- Copilot SDK for Java — Documentation
+ GitHub Copilot SDK for Java — Documentation
@@ -15,7 +15,7 @@
-
Copilot SDK for Java
+
GitHub Copilot SDK for Java
The official SDK for building AI-powered tools with GitHub Copilot's agentic runtime.
+ ℹ️ Public Preview: This is the official Java SDK for GitHub Copilot. This repository treats the official .NET and Node.js SDKs for GitHub Copilot as reference implementations. These SDKs are all officially supported as GitHub open source projects. The Java implementation follows the backward compatibility guarantees offered by the reference implementations. While in public preview, minor breaking changes may still occur between releases.
+
+
+
+ ⚠️ Artifact versioning plan:Releases of this implementation track releases of the reference implementation. For each release of the reference implementation, there may follow a corresponding relase of this implementation with the same number as the reference implementation. Release identifiers of the reference implementation are in the form `vMaj.Min.Micro`. For example v0.1.32. The corresponding maven version for the release will be `Maj.Min.Micro-java.N`, where `Maj`, `Min` and `Micro` are the corresponding numbers for the reference impementation release, and `N` is a monotonically increasing sequence number starting with 0 for each release. See the corrseponding architectural decision record for more information in the `docs/adr` directory of the source code.
+