fix(coding-agent): move the dynamic env block to the end of the Step system prompt - #169
Closed
jasonkneen wants to merge 1 commit into
Closed
jasonkneen wants to merge 1 commit into
jasonkneen wants to merge 1 commit into
Conversation
Invariant: the cacheable prompt prefix must be byte-identical across turns and sessions, with dynamic content appended after it. Cause: buildStepSystemPromptAppendix placed the <env> block (cwd, platform, date, git branch, uncommitted-change count, operating mode) as the 4th section, ahead of nearly all static contract text. The appendix rebuilds on every tool-set change (agent-session.ts _rebuildSystemPrompt via setActiveToolsByName/_refreshToolRegistry and on extension resource changes), so after any tool discovery the env block's near-front position busted the provider prompt cache for the whole system prompt, and made the prompt differ across sessions/days. Fix: push buildEnvironmentSection(...) as the last entry of the sections array instead of the 4th, so all static sections precede it unconditionally. core/system-prompt.ts already appends its own "Current working directory" line at the very end of the composed prompt in both branches, so no change was needed there. Wording is unchanged; only ordering moved. Tests: added to step-system-prompt.test.ts — one asserting the env block (and its trailing sentences) is the last thing in the prompt and that the static prefix is identical across differing cwd/platform/date contexts, and one pinning a sha256 hash of the static prefix for a fixed tool set (comment notes intentional prompt edits must update the hash). Verified both fail against the pre-fix ordering and pass after.
There was a problem hiding this comment.
Copilot review overview
🟢 Approval recommended
The scoped change has regression coverage, and the remaining comment is a non-blocking documentation nit.
Review effort: Lite
Findings: 1
Open (1)
What changed in this PR
Moves the dynamic environment block to the end of the Step system prompt appendix to improve prompt-cache stability.
Changes:
- Relocates environment-section generation after static and tool-specific sections.
- Adds regression tests for ordering and static-prefix hashing.
| File | Summary | Review note |
|---|---|---|
packages/coding-agent/test/step-system-prompt.test.ts |
Verifies environment ordering and prefix stability. | — |
packages/coding-agent/src/step/system-prompt.ts |
Moves environment prompt generation to the appendix tail. | Nit (2 votes): Qualify the cache-stability comment for fixed tool sets and other dynamic inputs. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Comment on lines
+403
to
+405
| // every static section above, means the static prefix stays byte-identical | ||
| // across rebuilds and sessions so provider prompt caches on that prefix | ||
| // survive; only this trailing block busts on rebuild. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Problem
packages/coding-agent/src/step/system-prompt.tsbuilt the Step appendix's<env>block (working directory, platform, today's date, git branch,"Uncommitted changes: N", operating mode —
buildEnvironmentSection,~L95-115) and placed it as the 4th entry of the
sectionsarray (~L305),right after the three opening contract lines and ahead of nearly all the
static contract text (Priorities, Communication, Security, Destructive
actions, Workflow, Code conventions, Git, Tool usage, plus all the
conditional sections).
The appendix is rebuilt on every tool-set change
(
core/agent-session.ts_rebuildSystemPrompt, called fromsetActiveToolsByName/_refreshToolRegistryat ~L1083 and on extensionresource changes at ~L2620), and each rebuild re-reads git status (cached
with a 5s TTL, but still time- and edit-state-dependent). Because the env
block sat near the front, any rebuild — including ones triggered mid-session
by newly discovered deferred tools — changed content that appears very early
in the composed system prompt, which busts the provider's prompt cache for
the entire prompt on every rebuild, and guarantees the prompt differs
across sessions/days.
Fix
Moved the
buildEnvironmentSection(...)call from position 4 in thesectionsarray to the very last entry, pushed after the tool-selectionrules block, immediately before
sections.join("\n\n"). No wording waschanged — the env block's own trailing sentences ("The working directory
above is also the default base...", "(see Current working directory
below)") still read correctly because the env block is now directly before
core/system-prompt.ts's trailingCurrent working directory: ...line,which was already the very last line of the fully composed prompt in both
the
customPromptand default branches ofbuildSystemPrompt. No changeswere needed in
core/system-prompt.ts— it already appendsCurrent working directoryat the end of the assembled prompt in both branches, soit does not put date/cwd early.
Everything else in the appendix — all static contract sections, tool rules,
and conditional sections — is now byte-identical across rebuilds and
sessions for the same tool set, and only the trailing env block (plus core's
final cwd line) varies.
Test
Added to
packages/coding-agent/test/step-system-prompt.test.ts:date/cwd/git state": builds the appendix twice with the same tool set but
differing
cwd/platform/date, asserts the env block's trailingsentence is the very last thing in the prompt, and asserts the text
before the first
<env>tag (the static prefix) is identical between thetwo builds.
sha256 of the static prefix for a fixed tool set and asserts it against a
pinned value, with a comment that intentional prompt-wording changes must
recompute and update the hash.
Verified both regression tests fail against the pre-fix code (env block was
mid-prompt, so the "trailing sentence" assertion failed and the pinned hash
did not match) and pass after the fix. Ran the pre-fix source via a
byte-for-byte revert of only
system-prompt.ts(test file kept as thefixed version) to confirm:
Full suite after the fix: 24/24 pass in
step-system-prompt.test.ts.No existing test pinned the old env-block position (all existing assertions
use
toContain, not index/order checks), so no other tests needed updating.Risk / behaviour change
Purely a section-ordering change inside
buildStepSystemPromptAppendix; theenv block's content and wording are unchanged, so model-visible semantics
are unchanged (same facts, same sentences). The only observable difference
is where
<env>...</env>appears in the prompt text — now at the very end,immediately before the harness's own trailing
Current working directory:line, instead of near the top. This is the intended fix: it makes the
prompt's static prefix cacheable by providers that support prompt caching,
which should reduce cost/latency for sessions with tool-set churn (e.g.
deferred MCP tool discovery) without changing any instruction the model
receives.
https://claude.ai/code/session_01GUdnnHEaDThHUATSwXBpV9