﻿# The query path never fits a conversation to the model's context window

- **Status**: Todo
- **Kind**: Feature
- **Authors**: jp
- **Date**: 2026-09-18
- **Label**: domain=conversation
- **Label**: domain=llm
- **Label**: package=jp_cli
- **Label**: package=jp_llm
- **Label**: type=enhancement

`jp query` builds a `Thread` from the full conversation stream and hands it to
the provider.
Nothing between the stream and the wire checks it against
`ModelDetails::context_window`.

`jp_llm::window::truncate_to_fit` exists and documents itself as the entry point
for "fitting a conversation into a model's context window".
It has two production call sites: `jp_llm::title` for title generation and
`jp_cli::cmd::query::tool::inquiry` for inquiry sub-requests.
Neither is the query path.
It was introduced for inquiries in #441 and reused for titles in #895; nothing
removed it from `query`, it was never there.

## What it costs

The common case is recoverable and clearly signalled: the provider returns
`ContextWindowExceeded` and the user runs `jp conversation compact`.
That is why this is a gap rather than a defect.

Two cases are worse:

- A provider that clamps instead of rejecting produces no signal at all.
  See T-0de0hry: Cerebras shortens completions as the window fills and the user
  is told nothing.
- RFD D50 (automatic compaction) delegates the single-turn overflow case back to
  this path: "A single turn that overflows on its own remains the domain of
  hard-fail and truncation."
  That backstop does not exist, so D50's own reasoning has a hole in it.

## Scope worth settling

Whether dropping the oldest events is the right shape here.
`truncate_to_fit` drops from the front, which on a long session removes the
original request and the early exploration while keeping the most recent tool
output.
The harness study in T-0n0nwz3 keeps the preamble and a verbatim recent window
and compacts only the middle, preferring to stub bulky tool observations before
dropping anything.
JP's compaction policies (RFD 064) already express that shape, so a query-path
backstop could reuse them rather than the blunt drop.

The related decision is ordering.
With an automatic compaction trigger in place this is a true backstop that
rarely runs; without one it is the only mechanism.
Landing them in either order works.
Landing neither leaves the provider error as the only guard.

Findings and the rest of the proposals: T-0n0nwz3.
