Accept (and ignore) static engine declaration keys in the external-engine schema - #14936
Open
gordonwoodhull wants to merge 2 commits into
Open
gordonwoodhull wants to merge 2 commits into
gordonwoodhull wants to merge 2 commits into
Conversation
Collaborator
✅ Snyk checks have passed. No issues have been found so far.
💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse. |
gordonwoodhull
added a commit
to gordonwoodhull/quarto-cli
that referenced
this pull request
Sep 23, 2026
The external-engine schema (contributes: engines entries in extension manifests) was closed around a single required path key. Add four optional keys -- name, claims, file-extensions, claims-files (with an optional processor on claims-files entries) -- that Quarto 1 accepts and ignores, so extensions can declare them for Quarto 2's static engine resolution without breaking Quarto 1 validation. No Quarto 1 behavior change: engine loading and execution still key off path alone.
gordonwoodhull
force-pushed
the
external-engine-static-declarations
branch
from
September 23, 2026 13:40
e528b49 to
c57d2a4
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Loosens the
external-engineschema (contributes: enginesentries in extension manifests), which was closed around a single requiredpathkey, to accept four new optional keys:name: engine name (e.g.julia)claims: languages the engine claims — either an array of language names (shorthand for a primary claim on each) or a map from language name to a claim spec (boolean | number | primary | interop | fallback | { kind, priority, whenClass }, with a specialfallbackkey for otherwise-unclaimed languages)file-extensions: file extensions the engine can handle (e.g..jl)claims-files: files the engine claims, by extension — each entry may also name aprocessor(a bare name likespin, or{ name, language?, comment? }like{ name: percent, language: julia }), the content processor that sniffs and converts matching filesQuarto 1 accepts and ignores these keys. This is pure forward-compatibility: they are reserved for Quarto 2, which resolves engines statically from these declarations without loading the engine module — including claiming files by content (percent/spin/ipynb scripts) via the
processordeclarations, which Quarto 2 runs natively. There is intentionally no Quarto 1 behavior change — engine loading and execution still key offpathalone.Why accept-and-ignore rather than honoring
claims:in Quarto 1?Quarto 1 already has engine claiming, and its semantics are deliberately conservative: the jupyter engine claims
juliaso that the old default of preferring jupyter over the julia engine is preserved (src/execute/jupyter/jupyter.ts:113-117):If Quarto 1 started honoring extension-declared
claims:, a document with{julia}cells would flip from jupyter to an installed external julia engine — exactly the behavior change that comment guards against. So these keys are validated (malformed values are still rejected) but inert in Quarto 1.Similarly,
file-extensions:here is a per-engine declaration for Quarto 2's resolution; it deliberately does not interact with Quarto 1's globaljupyter.notebookExtensionsgate.There is no problem with continuing to check the values at runtime in Quarto 1, because Quarto 1 is already running TS. It's only a concern for Quarto 2 so that it doesn't have to start up Deno in order to process Pass-1.
Consumer
PumasAI/quarto-julia-engine#15 — the Julia engine extension declares
name,claims, andfile-extensionsin its_extension.ymlso Quarto 2 can route{julia}cells and.jlfiles to it. Without this change, Quarto 1 rejects that manifest at validation time, so the extension cannot ship the declarations unconditionally. Theprocessorkey onclaims-filesentries anticipates the next declaration the same engine (and built-ins) will need: content-based claiming and conversion of percent/spin/ipynb scripts.Empirical before/after
Rendering a document with
engine: juliausing that manifest:Before (current schema):
After: render succeeds; the Julia engine executes the cell (
1 + 1→<pre><code>2</code></pre>in the output HTML). The declarations pass through into project metadata but are otherwise ignored.Changes
src/resources/schema/definitions.yml: type the four new keys; newexternal-engine-language-claimdefinition for claim specs. Every key's description states that Quarto 1 accepts and ignores it.dev-call build-artifacts(json-schemas.json,schema-types.ts, zod types, yaml-intelligence resources,vs-code.mjs).processorforms (bare name, map, map withcomment).Tests:
unit/schema-validation/schema-files.test.tsandschema-schema.test.tspass (8 passed, 0 failed), including the new fixtures; empirical render as above.Known generator limitation (left as-is): the JSON-schema output for
claims' object form dropsadditionalProperties(emits an untyped object); the validator, TS types, and zod types all handle it correctly. It's a generated IDE artifact — the validator is what enforces.