Say so when the Planner is unavailable #294
- MA
Messages manually addressing @chopin while the Planner is off now receive a local notice: “Chopin is off on this server. Your message went to the room only.” The notice appears beside the accepted message and disappears on reload.
Integration preserves the current rich-text composer, existing unavailable status, addressing controls and accessible input locators. The final request-id follow-up was folded into the patch; obsolete textarea/placeholder revisions were omitted.
Local checks, types, 142 chat unit tests and all three mention browser tests pass, including notice placement and reload behavior. Final rebased head `9109615a` passed hosted validation, E2E, and container checks.
<details><summary>Original proposal and historical textarea screenshot</summary>
## Why When the hosted Planner is off (`AGENT=off`), the composer still said "Use @chopin to ask Chopin", and a message addressed to @chopin posted and then nothing happened, with no hint that nobody would reply.
## What changed - Composer placeholder is "Message the room" when the Planner is unavailable (unchanged when enabled). The @ picker and the routing cue already hid the Planner in that state. - A message that still addresses @chopin (typed by hand) gets a muted system row under it: "Chopin is off on this server. Your message went to the room only." The notice is local and not persisted: a courtesy hint only, keyed by the send's `requestId` (the room entry id), gone on reload. The server has no Planner-specific signal for these messages. - Pure helpers `addressesPlanner` and `withNoticesAfter` in `references.ts`, with unit tests. - E2E: new test in `chat-mentions.e2e.ts`. Specs now assert the exact placeholder for their server (`PLANNER_PLACEHOLDER` for AGENT=on / agent-forced tests, `ROOM_PLACEHOLDER` for planner-off), both from `e2e/composer.ts`.
## Screenshots Before (left) / after (right), message sent with the Planner off:

## Testing - `bun test apps/web/src/chat`: pass - `bun run ci`, `bun run types`: pass - Browser E2E via PR CI.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
</details>
chopinmentionedlast month on GitHub
chopinsubscribedlast month on GitHub
- MA
**Review:** Changes needed (small, mostly tests)
Checked on a NO_PLANNER server (desktop 1440 and phone 390): placeholder reads "Message the room", `@` opens no picker, no routing cue, and a hand-typed `@chopin` message gets the muted row under it. Looks right and matches other system rows (same `data-chat-system` row, tertiary text, wraps cleanly on phone).
**Planner ON is unchanged.** `placeholder` is `agent ? <old string> : ...`, the notice branch is gated on `!agent`, and `chatSendPayload` already routes to the room when `agent` is false. `withNoticesAfter` returns `entries` untouched when no notices exist.
**No conflict with the server notice.** "The agent is not running..." (`chat/service.ts` ~653, ~781) only fires for a `to: "planner"` send or an accepted decision/comment while `config.agent` is false. The web client never sends `to: "planner"` when `agent` is false, so the two cannot stack for a composer message. Different triggers, so not redundant.
**Findings** 1. `e2e/composer.ts:2` and the ~8 spec files: the either/or regex is sound for passing, but it masks regressions. No test now asserts the exact placeholder with the Planner ON, and only the new test asserts "Message the room". If the flag inverted, every spec would still pass. Suggest: `harness.e2e.ts` (AGENT=on) use `"Use @chopin to ask Chopin"` exactly, and `smoke.e2e.ts` "chat uses one room-message composer when the planner is off" use `"Message the room"`. Note the `scriptPlanner` tests in smoke force `agent: true` in `/api/session` (smoke.e2e.ts:76) on an AGENT=off server, so they should pin the "Use @chopin" string. Keep the regex only where a spec truly runs against either state. 2. `chat.tsx:339-348`: the notice depends on the ack (`sent.id`). On the legacy no-ack path (`sendAcknowledgements` false, line 331) there is no notice at all, silently. The server's room entry id equals `payload.requestId` (service.ts ~627), so key `unanswered` by `payload.requestId` and set it right after `wire.ask` resolves or even at send time. `withNoticesAfter` already skips unknown ids, so it only appears once the entry exists. That removes the ack dependency and the `sent.id` dereference. As written the ack dependency is acceptable only if legacy servers are out of scope; say so or switch. 3. Known limits worth stating in the PR (not blockers): the row is local state, so it disappears on reload (verified: after reload the message shows with no notice, and the `@chopin` is stripped from display so it looks like any plain message) and other members never see it. Acceptable for a courtesy hint. 4. Wording: "so nobody will reply" is slightly cold and leans on "this server". Consider "Chopin is off on this server. Your message went to the room only." which also says where the message went. Optional. 5. The system row uses the sign-in arrow icon (existing `SystemEntry`), which is odd for this notice but consistent with the other system rows. Not this PR's job.
No unrelated changes; tabs/`let` conventions followed; no raw sizes or colours added. Unit tests cover the two helpers. I did not run the browser e2e suite.
chopinmentionedlast month on GitHub
chopinsubscribedlast month on GitHub
- MA
Addressed review: exact placeholders per server (PLANNER_PLACEHOLDER vs ROOM_PLACEHOLDER; no shared regex remains), notice keyed by requestId with no ack dependency, new wording, body states the notice is local and not persisted. Retook the crop.
lavaman131referenced this in [Design] Rebuild the workflow run card with assistant-ui Elements #307last month on GitHub
lavaman131referenced this in [Design] Replace the composer @ mention picker with assistant-ui mentions #308last month on GitHub
lavaman131referenced this in [Design] Conversation controls with assistant-ui Elements: message queue, stopped run, error state #309last month on GitHub
lavaman131referenced this in [Design] Research and references with assistant-ui Elements #310last month on GitHub
lavaman131referenced this in [Design] Decisions display with assistant-ui Elements (option list, question flow) #311last month on GitHub
lavaman131referenced 01c1998a7b1clast month on GitHub
lavaman131referenced 7f6cfcdc3abelast month on GitHub
MaggieAppletonhead-ref-force-pushed 480405126f5alast month on GitHub
MaggieAppletonhead-ref-force-pushed 170e6bc0272flast month on GitHub
MaggieAppletonhead-ref-force-pushed b1f29be7630flast month on GitHub
MaggieAppletonhead-ref-force-pushed 07b753029ad3last month on GitHub
MaggieAppletonhead-ref-force-pushed 70fa0a8161f1last month on GitHub
- MA
Commit pushed: [`5019e6b`](https://github.com/githubnext/chopin/commit/5019e6bad773238256adfbe6ef7bf69ba4cb236f)
> Generated by [PR CI fixer](https://github.com/githubnext/chopin/actions/runs/37627133303) · gpt54 · 245.6 AIC · ⌖ 9.38 AIC · ⊞ 16.4K
- MA
Root cause: the failed E2E assertion expected the raw source string `@chopin are you there?`, but chat transcript rendering intentionally projects mentions for display typography, so the visible row is `Chopin are you there?`.
Changed file: `e2e/chat-mentions.e2e.ts`.
Verification: `bun test apps/web/src/chat/model.test.ts apps/web/src/chat/references.test.ts` passes locally. `bun run e2e` could not be rerun end-to-end in this runner because Docker is unavailable, and `bun run fix` / `bun run ci` both stop earlier on a `dprint` plugin download proxy failure. The `[ci-fix]` commit is queued for guarded application; GitHub CI still needs to confirm it.
[babysit] head=70fa0a8161f1cb8bcdbcf6506ddf59d4eaa072aa
> [!WARNING] > <details> > <summary>Firewall blocked 1 domain</summary> > > The following domain was blocked by the firewall during workflow execution: > > - `releaseassets.githubusercontent.com` > > To allow these domains, add them to the `network.allowed` list in your workflow frontmatter: > > ```yaml > network: > allowed: > - defaults > - "releaseassets.githubusercontent.com" > ``` > > See [Network Configuration](https://github.github.com/gh-aw/reference/network/) for more information. > > </details>
> Generated by [PR CI fixer](https://github.com/githubnext/chopin/actions/runs/37627133303) · gpt54 · 245.6 AIC · ⌖ 9.38 AIC · ⊞ 16.4K · [◷](https://github.com/search?q=repo%3Agithubnext%2Fchopin+%22gh-aw-workflow-call-id%3A+githubnext%2Fchopin%2Fpr-ci-fix%22&type=issues)
<!-- gh-aw-agentic-workflow: PR CI fixer, engine: codex, model: gpt-5.4, id: 37627133303, workflow_id: pr-ci-fix, run: https://github.com/githubnext/chopin/actions/runs/37627133303 --> <!-- gh-aw-workflow-call-id: githubnext/chopin/pr-ci-fix -->
- MA
@copilot I previously shipped a PR that restyles the composer to be much nicer, and as part of that I know there was a state that showed Chopin not being available as part of the composer. Can you make sure that this PR aligns with that intended design and doesn't regress the design or display of the composer?
Copilotmentionedlast month on GitHub
Copilotsubscribedlast month on GitHub
MaggieAppletoncopilot-work-startedlast month on GitHub
> @copilot I previously shipped a PR that restyles the composer to be much nicer, and as part of that I know there was a state that showed Chopin not being available as part of the composer. Can you mak...
Verified against the attached screenshot and current composer code: the unavailable state keeps the existing composer structure, field styling, sizing, focus treatment, and send action; only the placeholder changes to “Message the room.” The muted notice remains a transcript system row under the sent message, matching the screenshot. No composer CSS or layout changes are needed, so I made no code changes.
Copilotmentionedlast month on GitHub
Copilotsubscribedlast month on GitHub
MaggieAppletoncopilot-work-finishedlast month on GitHub
MaggieAppletonhead-ref-force-pushed 77c0bed9f262last month on GitHub
MaggieAppletonhead-ref-force-pushed 9109615a448elast month on GitHub
MaggieAppletonmerged 70c71e0a3757last month on GitHub
MaggieAppletonhead-ref-deletedlast month on GitHub