fix(session): keep prompt cache prefixes stable across working directories

AN
8h ago
+337-15

Issue for this PR

Closes #1490

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

Why: prompt caching only helps when the request prefix (system message and tool definitions) is byte-identical between sessions. Working directory and date text sat at the front of the system message and in the bash tool schema, so opening the same project from a different directory (or on a different day) invalidated the cached prefix.

Root cause:

  • SystemPrompt.environment() (directory, workspace root, date) was assembled before skills and project instructions in the single system message.
  • The bash tool workdir description interpolated Instance.directory, changing the serialized tool schema per directory. (The ${directory} replacement in the description was already a no-op.)

Before -> after:

  • Environment context is passed as environment to LLM.stream and appended as a separate trailing system message after plugin transformation, so the cache markers sit before it and directory/date still reach the model. Output-budget estimation still counts it.
  • bash workdir describes its default generically; execution still resolves params.workdir || Instance.directory.

Deferred / limits:

  • No live cache-hit measurement; tests mock transport and verify stable prefixes and marker placement only.
  • Instruction source paths and skill locations still embed absolute paths, so prefixes can legitimately differ across checkouts with path-bearing instructions or skills (follow-up; review noted tests use constant instructions).
  • Unused adapter session/llm/request.ts unchanged.

Upstream-shared files (session/llm.ts, session/prompt.ts, tool/bash.ts) exist in the v1.4 baseline tree; all changes are wrapped in altimate_change upstream_fix markers. The analyzer reports nothing to check against upstream v2, so markers were audited manually.

How did you verify your code works?

  • bun test test/tool test/session test/provider/transform.test.ts test/memory/injection.test.ts test/altimate/enhance-prompt.test.ts test/acp/tool.test.ts test/branding/build-integrity.test.ts (packages/opencode, unsandboxed): 2086 pass, 0 fail, 33 skip, 45 todo.
  • bun run typecheck: clean. git diff --check: clean.
  • New tests failed before the fix and pass after. Independent Codex review: no P0/P1; one P2 (test coverage for path-bearing instructions/skills) noted above.

Screenshots / recordings

N/A

Checklist

  • I have added tests that prove my fix works
  • New and existing tests pass locally
  • I have not committed models-snapshot.ts

šŸ¤– Generated with Claude Code


[!NOTE]
Medium Risk
Changes how system messages and tool schemas are serialized for every LLM turn; behavior is well-tested but any missed caller of environment or path-bearing instructions could still break cache stability.

Overview
Fixes prompt cache invalidation when the same project is opened from a different cwd or on a new day. Directory, workspace root, and date used to live inside the reusable system-instructions prefix (and in the bash tool schema), so the byte-identical prefix providers cache on could change every session.

Session / LLM: SystemPrompt.environment() is no longer merged into the main system array in prompt.ts. It is passed as optional environment on LLM.stream and appended as a trailing system segment after plugin system transforms, so Anthropic/Bedrock cache markers stay on the stable instruction prefix while ambient <env> context still reaches the model.

Bash tool: Tool description and workdir parameter text no longer embed Instance.directory; defaults are described generically and cwd is still resolved at execute time (params.workdir || Instance.directory).

Tests: Coverage for identical system/tool prefixes across directories (including cache marker placement), prompt loop wiring of environment vs system/messages, and stable bash definitions plus runtime workdir behavior.

Reviewed by Cursor Bugbot for commit 01f4c63f20e88df7be10127cb8ff52fcdc908c43. Bugbot is set up for automated code reviews on this repo. Configure here.


Summary by cubic

Fixes prompt cache invalidation caused by working directory and date text appearing in the cached request prefix, so reusing the prefix across directories and days works as intended.

  • Passes the environment section (directory, workspace root, date) to LLM.stream separately and places it after the cached instructions: as a trailing system message for providers with explicit cache breakpoints (Anthropic, Bedrock, Alibaba) and appended to the single system message for others.
  • Extracts usesExplicitCacheBreakpoints so the split only applies where cache breakpoints are explicit; plugin-transformed instructions stay ahead of the environment.
  • Removes the instance directory from the bash tool workdir description and the no-op ${directory} substitution; execution still resolves the default directory at runtime.
  • Adds regression tests for bash tool schemas, prompt loop wiring, and Anthropic/Bedrock/OpenAI/Google request assembly.

Closes #1490.

Summary by CodeRabbit

  • Improvements
    • Working-directory and date context are now provided separately from reusable system instructions, helping keep system prompt prefixes consistent across directories.
    • Bash tool descriptions and parameter details no longer vary by working directory. Commands still run in the current directory by default, or in an explicitly selected directory.