Rendered from specs/F34-command-surface.md — edit it there, not here.
F34 — Command Surface & Onboarding
Overview
The extension contributes over thirty commands across preview, validation, generation, refactoring and analysis. Each was specified with its own surface, and the aggregate has outgrown the affordances that carry it: the editor title bar shows six icons plus an overflow for a schema file, the only way to discover most features is to scroll the Command Palette, there are no default keybindings, and a first-time user who installs from the Marketplace is shown nothing at all.
This spec is about the surface rather than any single feature: an onboarding walkthrough, keybindings for the few commands used often enough to deserve one, and a grouped menu so the title bar stays legible as the command set grows.
User Stories
- As a new user, I want the extension to show me what it does after install, so I don't have to read a README to find the preview.
- As a daily user, I want a keystroke for Preview and Validate rather than re-typing them in the palette.
- As someone with a schema open, I want the extension's commands grouped under one menu instead of six icons competing with the editor's own.
Functional Requirements
Onboarding
- F34-FR-01 The extension MUST contribute a walkthrough shown on first install, with steps covering: previewing a schema, binding and validating a data file, generating a schema from existing data, and (as the differentiator most users don't know exists) authenticating a private schema.
- F34-FR-02 Each step MUST have a completion condition tied to an observable event — the command having been run, or the relevant context key becoming true — so the walkthrough reflects what the user has actually done rather than only what they have clicked.
- F34-FR-03 Each step MUST link to the corresponding docs-site page, so the walkthrough is an index into the documentation rather than a second copy of it.
Keybindings
- F34-FR-04 The extension MUST contribute default keybindings for the two highest-frequency commands: Preview (
Ctrl+K V/Cmd+K V, matching the editor's own Markdown preview chord) and Validate This File (Ctrl+K J/Cmd+K J). - F34-FR-05 Every keybinding MUST carry a
whenclause restricting it to the file kind it applies to (a schema for Preview, a supported data file for Validate), so the chord is free for other extensions everywhere else.
Menus
- F34-FR-06 The editor title bar MUST show at most three of the extension's icons for any file kind; every other command MUST live under a single JSON Schema submenu in the title-bar overflow.
- F34-FR-07 The submenu MUST group commands by purpose — view, generate, transform, analyse — using menu groups, so its order is stable and meaningful rather than registration-ordered.
- F34-FR-08 The editor context menu MUST offer the commands that apply to the file under the cursor, so the feature set is reachable without the palette for users who work from the right-click menu.
- F34-FR-09 Command Palette visibility MUST remain filtered by file kind, so a command that cannot apply to the active editor is not offered there.
Detection
F34-FR-10 A file MUST be recognised as a schema when it declares a JSON Schema meta-
$schema(F01-FR-02), or when its name matches a conventional schema pattern (*.schema.json,*.schema.yaml,*.schema.yml,schema.json), or when its root object declares schema-defining keywords ($defs/definitionswithproperties, orpropertieswithtype: "object") and it is not itself bound to a schema. This is what makes the toolbar, linter and quick fixes available on a new schema file before it has a$schemaline — which is exactly when the "insert$schema" fix (F17) is most useful.F34-FR-11 The structural heuristic MUST NOT classify a data file as a schema: a document whose
$schemapoints at a non-meta schema (an inline binding, F10) MUST always be treated as data, regardless of its shape or name.F34-FR-13 The two heuristics F34-FR-10 adds beyond the
$schemadeclaration MUST be controllable by ajsonschema.schemaDetectionsetting with three values:Value Recognises a schema by auto(default)meta- $schema, file name, and structurefilenamemeta- $schemaand file namestrictmeta- $schemaonlyA meta-
$schemadeclaration MUST be honoured at every level — the setting narrows the heuristics, never the declaration — and F34-FR-11's precedence MUST hold unchanged at every level.The setting exists because F34-FR-10 is the one change in this feature that can take a working affordance away. A file with no
$schemathat happens to carrypropertiesalongsidetype: "object"— an OpenAPI fragment, a form definition, a UI component descriptor — is data to its author but matches the structural heuristic, and reclassifying it as a schema removes the Validate / Generate Schema / Coverage toolbar actions it used to offer. Recovery would otherwise mean editing the document to add a$schemaline, which is a change to the user's data to work around our inference.filenameexists as a distinct level rather than folding intostrictbecause the two heuristics are not equally risky:*.schema.jsonis a naming convention a file only matches on purpose, while the structural test is an inference about content. A user bitten by the latter should not have to give up the former.
Notifications
- F34-FR-12 A success confirmation that offers no action — "schema bundled", "credentials saved", "report copied", "cache refreshed" — MUST be shown as a transient status-bar message, not a notification toast. Toasts are for a choice the user must make or an outcome they must notice; a confirmation that the thing they just asked for happened is neither, and stacking them trains users to dismiss the ones that matter. Messages carrying an action button, warnings and errors are unaffected.
Non-Functional Requirements
- F34-NFR-01 The detection predicate MUST remain pure and unit-tested, and its extension MUST NOT regress any existing F01/F10 classification: the meta-
$schemaand inline-binding rules keep precedence over both new signals. - F34-NFR-02 Menu and keybinding contributions are manifest-only and MUST be asserted by the manifest tests, since they have no runtime code path.
- F34-NFR-03 The walkthrough MUST NOT run code on activation; it is a declarative contribution and MUST NOT add to activation cost (S03).
Out of Scope
- Localisation of command titles and walkthrough copy.
- A custom side-bar view container. The outline (F31) reuses the editor's own Outline view precisely to avoid one.
- Rebinding or hiding commands per user — that is the editor's own keybindings/menus customisation, not something to reimplement.
Acceptance Criteria
- A fresh install shows the walkthrough, and its preview step completes after the preview command runs.
Ctrl+K Vopens the preview on a schema file and does nothing on an unrelated file.- A schema file's title bar shows three icons; the remaining commands are under one JSON Schema submenu.
- A new
order.schema.jsonwithpropertiesbut no$schemaline shows the schema toolbar and offers the insert-$schemafix. - A data file whose
$schemapoints at./order.schema.jsonis never treated as a schema, whatever its name.
Relation to Existing Specs
- F01 (preview) owns the meta-
$schemadetection this spec widens (F34-FR-10) while preserving its precedence. - F10 (inline binding) supplies the rule that keeps bound data files data.
- F17 (linting) is the main beneficiary of earlier detection.
- S06 (accessibility) — every added affordance is keyboard-reachable and labelled, as all contributions here are native VS Code surfaces.
History
2026-09-02 — Initial specification.
2026-09-02 — Added F34-FR-12: action-less success confirmations move from toasts to a transient status-bar message. The extension had grown past ninety notification calls; the ones that only say "done" are the noise.
2026-09-09 — Added F34-FR-13, the
jsonschema.schemaDetectionsetting. A pre-release review of this branch asked what could break an existing install; the answer was that nothing changes a default, removes a command or moves an engine floor — except F34-FR-10, which is the one change that can take a working affordance away. An unbound file carryingpropertiesalongsidetype: "object"is reclassified from data to schema and loses Validate This File, Generate Schema from This File and Report Schema Coverage, with no way back other than editing the document to add a$schemaline — a change to the user's data to work around our inference.Three levels rather than a boolean, because the two heuristics are not equally risky:
*.schema.jsonis a convention a file matches on purpose, while the structural test is an inference about content.filenamelets someone bitten by the second keep the first.The unrecognised-value fallback is
auto, not the narrowest level: a typo in the setting should not silently strip the toolbar off every schema in a workspace whose files are still being written.
Requirement traceability
Status of each requirement in specs/traceability.json. Test coverage is auto-discovered from [ID] tags in test titles and is not listed here.
| Requirement | Status | Implementation | Note |
|---|---|---|---|
F34-FR-01 | implemented | package.json, media/walkthrough-preview.md | walkthrough with completion events and docs links; asserted by the manifest tests |
F34-FR-02 | implemented | package.json, media/walkthrough-preview.md | walkthrough with completion events and docs links; asserted by the manifest tests |
F34-FR-03 | implemented | package.json, media/walkthrough-preview.md | walkthrough with completion events and docs links; asserted by the manifest tests |
F34-FR-04 | implemented | package.json | keybindings with when clauses; asserted |
F34-FR-05 | implemented | package.json | keybindings with when clauses; asserted |
F34-FR-06 | implemented | package.json | submenu grouping and palette filtering; asserted |
F34-FR-07 | implemented | package.json | submenu grouping and palette filtering; asserted |
F34-FR-08 | implemented | package.json | submenu grouping and palette filtering; asserted |
F34-FR-09 | implemented | package.json | submenu grouping and palette filtering; asserted |
F34-FR-10 | implemented | src/PreviewWebPanel.ts | name + structural detection, with the inline-binding rule keeping precedence; unit-tested |
F34-FR-11 | implemented | src/PreviewWebPanel.ts | name + structural detection, with the inline-binding rule keeping precedence; unit-tested |
F34-FR-12 | implemented | src/notify.ts | confirm() → transient status-bar message; a test greps src/ for surviving action-less toasts |
F34-FR-13 | implemented | src/settings.ts, src/PreviewWebPanel.ts, package.json | |
F34-NFR-01 | implemented | src/PreviewWebPanel.ts | pure predicate; no F01/F10 regression |
F34-NFR-02 | implemented | package.json | manifest-only contributions asserted by tests |
F34-NFR-03 | implemented | package.json | declarative walkthrough; no activation cost |
Documented in
Documentation sections tagged spec:F34 (or one of its requirement ids) — 479 of ~683 expected words (70%). The expectation comes from this spec's evaluated complexity of 17.1 (16 documentable requirements — 13 FR, 3 NFR — weighted by kind and by each definition's length).