Skip to content

[bug] continuity.reason is computed, phrased for a human, returned on every session open, and displayed nowhere #697

Description

@serge-ivo

resolveSessionContinuity goes to deliberate trouble to produce a sentence a human can read, the API returns it on every session open, and no surface shows it.

What is computed

lib/coding-session-continuity.ts:59-63 — the field exists specifically to be shown:

/**
 * Why, phrased so a reply can use it verbatim after "started a fresh conversation — ".
 * Empty-ish reasons are not allowed: an unexplained fresh start is the bug report #408 predicts.
 */
reason: string;

Every branch fills it: "you asked for a clean slate", "the previous session on this repo ran a different engine", "the previous session never got its engine running", "the previous conversation on this repo was last touched 3 days ago". describeAge (:78) exists solely to round that age to a unit that reads as a fact.

What is returned

Observed 2026-08-17, POST /v1/instances/bd43f4de-…/coding/sessions:

{
  "session": { "id": "csess_7d077f96-…", "status": "active", },
  "runnerConnected": true,
  "resumed": true,
  "continuity": {
    "mode": "resume",
    "resumeFrom": "csess_21b8d1b9-…",
    "reason": "the previous conversation on this repo was last touched 11 hours ago"
  }
}

What is displayed

Nothing. grep -c continuity agents/coder/web/src/CodingTab.tsx0. That file is the only CodingTab — the console imports it (store/console/src/lib/surfaces.tsx:2, import { CodingTab } from "@proagentstore/coder-web"), so this is not a two-implementations problem. The MCP side does not surface it either (#696).

So the platform knows whether it kept your conversation, knows why, has phrased it for you, and says nothing.

Why it matters here specifically

This is the sentence that makes seamlessness legible. Without it the two outcomes are indistinguishable at a glance: a resumed session and a cold one both open on a blank pane. The owner hit exactly this on 2026-08-17 — the work had been preserved and the resume worked, and the reasonable conclusion from the screen was that everything was lost.

It is also the honest counterpart to #695. Removing "your session ended, start a new one" leaves a gap; this is what belongs in it. The two should ship together, or the first one alone just makes the platform quieter rather than clearer.

Fix

Render continuity.reason on open, prefixed by mode:

  • resume → "Picking up where you left off — the previous conversation on this repo was last touched 11 hours ago."
  • fresh → "Started a fresh conversation — {reason}." (the doc comment already phrases the field for exactly this concatenation)

openNotice already exists as state in CodingTab.tsx:128 and is already used for the reused-engine notice (reusedEngineNotice, #549), so there is a place to put it and a precedent for the shape.

Show it once per open, not persistently. A fresh outcome deserves more prominence than a resume one — resume is the expected case and should be reassuring rather than loud, while an unexpected cold start is the thing the user needs to know before they start talking to an agent that has forgotten them.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingfrontendFrontend / UI work

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions