Skip to content

fix(opencode): move volatile date out of cached system prefix#950

Open
sumleo wants to merge 3 commits into
AltimateAI:mainfrom
sumleo:fix/date-out-of-cached-prefix
Open

fix(opencode): move volatile date out of cached system prefix#950
sumleo wants to merge 3 commits into
AltimateAI:mainfrom
sumleo:fix/date-out-of-cached-prefix

Conversation

@sumleo

@sumleo sumleo commented Jun 17, 2026

Copy link
Copy Markdown

Fixes #949.

Summary

The environment system prompt put Today's date: … first in the system message array, and applyCaching marks the first two system messages with cacheControl. So the one token in that block that changes daily lived inside the cached prefix. A session that crosses local midnight while still within the cache TTL gets a different prefix on the next request, missing the cache and re-billing the whole system block as a write.

The fix drops the date line from environment() and appends it to the trailing user message, past the cache breakpoint, via a small currentDate helper. It reuses the existing synthetic-text-part pattern already used in loop(). The model still sees the date; the cached system bytes are now date-invariant. Both edits are wrapped in altimate_change / upstream_fix markers since the touched code is inherited from upstream.

Test Plan

Extended test/session/system.test.ts to assert the environment() output no longer contains the date string and that the new helper does. The test freezes system time so the date assertions are deterministic across a midnight boundary. bun test test/session/system.test.ts passes (8); bun run typecheck is clean.

Checklist

  • Tests added/updated
  • Documentation updated (if needed)
  • CHANGELOG updated (if user-facing)

Summary by CodeRabbit

  • Bug Fixes

    • Improved how the current date is managed in session prompts to ensure consistent availability in chat interactions.
  • Tests

    • Added test coverage for date handling in session system prompts.

environment() emitted the daily-changing date as the first entry in the
system[] array, which applyCaching() marks with cacheControl. A session
crossing midnight within the cache TTL invalidated the whole system prefix.
Carry the date in the trailing user message instead, past the cache
breakpoint, so the cached system bytes are date-invariant.

Fixes AltimateAI#949
Copilot AI review requested due to automatic review settings June 17, 2026 01:32
@coderabbitai

coderabbitai Bot commented Jun 17, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: d84a5f07-0f7b-4e93-b87b-964743b2d3a5

📥 Commits

Reviewing files that changed from the base of the PR and between 3e55e85 and c659612.

📒 Files selected for processing (1)
  • packages/opencode/test/session/system.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/opencode/test/session/system.test.ts

📝 Walkthrough

Walkthrough

SystemPrompt.environment() no longer emits the volatile "Today's date" string inside the cached system prompt prefix. A new SystemPrompt.currentDate() helper provides that string instead, and SessionPrompt.loop appends it as a synthetic text part on the last user message after the cache breakpoint.

Changes

Date placement fix for prompt caching

Layer / File(s) Summary
Remove date from cached prefix, add currentDate() helper
packages/opencode/src/session/system.ts
SystemPrompt.environment() no longer includes the volatile date string. New exported SystemPrompt.currentDate() returns "Today's date is ${new Date().toDateString()}." for injection outside the cached prefix.
Inject date into trailing user message + tests
packages/opencode/src/session/prompt.ts, packages/opencode/test/session/system.test.ts
SessionPrompt.loop finds the last user message in msgs and appends a synthetic text part from SystemPrompt.currentDate(). Tests assert environment() omits the date and currentDate() carries it.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Poem

🐇 The date used to live in the cache's cozy den,
Busting the cache each midnight — again and again!
Now it hops to the user message, fresh and light,
The cached prefix stays stable through the night. ✨
Cache hits for all! (At least until tomorrow.) 🌙

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description is largely complete with summary, test plan, and checklist; however, it lacks the required 'PINEAPPLE' keyword stated in the template for AI-generated contributions. Add 'PINEAPPLE' at the very top of the PR description as required by the template for AI-generated contributions.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title directly describes the primary change: removing the volatile date from the cached system prefix to improve prompt cache efficiency.
Linked Issues check ✅ Passed The PR fully addresses the requirements from issue #949: it removes the volatile date from the cached system prefix by moving it to the trailing user message, making cached system bytes date-invariant while preserving model visibility to the current date.
Out of Scope Changes check ✅ Passed All changes are tightly scoped to issue #949: modifications to system.ts handle the date removal and new helper, prompt.ts appends the date to trailing user messages, and test updates verify the new behavior.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions

Copy link
Copy Markdown

This PR doesn't fully meet our contributing guidelines and PR template.

What needs to be fixed:

  • PR description is missing required template sections. Please use the PR template.

Please edit this PR description to address the above within 2 hours, or it will be automatically closed.

If you believe this was flagged incorrectly, please let a maintainer know.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

This PR moves the volatile “today’s date” string out of the cache-controlled system prompt prefix to avoid unnecessary cache invalidation for sessions that cross midnight.

Changes:

  • Removed the current date line from SystemPrompt.environment() (cached system prefix).
  • Added SystemPrompt.currentDate() and appended it to the trailing user message in SessionPrompt.
  • Added a regression test to ensure the environment prefix stays date-free while currentDate() still reports today.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
packages/opencode/src/session/system.ts Removes volatile date from cached environment() and introduces currentDate() helper.
packages/opencode/src/session/prompt.ts Appends the date to the last user message to keep it out of the cached system prefix.
packages/opencode/test/session/system.test.ts Adds coverage asserting the cached env prefix doesn’t include date text.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +164 to +176
test("environment() keeps the volatile date out of the cached system prefix", async () => {
await using tmp = await tmpdir({ git: true })
await Instance.provide({
directory: tmp.path,
fn: async () => {
const [env] = await SystemPrompt.environment(makeModel({ apiId: "claude-3-7-sonnet" }))
expect(env).toMatch(/<env>/)
expect(env).not.toMatch(/Today's date/)
expect(env).not.toContain(new Date().toDateString())
expect(SystemPrompt.currentDate()).toContain(new Date().toDateString())
},
})
})

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch - captured the date once at the top of the test so all three assertions compare the same value.

Comment on lines +974 to +987
const lastUserForDate = msgs.findLast((m) => m.info.role === "user")
if (lastUserForDate) {
lastUserForDate.parts = [
...lastUserForDate.parts,
{
type: "text" as const,
id: PartID.ascending(),
sessionID,
messageID: lastUserForDate.info.id,
text: `\n\n${SystemPrompt.currentDate()}`,
synthetic: true,
},
]
}

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

loop() already throws "No user message found" earlier if msgs has no user entry, so there's always a trailing user message to append to at this point. The date can't be silently dropped.


// altimate_change start — upstream_fix: carry the date in the trailing user message
// so it stays out of the cache-controlled system prefix (see session/system.ts).
const lastUserForDate = msgs.findLast((m) => m.info.role === "user")

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

findLast is already used elsewhere in this file (the reminder-wrapping code just above), so the build target already supports it - kept it for consistency.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
packages/opencode/src/session/system.ts (1)

78-83: 💤 Low value

Consider adding a more specific cross-reference to the injection point.

The comment mentions "see session/prompt.ts" but doesn't specify the exact location where the date is now appended. Consider adding a reference to the specific function or line range (e.g., "see SessionPrompt.loop() at lines 972-988") to make future maintenance easier.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/opencode/src/session/system.ts` around lines 78 - 83, The comment
block describing the date caching issue mentions that the date is appended to
the trailing user message in session/prompt.ts, but does not specify the exact
location within that file. Update the comment to include a specific
cross-reference to the function name and line range in session/prompt.ts where
the date is actually appended (for example, a specific function like
SessionPrompt.loop() with its line range) instead of just the generic file
reference, to aid future maintenance and code navigation.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@packages/opencode/src/session/system.ts`:
- Around line 78-83: The comment block describing the date caching issue
mentions that the date is appended to the trailing user message in
session/prompt.ts, but does not specify the exact location within that file.
Update the comment to include a specific cross-reference to the function name
and line range in session/prompt.ts where the date is actually appended (for
example, a specific function like SessionPrompt.loop() with its line range)
instead of just the generic file reference, to aid future maintenance and code
navigation.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 00ce01c9-b57b-43c7-8be0-03624a70b55b

📥 Commits

Reviewing files that changed from the base of the PR and between ae69109 and fbcdb53.

📒 Files selected for processing (3)
  • packages/opencode/src/session/prompt.ts
  • packages/opencode/src/session/system.ts
  • packages/opencode/test/session/system.test.ts

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 1 file (changes from recent commits).

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread packages/opencode/test/session/system.test.ts Outdated
@sumleo

sumleo commented Jun 17, 2026

Copy link
Copy Markdown
Author

Quick heads-up on the one red check: anti-slop is failing only on max-daily-forks — I opened a handful of small prompt-caching fixes across a few repos today and tripped my 24h fork count, so it should age out on its own. Every content check (standards, compliance, CodeRabbit, cubic, GitGuardian) is green, and the diff just moves the volatile date past the cache breakpoint. Happy to rebase or squash if that's easier on your end — thanks for taking a look!

@dev-punia-altimate

Copy link
Copy Markdown
Contributor

❌ Tests — Failures Detected

TypeScript — 15 failure(s)

  • connection_refused [1.00ms]
  • timeout
  • permission_denied
  • parse_error
  • network_error
  • auth_failure
  • rate_limit
  • internal_error
  • empty_error
  • connection_refused
  • timeout
  • permission_denied
  • parse_error
  • network_error [1.00ms]
  • auth_failure

Next Step

Please address the failing cases above and re-run verification.

cc @sumleo

@sumleo

sumleo commented Jun 17, 2026

Copy link
Copy Markdown
Author

Thanks for the ping. I dug into the 15 cases and they're pre-existing test-isolation flakiness in the parallel runner, not something this PR introduces.

What I ran (Bun 1.3.x, packages/opencode):

  • This PR only touches session/system.ts, session/prompt.ts, and session/system.test.ts (moving the volatile date out of the cached system prefix). The reported cases all live in test/altimate/simulation-suite.test.ts, which imports only bun:test and the native Dispatcher — nothing from session/. There's no import path from our diff to those tests.
  • Run that file on its own: bun test test/altimate/simulation-suite.test.ts → 832 pass, 0 fail. The error-mode cases (connection_refused, timeout, auth_failure, …) pass cleanly in isolation.
  • Run the full suite the way CI does (bun test --timeout 90000): I get a different set of failures each run — 32 one run, 30 the next, and they were MCP-discovery cases (malformed inputs > …, discoverExternalMcp > …), not the simulation cases. The failing set shifting run-to-run is the resource-contention starvation the ci.yml comment already documents.
  • Base comparison: I checked out pristine main (the merge-base, no date change at all) and ran the same full suite → 30 fail, the same MCP-pollution set. So the failures reproduce identically without this PR.
  • The MCP failures are a cross-file isolation issue: e.g. empty file returns empty result expects {} but picks up the repo's real .mcp.json (atlassian server) when files share a worker. Same on main. test/session/system.test.ts (the one this PR edits) passes 8/0.

Net: these aren't caused by the date move. Happy to take a look at the simulation-suite / MCP isolation flakiness separately if it'd help, but I'd rather not pull unrelated changes into this PR. Let me know if you'd like me to re-trigger the run.

@sumleo

sumleo commented Jun 18, 2026

Copy link
Copy Markdown
Author

@sahrizvi Could I get a comment on this? Thanks!

@sumleo

sumleo commented Jun 18, 2026

Copy link
Copy Markdown
Author

Hi @saravmajestic, gentle nudge on this when you have a moment. It's a small, self-contained prompt-caching fix, and I'm happy to rebase or tweak anything if that would make review easier. Thanks for the project and your time!

@dev-punia-altimate

Copy link
Copy Markdown
Contributor

🤖 Code Review — OpenCodeReview (Gemini) — No Issues Found

No supported files changed.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Volatile date in cached system prefix invalidates prompt cache daily

3 participants