Skip to content

ask behavior doc sync

Kazushi Kamegawa edited this page Sep 19, 2026 · 1 revision

Sync the README and the Panel Welcome Text with the /ask Grounding Behavior

Date: 2026-09-19 Tracking: Issue #249

日本語

Summary

PR #233 and PR #237 changed how chat grounding works:

  • Plain chat (no slash command) attaches pinned snippets and attached files as grounding context automatically, and sets contextualResources.webContext.isWebEnabled = false for that turn.
  • /ask changed from "the command that attaches context" into an optional guard that refuses to send when no pinned snippet or attached file is present.

This plan starts from an audit of whether that change reached the documentation. Most of it had: the README "Chatting and Searching" and /ask sections, the command table, docs/plan.md §4.1/§4.3, docs/adr.md, docs/tasks.md, docs/test_plan.md (T-CHAT-05, T-CHAT-09), docs/e2e_checklist.md (E2E-33), and the /ask help text in src/router/commandRouter.ts all describe the current behavior.

Four places did not, two of them user-facing panel strings:

  1. README.md intro — "Plain text starts a Microsoft 365 Copilot chat without automatically attaching ContextRelay search context", with no mention that pinned snippets and attached files are attached.
  2. README.md Features, "Plain Copilot chat" — no mention of the automatic grounding or of /ask's guard role.
  3. src/webview/chatRenderer.ts — the welcome block rebuilt by clear() still read "Pin snippets and run /ask to process pinned snippets or #file mentions with Microsoft 365 Copilot", contradicting the initial HTML in ChatViewProvider.getHtmlForWebview(). Running /clear replaced the correct hint with the stale one.
  4. src/webview/slashMenu.ts — the /ask entry read "Ask Microsoft 365 Copilot using pinned snippets in the panel", which does not convey the guard.

README_ja.md also did not exist, although the repository is MIT-licensed and keeps Japanese translations of its other documents.

Design decisions

  • One definition for the welcome block, not two copies kept in sync. The welcome paragraph existed as two independent implementations — static HTML built by the extension host and DOM nodes built by the webview — which is why the #233/#237 update landed on only one side. The text moves into src/chatWelcomeText.ts, a module with no vscode import, and both sides render from it. src/sourcePresentation.ts already establishes that a vscode-free module under src/ can be imported by the extension host and by the webview bundle.
  • Segments, not a single string. Both renderings need inline <code> spans, but one produces HTML and the other DOM nodes. The shared text is a list of { text, code? } segments; the host escapes and wraps them, the webview creates text and <code> nodes. Neither side uses innerHTML with this text.
  • The extension host wording wins, with one addition. Of the two copies, the host version describes the current behavior and is what users see first, so it becomes the shared text. The webview copy's "combine source commands like /mail /onedrive" tip is real (the router accepts multiple source commands) and is kept, so no information is lost.
  • README_ja.md is a full translation, not a summary. Same heading structure, tables, and code blocks as README.md, so the two can be reviewed side by side. README.md stays the source of truth. SECURITY.md and LICENSE are never translated.
  • No behavior change. Text and documentation only: no settings, request payloads, or control flow are touched.

Implementation

  • src/chatWelcomeText.ts (new): WelcomeTextSegment, CHAT_WELCOME_HEADING, CHAT_WELCOME_INTRO, CHAT_WELCOME_COMMANDS_HINT, CHAT_WELCOME_GROUNDING_HINT, and CHAT_WELCOME_HINT_FONT_SIZE.
  • src/panel/chatViewProvider.ts: module-level escapeHtml() and renderWelcomeParagraph() build the welcome block in getHtmlForWebview() from the shared segments.
  • src/webview/chatRenderer.ts: clear() builds the block through a new private buildWelcomeParagraph() from the same segments.
  • src/webview/slashMenu.ts: the /ask description becomes "Ask Microsoft 365 Copilot, but only when pinned snippets or attached files are present", consistent with the help text in commandRouter.ts.
  • README.md: intro and the "Plain Copilot chat" bullet aligned with the current behavior; link to README_ja.md.
  • README_ja.md (new): full Japanese translation, cross-linked back to README.md.
  • docs/adr.md: 2026-09-19 entry for the single welcome-text definition and the Japanese README.
  • docs/plan.md: Appendix C describing the documentation set and where the panel's own user-facing text lives.
  • docs/tasks.md: work log entry.

Validation

npm run lint
npm run compile
npm test
npm run security:check

src/test/suite/chatRenderer.test.ts gains two cases on top of the existing domTestUtils harness, which loads the production panel HTML from getHtmlForWebview():

  • the block rebuilt by clear() must match the block in the shipped panel HTML — heading, paragraph text, font sizes, and inline code — which is the regression that shipped;
  • the welcome text must state that pinned context is attached automatically.

The rendered welcome HTML was also dumped from getHtmlForWebview() and inspected directly. Result: 389 passing, 0 failing, 0 vulnerabilities.

Clone this wiki locally