Skip to content

Report Quick Start situations as typed keys, not as English sentences - #879

Merged
Tomasz Naumowicz (tnaum-ms) merged 2 commits into
dev/tnaum/quickstart-improvementsfrom
dev/tnaum/quickstart-typed-messages
Aug 10, 2026
Merged

Report Quick Start situations as typed keys, not as English sentences#879
Tomasz Naumowicz (tnaum-ms) merged 2 commits into
dev/tnaum/quickstart-improvementsfrom
dev/tnaum/quickstart-typed-messages

Conversation

@tnaum-ms

Copy link
Copy Markdown
Collaborator

Fixes #865. Milestone 0.10.0.

Stacked on #876 (dev/tnaum/quickstart-improvements), so review that one first — the diff here is against it.

Problem

QuickStartService emitted user-facing text as plain strings on StageEvent.message / StageEvent.error and QuickStartStatus.errorMessage. The webview rendered them verbatim and the Connections view used errorMessage as the tree row description. That put copy in the service layer, and made every new message another chance to forget l10n.t.

Five of them had already forgotten:

'Checking Docker…'
'Pulling the official image…'
'Creating container…'
'Starting container…'
'Waiting for DocumentDB to accept connections…'

Raw English, no l10n.t, never extracted.

They were also dead. The webview labels the stage checklist from its own stageLabels() map and only reads event.message on terminal events. Those five strings were never rendered — untranslated text nobody could report, because nobody could see it. They are deleted rather than localized.

What replaces them

export interface QuickStartMessage {
    readonly key: QuickStartMessageKey;
    readonly port?: number;
    readonly environment?: DockerHostEnvironment;
    /** Raw daemon / driver text, rendered verbatim beside the localized copy. */
    readonly detail?: string;
}

A situation, plus the data needed to phrase it. detail is the one field that is never translated, because it is evidence, not copy — and giving it its own field is what stops a daemon string being concatenated into a sentence a translator owns.

Fourteen keys cover the surface. The shape follows the DockerFailureKind / DockerGuidanceKey precedent this feature already uses.

Three decisions worth reviewing

One formatter, not one map per surface. The issue proposed moving copy into the webview's lookup map and into LocalQuickStartItem. That is two copies of the same sentence, which can only drift — the exact failure #876 just fixed for the transitional rows. Instead there is a single formatQuickStartMessage() in quickStartMessages.ts, imported by both. It stays free of vscode imports (the webview bundle takes it too) and builds every string inside the function, so it resolves against whichever l10n bundle the calling surface loaded — which also keeps it clear of #864.

StageEvent.error is gone. It duplicated message at every call site but two, where it differed only by being undefined on abort — and the webview then fell back to message anyway, producing the same sentence. One field plus status says the same thing.

QuickStartStatus.errorMessageerror?: QuickStartMessage. The tree formats it at render time, so a Quick Start error row and the setup panel cannot describe the same failure differently.

Tests

Assertions moved from sentences to keys, which is what #764 asks for:

expect(events.at(-1)?.message).toEqual({ key: 'portInUse', port: QUICK_START_PORT });

The M5 regression (the daemon's Bind for 127.0.0.1:10260 failed… text must not reach the user) is now structural rather than asserted: a keyed message has nowhere to put that text. The test pins detail is absent instead of grepping a rendered string.

Localization impact

Net one key removed, one added. 'A setup operation is already in progress.' collapsed into setupAlreadyInProgress, and a detail-free 'Docker became unavailable during setup.' variant was added for the case where no daemon text is available.

Validation

  • npm run l10n
  • npm run prettier-fix
  • npm run lint — clean
  • npx jest --no-coverage — 217 suites, 3,477 tests
  • npm run build — clean

Fixes #865.

`QuickStartService` emitted user-facing text on `StageEvent.message` /
`StageEvent.error` and `QuickStartStatus.errorMessage`, so the service layer
owned copy, and every new message was one more chance to forget `l10n.t`. Five
of them had already forgotten: the stage payloads `'Checking Docker…'`,
`'Pulling the official image…'`, `'Creating container…'`, `'Starting container…'`
and `'Waiting for DocumentDB to accept connections…'` were raw English.

They were also dead. The webview labels the checklist from its own
`stageLabels()` map and only reads `message` on terminal events, so those five
strings were never rendered — untranslated text that nobody could have reported,
because nobody could see it. They are gone rather than localized.

What remains is a `QuickStartMessage`: a key, plus the data needed to phrase it
(`port`, `environment`) and a `detail` field carrying raw daemon or driver text.
`detail` is the one thing never translated, because it is evidence rather than
copy — and keeping it in its own field is what stops a daemon string being
concatenated into a sentence a translator owns.

`StageEvent.error` is gone too. It duplicated `message` at every call site
except two, where it differed only by being undefined on abort, which the
webview then fell back out of. One field and `status` say the same thing.

The wording lives in one shared `formatQuickStartMessage`, not one map per
surface. Two copies of the same sentence in the tree and the webview could only
drift, which is the failure this repo just fixed for the transitional rows.

Tests now assert keys instead of sentences, which is what #764 asks for. The M5
regression — the daemon's "Bind for …" text must not reach the user — is now
structural: a keyed message has nowhere to put it, and the test pins that
`detail` is absent rather than grepping the rendered string.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Refactors Local Quick Start messaging so the service emits typed “situation” keys (QuickStartMessage) instead of user-facing English strings, and centralizes localization/formatting in a shared formatter used by both the webview and the Connections tree.

Changes:

  • Introduces QuickStartMessageKey/QuickStartMessage and replaces StageEvent.message: string / QuickStartStatus.errorMessage: string with typed messages (message?: QuickStartMessage, error?: QuickStartMessage).
  • Adds formatQuickStartMessage() (quickStartMessages.ts) and updates the webview and tree surfaces to format messages at render time.
  • Updates Quick Start tests to assert on message keys/payloads instead of localized sentences, and adjusts l10n bundle entries.

Reviewed changes

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

Show a summary per file
File Description
src/webviews/documentdb/localQuickStart/localQuickStartRouter.ts Sends QuickStartStatus.error to the webview instead of errorMessage.
src/webviews/documentdb/localQuickStart/LocalQuickStart.tsx Formats terminal stage messages via formatQuickStartMessage(); removes event.error usage.
src/tree/connections-view/LocalQuickStart/LocalQuickStartItem.ts Formats tree error-row description from status.error via the shared formatter.
src/services/localQuickStart/quickStartTypes.ts Defines QuickStartMessageKey/QuickStartMessage; updates StageEvent and status types to use typed messages.
src/services/localQuickStart/QuickStartService.ts Emits typed message keys/payloads throughout provisioning/resume/status paths; removes intermediate-stage free-text.
src/services/localQuickStart/QuickStartService.test.ts Updates assertions to use keys/payloads; uses formatter for readiness-timeout wording checks.
src/services/localQuickStart/QuickStartProvisionDurability.test.ts Moves port-in-use assertions from string matching to keyed messages and pins detail absence.
src/services/localQuickStart/quickStartMessages.ts New shared formatter: key → localized string (+ optional detail).
l10n/bundle.l10n.json Updates extracted localization strings for the new/removed message wording.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/services/localQuickStart/QuickStartService.ts Outdated
Comment thread src/services/localQuickStart/quickStartMessages.ts
…nd detail

Two findings from the #879 review, both real.

A second readiness timeout in `resumeReadiness` fell through to
`unexpectedFailure` and put the raw `ReadinessTimeoutError` text on screen — the
one thing this PR set out to stop. It now reports `readinessTimeout` carrying the
host environment, so a repeat timeout gets the same dev-container port-routing
explanation as the first one; `stillInitializing` stays for a cancelled wait and
`unexpectedFailure` for a genuine finalize error.

`formatQuickStartMessage` trimmed `detail` and then returned it through `??`, so
a whitespace-only detail rendered as an empty message. Detail now collapses to
undefined when it carries no evidence, and `unexpectedFailure` keeps a localized
sentence around the raw text instead of replacing the copy with it — which is
what the field was documented to do.

Covered by a new test for the formatter: every key renders something, raw driver
text never stands alone, and whitespace-only detail can never blank the message.
@tnaum-ms
Tomasz Naumowicz (tnaum-ms) merged commit 0f78cc7 into dev/tnaum/quickstart-improvements Aug 10, 2026
2 checks passed
@tnaum-ms
Tomasz Naumowicz (tnaum-ms) deleted the dev/tnaum/quickstart-typed-messages branch August 10, 2026 07:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants