Skip to content

Add preamble section and preserve action to SDKs#1713

Open
MackinnonBuck wants to merge 5 commits into
mainfrom
mackinnonbuck/preamble-prompt-section
Open

Add preamble section and preserve action to SDKs#1713
MackinnonBuck wants to merge 5 commits into
mainfrom
mackinnonbuck/preamble-prompt-section

Conversation

@MackinnonBuck

Copy link
Copy Markdown
Collaborator

Why

The runtime recently reworked system prompt customization (copilot-agent-runtime#10025) to fix a bug where identity: { action: "replace" } silently deleted sibling sections (tone, tool efficiency, etc.). That fix introduced a new preamble section ID and a new preserve action, but the SDKs didn't expose either, so clients couldn't target just the identity preamble or opt a section out of a group-level remove.

What

This brings all six SDKs in line with the new runtime model:

  • New preamble section — targets just the identity preamble without touching its sibling sub-sections. The identity and tool_instructions IDs are now documented as section groups.
  • New preserve action — a no-op that protects an individually-addressable section (e.g. tone) from a group-level remove on its parent group.

Changes are applied consistently across the type/constant definitions for Node, Go, Python, .NET, and Java. Rust uses free-form section/action strings, so only its doc comments needed updating. Docs in getting-started.md and the Node/Go/.NET READMEs are updated to describe the groups and the fifth action.

Tests

Added an end-to-end should_use_replaced_preamble_section_in_response test to all six SDKs, backed by a shared replay snapshot under test/snapshots/. The test replaces the preamble section with a custom persona and asserts the persona surfaces in the assistant's reply, validating the customization flows through the full SDK -> RPC -> CLI stack.

A couple of notes for reviewers:

  • The snapshot was recorded against the real Copilot API (not hand-authored), then verified to replay cleanly. The replay proxy normalizes the system prompt to a ${system} placeholder, so the test asserts on observable assistant output rather than raw prompt bytes.
  • The Java test that asserts the exact count of section constants was bumped from 11 to 12 to account for PREAMBLE.
  • A preserve-specific E2E test was intentionally omitted: its effect lives entirely in the system-prompt bytes that the harness normalizes away, so it would carry no real signal. The constant additions are the meaningful SDK surface here.

Verified: Node/Go/Python E2E pass on replay; .NET/Java/Rust compile and format clean.

MackinnonBuck and others added 2 commits June 17, 2026 15:30
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Adds a 'should_use_replaced_preamble_section_in_response' E2E test to all
six SDKs (Node, Go, Python, .NET, Java, Rust) exercising the new 'preamble'
section ID end-to-end, with a shared replay snapshot. Updates the Java
SystemMessageSections constant-count assertion from 11 to 12.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@MackinnonBuck MackinnonBuck requested a review from a team as a code owner June 17, 2026 23:12
Copilot AI review requested due to automatic review settings June 17, 2026 23:12

Copilot AI left a comment

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.

Pull request overview

This PR updates the SDK surface area for system-prompt customization to match the runtime’s newer model by adding a dedicated preamble section ID and a preserve section override action, then validating the new section via cross-SDK E2E coverage and documentation updates.

Changes:

  • Added preamble as a first-class system message section identifier, and clarified identity / tool_instructions as section groups in constants/docs across SDKs.
  • Added the preserve override action (no-op marker used to protect a leaf section from a group-level remove) in language SDK types/enums/docs (Rust docs only, since Rust uses free-form strings).
  • Added a new E2E scenario (should_use_replaced_preamble_section_in_response) and shared replay snapshot to verify preamble replacement flows through SDK → RPC → CLI.
Show a summary per file
File Description
test/snapshots/system_message_sections/should_use_replaced_preamble_section_in_response.yaml New shared replay snapshot for the preamble-replacement persona test.
rust/tests/e2e/system_message_sections.rs Adds Rust E2E test covering preamble replacement behavior.
rust/src/types.rs Updates SectionOverride doc comments to include the new preserve action.
python/e2e/test_system_message_sections_e2e.py Adds Python E2E test covering preamble replacement behavior.
python/copilot/session.py Extends Python system-message section/action types and metadata (preamble, preserve), updates section descriptions.
nodejs/test/e2e/system_message_sections.e2e.test.ts Adds Node E2E test covering preamble replacement behavior.
nodejs/src/types.ts Extends Node system-message section/action types and metadata (preamble, preserve), updates section descriptions.
nodejs/README.md Documents preamble, section groups, and the 5th action (preserve).
java/src/test/java/com/github/copilot/SystemMessageSectionsIT.java Adds Java E2E/integration test for preamble; updates constant-count assertions.
java/src/main/java/com/github/copilot/rpc/SystemMessageSections.java Adds PREAMBLE constant and clarifies IDENTITY as a group.
java/src/main/java/com/github/copilot/rpc/SectionOverrideAction.java Adds PRESERVE enum value with Javadoc describing semantics.
go/types.go Adds SectionPreamble and SectionActionPreserve, updates SectionIdentity docs to describe group semantics.
go/README.md Documents SectionPreamble, section groups, and the 5th action (preserve).
go/internal/e2e/system_message_sections_e2e_test.go Adds Go E2E test covering preamble replacement behavior.
dotnet/test/E2E/SystemMessageSectionsE2ETests.cs Adds .NET E2E test covering preamble replacement behavior.
dotnet/src/Types.cs Adds Preamble section identifier and Preserve override action.
dotnet/README.md Documents Preamble, section groups, and the 5th action (Preserve).
docs/getting-started.md Documents preamble, section groups, and the 5th action (preserve).

Copilot's findings

  • Files reviewed: 18/18 changed files
  • Comments generated: 1

Comment thread docs/getting-started.md Outdated
@github-actions

This comment has been minimized.

Remove the unsupported 'a warning is emitted' claim from the system
message customization section so it matches the silent-fallback behavior
documented in the language READMEs.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions

This comment has been minimized.

The new preamble test docstring exceeded the 100-char limit, failing
'ruff check' in the Python SDK Tests CI job across all platforms.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions

This comment has been minimized.

@github-actions github-actions Bot left a comment

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.

Generated by SDK Consistency Review Agent for issue #1713 · sonnet46 1.4M

Comments that could not be inline-anchored

go/README.md:168

This inline parameter-description list was not updated alongside the "Available section constants" paragraph below. SectionPreamble is missing from the keys: list, and the description of SectionIdentity should note it is a section group.

Suggested update:

  - **customize**: Selectively override individual sections via `Sections` map (keys: `SectionPreamble`, `SectionIdentity` (group), `SectionTone`, `SectionToolEfficiency`, `SectionEnvironmentContext`, `SectionCodeChangeRules`, `Sec…

</details>

The SystemMessage parameter-reference table's inline section-constant
list still started at SectionIdentity. Add SectionPreamble so it matches
the dedicated 'Available section constants' list and the other SDKs.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@MackinnonBuck

Copy link
Copy Markdown
Collaborator Author

Thanks, good catch. Fixed in 077a390: added SectionPreamble to the front of the inline keys: list in the SystemMessage parameter-reference table (go/README.md line 168) so it matches the dedicated "Available section constants" paragraph and the other SDKs.

I left the group annotation out of that terse one-liner intentionally; the group semantics for SectionIdentity/SectionToolInstructions are already covered in the prose right below the constants list. Verified no other README has an analogous stale inline list.

@github-actions

Copy link
Copy Markdown
Contributor

Cross-SDK Consistency Review ✅

This PR maintains excellent feature parity across all six SDK implementations. Here's a quick breakdown:

New preamble section — all SDKs updated

SDK Addition
Node.js "preamble" added to SystemMessageSection union type and SYSTEM_MESSAGE_SECTIONS constant
Python "preamble" added to SystemMessageSection Literal and SYSTEM_MESSAGE_SECTIONS dict
Go SectionPreamble = "preamble" constant added
.NET SystemMessageSection.Preamble static property added
Java PREAMBLE = "preamble" constant added to SystemMessageSections (inherited by deprecated SystemPromptSections)
Rust Doc comments updated (free-form strings — no constants, consistent with other Rust section/action strings)

New preserve action — all SDKs updated

SDK Addition
Node.js "preserve" added to SectionOverrideAction union type
Python "preserve" added to SectionOverrideAction Literal
Go SectionActionPreserve SectionOverrideAction = "preserve" constant added
.NET SectionOverrideAction.Preserve enum value added
Java PRESERVE("preserve") enum value added
Rust Doc comments updated

E2E coverage — all SDKs have the new test

Every SDK adds should_use_replaced_preamble_section_in_response, all backed by the same shared snapshot at test/snapshots/system_message_sections/should_use_replaced_preamble_section_in_response.yaml.

Documentation

The READMEs for Node.js, Go, and .NET — which enumerate section IDs and actions — are all updated. docs/getting-started.md is updated. Python, Java, and Rust READMEs do not enumerate section IDs, so no updates were needed there.

No consistency gaps found.

Generated by SDK Consistency Review Agent for issue #1713 · sonnet46 1.6M ·

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants