Skip to content

Commit 6b3948d

Browse files
committed
Name the notice path for what it carries
The wrapper module added nothing the shell function did not already do. It introduced no type and narrowed no export, so a producer reaching for appendStreamRow directly was exactly as easy with it as without, and the history it documented reads better on the function itself. The name was also wrong. The path carries unknown commands, unavailable modals and provider failures, none of which happen at startup, and a name that lies to the next reader is how this constraint got lost twice.
1 parent 875143c commit 6b3948d

6 files changed

Lines changed: 21 additions & 45 deletions

File tree

src/tui-opentui/landing.test.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,8 @@ import {
1717
isLanding,
1818
paintLanding,
1919
streamRowCount,
20-
surfaceStartupNotice,
20+
surfaceSystemNotice,
2121
} from "./shell"
22-
import { flushStartupNotices } from "./startup-notices"
2322
import { makeOperatorQuestion, openOperatorOverlay } from "./overlays"
2423
import {
2524
LANDING_HINTS,
@@ -519,7 +518,7 @@ describe("landing screen", () => {
519518

520519
const mcpError =
521520
"mcp github did not connect (ECONNREFUSED) — its tools are unavailable; /mcp for detail"
522-
surfaceStartupNotice(shell, mcpError)
521+
surfaceSystemNotice(shell, mcpError)
523522
await settle(h)
524523

525524
// The mountain stays; the notice strip carries the wording.
@@ -567,7 +566,7 @@ describe("landing screen", () => {
567566
expect(before.length).toBeGreaterThan(0)
568567

569568
const summary = "plugins: 3 skills missing: brand-identity, style, philosophy"
570-
flushStartupNotices(shell, [summary])
569+
surfaceSystemNotice(shell, summary)
571570
await settle(h)
572571

573572
expect(isLanding(shell)).toBe(true)
@@ -592,7 +591,7 @@ describe("landing screen", () => {
592591
})
593592
try {
594593
await settle(h)
595-
flushStartupNotices(shell, ["plugins: 1 skill missing: style"])
594+
surfaceSystemNotice(shell, "plugins: 1 skill missing: style")
596595
appendStreamRow(shell, { role: "user", text: "first prompt" })
597596
await settle(h)
598597

src/tui-opentui/product-host.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ import {
4747
setPaletteOnCommand,
4848
setMcpNeedsAuth,
4949
setStatusFlash,
50-
surfaceStartupNotice,
50+
surfaceSystemNotice,
5151
type AppShell,
5252
type ItemDescription,
5353
type OverlaySelection,
@@ -348,7 +348,7 @@ export async function mountProductHost(
348348
// before the first turn (CL-5618).
349349
const widthReport = checkWidthContract(renderer.widthMethod)
350350
if (!widthReport.agrees) {
351-
surfaceStartupNotice(shell, widthContractNotice(widthReport))
351+
surfaceSystemNotice(shell, widthContractNotice(widthReport))
352352
}
353353

354354
const port = createLiveSessionPort({
@@ -465,9 +465,9 @@ export async function mountProductHost(
465465
if (notice === null) return
466466
if (notice.kind === "row") {
467467
// MCP load failures and hook failures must not wipe the landing mark.
468-
// surfaceStartupNotice keeps the mountain while the notice strip carries
468+
// surfaceSystemNotice keeps the mountain while the notice strip carries
469469
// the wording, then flushes a durable row once the session starts.
470-
surfaceStartupNotice(shell, notice.text)
470+
surfaceSystemNotice(shell, notice.text)
471471
return
472472
}
473473
setStatusFlash(shell, notice.text, { ttlMs: RUNTIME_FLASH_MS })

src/tui-opentui/runner-host.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ import {
3636
setPromptModelLabel,
3737
setPromptWorkspace,
3838
setShellExitHandler,
39-
surfaceStartupNotice,
39+
surfaceSystemNotice,
4040
} from "./shell.js"
4141
import type { CostSummary } from "../cost/cost-summary.js"
4242
import { watchGitBranch, type FetchBranch } from "./workspace-watch.js"
@@ -326,7 +326,7 @@ export async function mountRunnerHost(deps: RunnerHostDeps): Promise<RunnerHost>
326326
const surfaceDeps: CommandSurfaceDeps = {
327327
...(deps.surfaces ?? {}),
328328
...(host.openModels !== undefined ? { openModels: host.openModels } : {}),
329-
notify: (text) => surfaceStartupNotice(host.shell, text),
329+
notify: (text) => surfaceSystemNotice(host.shell, text),
330330
}
331331

332332
const refreshModels = (

src/tui-opentui/shell.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2118,8 +2118,13 @@ function evictedRowsNotice(evicted: number): string {
21182118
* mounted the wording rides the notice strip and the row is held for flush
21192119
* once a real session row ends the landing; after that it is a normal system
21202120
* row.
2121+
*
2122+
* Every producer of a system-class row belongs here rather than at
2123+
* `appendStreamRow`. CL-5618 fixed the MCP and hook producers one at a time
2124+
* and the plugin producer kept the defect, which is what per-call-site rules
2125+
* buy you. Reaching for `appendStreamRow` directly is the bug.
21212126
*/
2122-
export function surfaceStartupNotice(shell: AppShell, text: string): void {
2127+
export function surfaceSystemNotice(shell: AppShell, text: string): void {
21232128
if (isLanding(shell)) {
21242129
const bag = internals.get(shell)
21252130
if (bag !== undefined) {

src/tui-opentui/startup-notices.ts

Lines changed: 0 additions & 28 deletions
This file was deleted.

src/tui/runner.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -149,9 +149,8 @@ import {
149149
setPromptRecognitionSource,
150150
setSentMessageHistory,
151151
setShellRunState,
152-
surfaceStartupNotice,
152+
surfaceSystemNotice,
153153
} from "../tui-opentui/shell.js";
154-
import { flushStartupNotices } from "../tui-opentui/startup-notices.js";
155154
import {
156155
classifyAgentSendFailure,
157156
shouldSettleUiAfterSendFailure,
@@ -436,7 +435,7 @@ export async function runTUI(initialConfig: Config): Promise<number> {
436435
// have no result channel back to an operator action, unlike verify/add-path/
437436
// trust-grant. A log-only summary is invisible — nobody watches
438437
// ~/.corbits/logs/corbits.log — so these are queued and handed to
439-
// `flushStartupNotices` once the shell mounts.
438+
// the shell one at a time once it mounts.
440439
const startupPluginNotices: string[] = [];
441440
const discoveryNotice = formatPluginWarningsSummary(pluginLoadDiag.warnings);
442441
if (discoveryNotice !== undefined) startupPluginNotices.push(discoveryNotice);
@@ -1847,7 +1846,7 @@ export async function runTUI(initialConfig: Config): Promise<number> {
18471846
// the whole composition. Once a session row has ended the landing this is an
18481847
// ordinary system row, so there is no second behaviour to reason about.
18491848
const systemNotice = (text: string): void => {
1850-
surfaceStartupNotice(host.shell, text);
1849+
surfaceSystemNotice(host.shell, text);
18511850
};
18521851

18531852
/** Settle the shell after a rejected send so the run does not look live. */
@@ -2378,7 +2377,8 @@ export async function runTUI(initialConfig: Config): Promise<number> {
23782377

23792378
// Surface fire-and-forget startup plugin diagnostics now that there is a
23802379
// shell to say them to (queued above, before `host` existed).
2381-
flushStartupNotices(host.shell, startupPluginNotices);
2380+
for (const notice of startupPluginNotices)
2381+
surfaceSystemNotice(host.shell, notice);
23822382

23832383
await host.waitUntilExit();
23842384
// Quitting mid-stream is an abnormal end for the in-flight cycle: nothing

0 commit comments

Comments
 (0)