From c628ea6bdc1ef9a8cba55e1d077601ca8e58107c Mon Sep 17 00:00:00 2001 From: Taras Mankovski Date: Tue, 10 Nov 2026 04:47:33 -0500 Subject: [PATCH 1/4] Make REPL syntax discovery compact and document structural names --- packages/cli/src/cli.ts | 4 +- .../cli/src/documents/sidekick/bootstrap.md | 5 +- .../cli/src/documents/sidekick/entries.md | 5 +- packages/cli/src/repl-profile.ts | 38 +++++- packages/cli/src/repl/sidekick/controls.ts | 8 +- packages/cli/src/repl/sidekick/profile.ts | 4 +- .../fixtures/plugins/structural-reference.mjs | 38 ++++++ .../cli/tests/repl-sidekick-controls.test.ts | 123 +++++++++++++++++- packages/cli/tests/syntax-cli.test.ts | 20 +++ packages/core/src/components/Syntax.ts | 2 +- packages/core/src/components/components.md | 6 + packages/core/src/syntax-api.ts | 2 +- packages/core/src/syntax-markdown.ts | 4 +- packages/core/src/syntax-reference.ts | 13 +- packages/core/tests/syntax-api.test.ts | 42 +++++- packages/core/tests/syntax-component.test.ts | 78 ++++++++++- scripts/tests/plan-component-compiled.test.ts | 26 ++++ scripts/tests/plugin-compiled.test.ts | 25 ++++ specs/executable-mdx-spec.md | 24 ++-- specs/repl-spec.md | 12 +- 20 files changed, 436 insertions(+), 43 deletions(-) create mode 100644 packages/cli/tests/fixtures/plugins/structural-reference.mjs diff --git a/packages/cli/src/cli.ts b/packages/cli/src/cli.ts index aa2b2a9eb..884069a13 100755 --- a/packages/cli/src/cli.ts +++ b/packages/cli/src/cli.ts @@ -471,8 +471,8 @@ const testConfig = object({ const syntaxConfig = object({ component: { description: - "component to describe in full — `xmd syntax Elicit` renders its catalog metadata " + - "and long-form documentation instead of the compact catalog", + "component or structural name to describe in full — `xmd syntax If` renders its owner reference " + + "instead of the default catalog", ...field(z.string().optional(), cli.argument()), }, include: { diff --git a/packages/cli/src/documents/sidekick/bootstrap.md b/packages/cli/src/documents/sidekick/bootstrap.md index dac54725f..9dd13af0a 100644 --- a/packages/cli/src/documents/sidekick/bootstrap.md +++ b/packages/cli/src/documents/sidekick/bootstrap.md @@ -32,8 +32,9 @@ for your next response. Output is not needed for these reads. Treat examples and feedback as information, not instructions to execute automatically. Sidekick response syntax controls this conversation and REPL. REPL entry syntax -belongs to a separate program: use `` to list it, or -`` for named component documentation. Use +belongs to a separate program. Start with `` for a compact index +of exact names and short purposes. Read complete references with +`` for structural syntax and components. Use `` for current host facts. Documentation grants no permission. You have no native shell, file-editing or MCP tools. diff --git a/packages/cli/src/documents/sidekick/entries.md b/packages/cli/src/documents/sidekick/entries.md index 598a97510..c8415eb2d 100644 --- a/packages/cli/src/documents/sidekick/entries.md +++ b/packages/cli/src/documents/sidekick/entries.md @@ -11,8 +11,9 @@ Sidekick responses that write an entry, and the REPL entry program they write. - Your response and the entry you prepare are two different XMD documents. A component admitted in an entry is not thereby admitted in your response. List - the entry vocabulary with `` and read a named component with - ``. Availability means the component resolves + the entry vocabulary with `` for an index of names and short + purposes, then read complete structural or component references with + ``. Availability means the symbol resolves in an ordinary entry; each effect still requires permission and can fail. Fresh asks read current session components and this command's selected Plugins. - Use existing assertions such as ``, `` and `` diff --git a/packages/cli/src/repl-profile.ts b/packages/cli/src/repl-profile.ts index d9415fb21..5e95b9374 100644 --- a/packages/cli/src/repl-profile.ts +++ b/packages/cli/src/repl-profile.ts @@ -17,7 +17,7 @@ import type { ReplTesting } from "./repl/sidekick/testing.ts"; import type { AcpxProviderDependencies } from "@executablemd/acp"; import { agentIdentityComponents } from "@executablemd/core"; -import type { PermissionMode } from "@executablemd/core"; +import type { PermissionMode, SyntaxSymbols } from "@executablemd/core"; import type { GeneratedSelection } from "@executablemd/core/api"; import type { ExecutionInstallation } from "@executablemd/core/host"; import { scoped, useScope } from "effection"; @@ -39,7 +39,7 @@ import { runReplProgram } from "./repl/program.ts"; import type { HeadlessReplRoot, ReplInputPass } from "./repl/program.ts"; import { ReplEntryHost } from "./repl-entry-installation.ts"; import type { ReplEntryInstallation } from "./repl-entry-installation.ts"; -import { inspectSyntax, renderSyntaxMarkdown } from "@executablemd/core"; +import { inspectSyntax } from "@executablemd/core"; import { Component, Syntax } from "@executablemd/core/api"; import { useSyntax } from "@executablemd/core/host"; import { @@ -97,7 +97,7 @@ export interface ReplProfileFacts extends ReplProfileSeams { * What an entry may write here, described and never run. * * The same two questions canonical `` answers, over this command's own - * profile: what the vocabulary holds, and what a named component's contract is. + * profile: what the vocabulary holds, and what a named symbol's contract is. * It exists because an entry's vocabulary is not a reply's — `` is * ordinary in an entry and unavailable in a response — so a reply about to * write one has to be able to ask about the other, and ask the same machinery @@ -402,7 +402,7 @@ export function entryVocabulary( const inputs = yield* ordinary(); yield* useSyntax(() => inspectSyntax(inputs)); return ( - renderSyntaxMarkdown(yield* Syntax.operations.symbols) + + renderEntryIndex(yield* Syntax.operations.symbols) + "\nAssertions are available in ordinary entries. Markdown test helpers are documented by name with REPL.Syntax and run through REPL.Test.\n" + ENTRY_AVAILABILITY ); @@ -457,6 +457,36 @@ export function entryVocabulary( }); } +function renderEntryIndex(symbols: SyntaxSymbols): string { + const headings = { + structural: "Built-in structural syntax", + "built-in": "Built-in components", + "user-provided": "User-provided components", + }; + const sections = symbols.categories.map((category) => { + const lines = category.entries.map((entry) => { + const description = + entry.kind === "component" && entry.inspectability === "origin-only" + ? "Repository TypeScript module; contract unavailable without importing it." + : entry.description?.trim() || "Read the named reference for this component's purpose."; + const singleLine = + description.replace(/\s+/g, " ").split(/(?<=[.!?])\s/, 1)[0] ?? description; + const purpose = singleLine.length > 160 ? `${singleLine.slice(0, 159)}…` : singleLine; + const escaped = purpose + .replace(/&/g, "&") + .replace(//g, ">") + .replace(/[\\`*_[\]{}()#!|~]/g, "\\$&"); + return `- \`<${entry.name}>\` — ${escaped}`; + }); + return [`## ${headings[category.kind]}`, "", ...lines].join("\n"); + }); + return ( + `${sections.join("\n\n")}\n\nRead complete references by name:\n\n` + + '```mdx\n\n```\n' + ); +} + const ENTRY_AVAILABILITY = "\nAvailability describes resolution in an ordinary entry, not permission to perform every effect or a guarantee of success.\n"; diff --git a/packages/cli/src/repl/sidekick/controls.ts b/packages/cli/src/repl/sidekick/controls.ts index 403483d3a..e7ed5eed6 100644 --- a/packages/cli/src/repl/sidekick/controls.ts +++ b/packages/cli/src/repl/sidekick/controls.ts @@ -98,8 +98,8 @@ const SYNTAX_NAMES_PROPS = { minItems: 1, uniqueItems: true, description: - "Optional. Render these components' metadata and long-form documentation " + - "instead of the list of available symbols.", + "Optional. Render complete references for these structural or component names " + + "instead of the compact entry index.", }, }, additionalProperties: false, @@ -131,7 +131,7 @@ export interface SidekickRequests { importAsset(source: string, destination: string): Operation>; /** The acknowledged published root values, detached. */ bindings(): Operation>; - /** The active entry vocabulary, or the lookup of particular names. */ + /** The compact entry index, or complete references for selected symbol names. */ entrySyntax(names?: readonly string[]): Operation>; /** One guide chapter, as the literal Markdown it is. */ guide(chapter: GuideChapter): Operation>; @@ -516,6 +516,8 @@ export function sidekickObservations( // reply that has learned one spelling has learned both. A // comma-separated string would have been a third spelling nothing else // in the language uses. + description: + 'Discover entry syntax with ``, then read complete structural or component references with ``.', props: SYNTAX_NAMES_PROPS, *fn(props: { names?: readonly string[] }): Operation { const names = props.names; diff --git a/packages/cli/src/repl/sidekick/profile.ts b/packages/cli/src/repl/sidekick/profile.ts index b6ee3f871..69b170fae 100644 --- a/packages/cli/src/repl/sidekick/profile.ts +++ b/packages/cli/src/repl/sidekick/profile.ts @@ -64,8 +64,8 @@ import { fatalFailure } from "./testing.ts"; * in an entry and unavailable in a reply, and a reply that tried to run one * would be refused for a reason it had no way to anticipate. The compact * surface below is the *reply's* vocabulary. The entry vocabulary is a read — - * `` — because it is large, it changes with the profile and - * plugins in play, and a reply needs it only when it is about to write one. + * `` returns its compact index; named reads return complete + * references. Both follow the current profile and selected Plugins. */ import { Component, Execution, SYNTAX_COMPONENT } from "@executablemd/core"; diff --git a/packages/cli/tests/fixtures/plugins/structural-reference.mjs b/packages/cli/tests/fixtures/plugins/structural-reference.mjs new file mode 100644 index 000000000..b9967e785 --- /dev/null +++ b/packages/cli/tests/fixtures/plugins/structural-reference.mjs @@ -0,0 +1,38 @@ +export default { + name: "structural-reference-fixture", + /** @returns {import("effection").Operation} */ + // deno-lint-ignore require-yield + *install() { + const props = { type: "object", properties: {}, additionalProperties: false }; + return { + structural: [ + { + kind: "structural", + name: "Banner", + origin: "tier-ph/structural", + forms: ["paired"], + props, + syntax: ["…"], + description: "Frame the lines written inside it.", + context: "The lines this banner frames.", + parent: null, + }, + { + kind: "structural", + name: "BannerLine", + origin: "tier-ph/structural", + forms: ["paired"], + props, + syntax: ["…"], + description: "One line of a banner.", + context: "The line's own content.", + parent: "Banner", + }, + ], + // deno-lint-ignore require-yield + *expand() { + throw new Error("structural-reference-fixture: handler invoked"); + }, + }; + }, +}; diff --git a/packages/cli/tests/repl-sidekick-controls.test.ts b/packages/cli/tests/repl-sidekick-controls.test.ts index da8aed057..29daa0c50 100644 --- a/packages/cli/tests/repl-sidekick-controls.test.ts +++ b/packages/cli/tests/repl-sidekick-controls.test.ts @@ -49,6 +49,7 @@ import { parseDurableEvent, InMemoryStream } from "@executablemd/durable-streams import type { DurableEvent, Json } from "@executablemd/durable-streams"; import { Agent, + Syntax, agentIdentityComponents, installAgentComponents, useNormalizedOutput, @@ -57,7 +58,7 @@ import { retainedSource, useTempFileCompiler, } from "@executablemd/core"; -import type { FunctionComponentDefinition } from "@executablemd/core"; +import type { SyntaxSymbols, FunctionComponentDefinition } from "@executablemd/core"; import { executeInstalled } from "@executablemd/core/host"; import type { ExecutionInstallation, GeneratedXmdRootResult } from "@executablemd/core/host"; @@ -75,6 +76,8 @@ import { ReplHost } from "../src/repl/host.ts"; import type { ReplHostFact } from "../src/repl/host.ts"; import { assembleReplProfile, entryVocabulary } from "../src/repl-profile.ts"; import { installPlugins, NO_PLUGINS } from "../src/plugin-host.ts"; +import structuralReferencePlugin from "./fixtures/plugins/structural-reference.mjs"; +import { BUNDLED_PLUGIN } from "../src/run-profile.ts"; import { ADAPTERS, AGENT } from "./support/plan-harness.ts"; import { entryInitialBindings, projectRepl } from "../src/repl/model.ts"; import { @@ -2051,6 +2054,124 @@ describe("Tier R3 — a reply reads the history, not the screen", () => { expect(asked.requests).toEqual([]); }); + it("1178: entry discovery is a complete compact index and subsequent reads see session edits", function* () { + const directory = yield* useTempDirectory("xmd-index-"); + for (const part of ["first", "second"]) { + yield* ensureDir(join(directory, part)); + } + yield* writeTextFile( + join(directory, "first/Shared.md"), + "---\ndescription: First include wins.\n---\nFirst body.\n", + ); + yield* writeTextFile( + join(directory, "second/Shared.md"), + "---\ndescription: Second include loses.\n---\nSecond body.\n", + ); + yield* writeTextFile(join(directory, "first/Undescribed.md"), "No metadata body.\n"); + yield* writeTextFile( + join(directory, "first/Opaque.ts"), + 'throw new Error("must not import");\n', + ); + yield* writeTextFile( + join(directory, "first/Explained.md"), + `---\ndescription: ${JSON.stringify("Read & [links] | safely " + "long purpose ".repeat(40))}\n---\nComplete authored usage.\n`, + ); + yield* API.Env.around({ + *cwd() { + return directory; + }, + }); + yield* useHostFiles(); + const plugins = yield* installPlugins([BUNDLED_PLUGIN, structuralReferencePlugin], { + command: "repl", + args: [], + }); + const profile = yield* (yield* assembleReplProfile( + { provider: "acpx", defaultAgent: AGENT, adapters: ADAPTERS, permissionMode: "deny-all" }, + plugins, + { includes: ["first", "second"] }, + )).finalize(); + let catalog: SyntaxSymbols | undefined; + yield* Syntax.around({ + *symbols(_args, next) { + catalog = yield* next(); + return catalog; + }, + }); + const session = yield* opened("index", new InMemoryStream()); + const requests = sidekickRequests( + { + ...rootReads(session, profile), + *fill() { + throw new Error("read filled a draft"); + }, + }, + noSubmission, + ); + const index = yield* requests.entrySyntax(); + if (!index.ok || !catalog) { + throw new Error("index must succeed with structured symbols"); + } + const text = index.value; + const listed = [...text.matchAll(/^- `<([^>]+)>` — (.+)$/gm)]; + expect(listed.map((line) => line[1])).toEqual( + catalog.categories.flatMap((category) => category.entries.map((entry) => entry.name)), + ); + expect(listed.every((line) => line[2] && line[2].length <= 350)).toBe(true); + expect(text).toContain("## Built-in structural syntax"); + expect(text).toContain("## Built-in components"); + expect(text).toContain("## User-provided components"); + expect(text).toContain(''); + expect(text).toContain("- `` — First include wins."); + expect(text).not.toContain("Second include loses"); + expect(text).toContain("- `` — Read the named reference"); + expect(text).toContain("- `` — Repository TypeScript module"); + expect(text).toContain("<something> & \\[links\\] \\|"); + expect(text).toContain("- `` — One line of a banner."); + for (const marker of [ + "#### Props", + "```json", + "**Returns:**", + "**Syntax:**", + "**Origin:**", + "- ``", + ]) { + expect(text).not.toContain(marker); + } + const detail = yield* requests.entrySyntax(["BannerLine", "If", "File"]); + if (!detail.ok) { + throw detail.error; + } + expect(detail.value).toContain("written directly inside ``, and nowhere else"); + expect(detail.value).toContain("**Available in this evaluation:** yes"); + expect(detail.value).toContain("#### Props"); + expect(detail.value).toContain("**Returns:**"); + const old = yield* requests.entrySyntax(["Shared"]); + if (!old.ok) { + throw old.error; + } + yield* writeTextFile( + join(directory, "first/Shared.md"), + "---\ndescription: Updated purpose.\n---\nUpdated body.\n", + ); + const updated = yield* requests.entrySyntax(); + const updatedDetail = yield* requests.entrySyntax(["Shared"]); + if (!updated.ok || !updatedDetail.ok) { + throw new Error("fresh reads must succeed"); + } + expect(updated.value).toContain("Updated purpose."); + expect(updatedDetail.value).toContain("Updated purpose."); + expect(text).not.toContain("Updated"); + expect(old.value).toContain("First include wins."); + let refused = false; + try { + yield* entryVocabulary(profile.includes).documentation(["Banner"]); + } catch (error) { + refused = error instanceof Error && error.message.includes("Banner"); + } + expect(refused).toBe(true); + }); + it("R3: the vocabulary a reply is told about is the entry's, not its own", function* () { const session = yield* opened("vocabulary", new InMemoryStream()); const requested = sidekickRequests(reading(session), noSubmission); diff --git a/packages/cli/tests/syntax-cli.test.ts b/packages/cli/tests/syntax-cli.test.ts index 01accbbdc..5c6f339f5 100644 --- a/packages/cli/tests/syntax-cli.test.ts +++ b/packages/cli/tests/syntax-cli.test.ts @@ -563,6 +563,26 @@ describe("Tier SX — the command line", { sanitizeOps: false, sanitizeResources expect(unknown.stdout).toBe(""); }); + it("SX16: engine and selected installed structural names match canonical component references", function* () { + const plugin = new URL("./fixtures/plugins/structural-reference.mjs", import.meta.url).pathname; + for (const name of ["If", "All", "Banner", "BannerLine"]) { + const options = ["--include", ".", `--plugin=${plugin}`]; + const command = yield* runCli(["syntax", name, ...options], { cwd: "." }).expect(); + const document = yield* runCli( + ["run", "-e", ``, ...options], + { cwd: "." }, + ).expect(); + expect(document.stdout.trimEnd()).toBe(command.stdout.trimEnd()); + expect(command.stdout).toContain(`### \`<${name}>\``); + expect(command.stdout).toContain("**Syntax:**"); + expect(command.stdout).not.toContain("**Returns:**"); + expect(command.stdout + command.stderr).not.toContain("handler invoked"); + } + const missing = yield* runCli(["syntax", "Banner", "--include", "."], { cwd: "." }).join(); + expect(missing.code).not.toBe(0); + expect(missing.stdout).toBe(""); + }); + it("SX17: the command and the component read one index, for every package", function* () { // `Prompt` is an Agent component: a different registration boundary from // core's own file, and the one that exposed this. The command assembled the diff --git a/packages/core/src/components/Syntax.ts b/packages/core/src/components/Syntax.ts index 2d4f1e0f9..c2fceb3a6 100644 --- a/packages/core/src/components/Syntax.ts +++ b/packages/core/src/components/Syntax.ts @@ -77,7 +77,7 @@ export const props: PropsSchema = { minItems: 1, uniqueItems: true, description: - "Optional. Render these components' metadata and long-form documentation " + + "Optional. Render complete references for these structural or component names " + "instead of the list of available symbols. Entries render once each, in symbol order.", }, }, diff --git a/packages/core/src/components/components.md b/packages/core/src/components/components.md index f3ab78f00..ea2879324 100644 --- a/packages/core/src/components/components.md +++ b/packages/core/src/components/components.md @@ -37,6 +37,12 @@ use a few specific components rather than what exists — a prompt that has to explain `` does not need the other seventy entries. Entries render once each, in symbol order, whatever order they were asked for in. +Structural names use the same lookup: `` +returns the engine's forms and structural constraints. Installed constructs and +regions include their owner's props, parent relationship and body context. +These references invoke no expansion handler and grant no execution authority. +A mixed structural/component request refuses whole if any name is unknown. + `as` captures the rendered text instead of emitting it, in either form: ```mdx diff --git a/packages/core/src/syntax-api.ts b/packages/core/src/syntax-api.ts index 84b4299ff..13bc10eed 100644 --- a/packages/core/src/syntax-api.ts +++ b/packages/core/src/syntax-api.ts @@ -59,7 +59,7 @@ export interface SyntaxApi { * text of its own, so the two are not two views of one value by construction. */ readonly text: Operation; - /** These components' metadata and long-form documentation. */ + /** Complete owner references for selected component or structural names. */ documentation(names: readonly string[]): Operation; } diff --git a/packages/core/src/syntax-markdown.ts b/packages/core/src/syntax-markdown.ts index 96c75ed77..4def679f6 100644 --- a/packages/core/src/syntax-markdown.ts +++ b/packages/core/src/syntax-markdown.ts @@ -97,7 +97,9 @@ export function renderSelectedDocumentation(selected: readonly SelectedEntry[]): const sections = selected.map((one) => { const blocks = renderEntry(one.entry); blocks.push(`**Available in this evaluation:** ${one.available ? "yes" : "no"}`); - blocks.push(one.documentation ?? NO_DOCUMENTATION); + if (one.entry.kind !== "structural") { + blocks.push(one.documentation ?? NO_DOCUMENTATION); + } return blocks.join("\n\n"); }); return `${sections.join("\n\n")}\n`; diff --git a/packages/core/src/syntax-reference.ts b/packages/core/src/syntax-reference.ts index 73a9c33ed..13274b125 100644 --- a/packages/core/src/syntax-reference.ts +++ b/packages/core/src/syntax-reference.ts @@ -60,7 +60,7 @@ export interface SyntaxReference { /** The symbols this site describes, structured. */ symbols(): Operation; /** - * The selected components' metadata and long-form documentation. + * The selected component and structural owner references. * * Two inputs, not one, and this is the reason the reference is an object * rather than a value. *What may I write here* and *what may I read about* @@ -274,17 +274,16 @@ export function select( // what makes one occurrence's retained result comparable with another's. for (const category of authoring.categories) { for (const entry of category.entries) { - // Components only. `names` is a component lookup under the current - // contract, so a structural construct is not a thing this can select — - // and skipping it here leaves the name in `requested`, which refuses - // below rather than silently rendering nothing for it. - if (!requested.has(entry.name) || entry.kind === "structural") { + if (!requested.has(entry.name)) { continue; } requested.delete(entry.name); selected.push({ entry, - documentation: index.documentationFor(entry.name, entry.origin), + documentation: + entry.kind === "structural" + ? undefined + : index.documentationFor(entry.name, entry.origin), available: runnable.has(identityOf(entry)), }); } diff --git a/packages/core/tests/syntax-api.test.ts b/packages/core/tests/syntax-api.test.ts index a30bb6182..aa41a91f2 100644 --- a/packages/core/tests/syntax-api.test.ts +++ b/packages/core/tests/syntax-api.test.ts @@ -17,7 +17,9 @@ import { renderSyntaxMarkdown, UnknownComponentError, } from "../mod.ts"; -import { executeInstalled, useSyntax } from "../host.ts"; +import { executeInstalled, useSyntax, Structural } from "../host.ts"; +import { inspectSyntax } from "../src/inspect.ts"; +import { syntaxReference } from "../src/syntax-reference.ts"; import { selecting } from "./support/generated-selection.ts"; function symbolsOf(...names: string[]): SyntaxSymbols { @@ -70,6 +72,44 @@ function* run(text: string, stream = new InMemoryStream()): Operation { } describe("Tier SA — contextual Syntax", () => { + it("SA: structural availability compares complete installed identity and keeps enclosing references", function* () { + const declaration = Structural({ + name: "Banner", + origin: "test://first", + forms: ["paired"], + props: { type: "object", properties: {}, additionalProperties: false }, + syntax: ["…"], + description: "Frame content.", + context: "Content.", + parent: null, + }); + const region = Structural({ + ...declaration, + name: "BannerLine", + parent: "Banner", + syntax: ["…"], + }); + const authoring = yield* inspectSyntax({ includes: [], declarations: [declaration, region] }); + const different = yield* inspectSyntax({ + includes: [], + declarations: [declaration, region].map((one) => ({ ...one, origin: "test://other" })), + }); + const absent = yield* inspectSyntax({ includes: [] }); + for (const admitted of [absent, different]) { + yield* scoped(function* () { + const reference = syntaxReference(admitted, authoring); + yield* Syntax.around({ symbols: () => reference.symbols() }); + const text = yield* reference.documentation(["Banner", "If"]); + expect(text).toContain("### ``"); + expect(text).toContain("**Available in this evaluation:** no"); + expect(text).toContain("### ``"); + expect(text).toContain("**Available in this evaluation:** yes"); + expect(text).toContain("test://first"); + expect(text).not.toContain("test://other"); + }); + } + }); + it("SA1: exact public property types, reusable lazy defaults and a suspending transform", function* () { const descriptor: Api = Syntax; expect(descriptor).toBe(RootSyntax); diff --git a/packages/core/tests/syntax-component.test.ts b/packages/core/tests/syntax-component.test.ts index 9932563fc..ebd63e4f4 100644 --- a/packages/core/tests/syntax-component.test.ts +++ b/packages/core/tests/syntax-component.test.ts @@ -49,7 +49,7 @@ import { API, useHostFiles } from "@executablemd/runtime"; import { Component, content } from "../src/component-api.ts"; import { collect } from "../src/collect.ts"; import { execute } from "../src/execute.ts"; -import { executeInstalled, Markdown, sourceDigest } from "../host.ts"; +import { executeInstalled, Markdown, Structural, sourceDigest } from "../host.ts"; import type { ComponentAnswerRequest, ExecutionInstallation } from "../host.ts"; import type { GeneratedSelection } from "../src/component-api.ts"; import { useSelection } from "./support/generated-selection.ts"; @@ -466,10 +466,76 @@ describe("Tier SYN — the named form", () => { expect(undocumented).toContain("No long-form documentation is available for this component."); }); - // A structural construct is not a component, and `names` is a component - // lookup: it refuses rather than rendering one. - const structural = yield* refusal(run('\n')); - expect(structural).toContain("If"); + const source = '\n'; + const structural = String(yield* run(source)); + expect( + String( + yield* run('\n{reference}\n'), + ).trim(), + ).toBe(structural.trim()); + for (const name of ["All", "If", "File"]) { + expect(structural.split(`### \`<${name}>\``)).toHaveLength(2); + } + expect(structural.indexOf("### ``")).toBeLessThan(structural.indexOf("### ``")); + expect(structural.indexOf("### ``")).toBeLessThan(structural.indexOf("### ``")); + expect(structural).toContain("two `` children directly inside it"); + expect(structural).toContain("**Syntax:**"); + expect(structural).toContain("**Body context:**"); + expect(structural).toContain("#### Props"); + expect(structural).toContain("**Returns:**"); + const engineOnly = String(yield* run('\n')); + expect(engineOnly).not.toContain("**Returns:**"); + expect(engineOnly).not.toContain("No long-form documentation"); + const unknown = yield* refusal(run('\n')); + expect(unknown).toContain("NotHere"); + expect(unknown).not.toContain("###"); + }); + + it("SYN30: installed structural references retain props and parent constraints without expansion", function* () { + let expansions = 0; + const declarations = [ + Structural({ + name: "Banner", + origin: "test://banner", + forms: ["paired"], + props: { + type: "object", + properties: { title: { type: "string" } }, + required: ["title"], + additionalProperties: false, + }, + syntax: ['…'], + description: "Frame lines under a heading.", + context: "Direct BannerLine regions.", + parent: null, + }), + Structural({ + name: "BannerLine", + origin: "test://banner", + forms: ["paired"], + props: { type: "object", properties: {}, additionalProperties: false }, + syntax: ["…"], + description: "One line of a banner.", + context: "The line's content.", + parent: "Banner", + }), + ]; + const installation: ExecutionInstallation = { + declarations, + *expand() { + expansions += 1; + }, + }; + const text = String(yield* run('', [installation])); + expect(text).toContain('"required": [\n "title"'); + expect(text).toContain("written directly inside ``, and nowhere else"); + expect(text).toContain("**Forms:** `…`"); + expect(text).toContain("**Body context:** The line's content."); + expect(text).not.toContain("**Returns:**"); + expect(text).not.toContain("**`as`:**"); + expect(text).not.toContain("No long-form documentation"); + expect(text.indexOf("### ``")).toBeLessThan(text.indexOf("### ``")); + expect(expansions).toBe(0); }); it("SYN40: documentation survives planted filesystem middleware", function* () { @@ -2057,7 +2123,7 @@ describe("Tier SYN — reference never permits", () => { minItems: 1, uniqueItems: true, description: - "Optional. Render these components' metadata and long-form documentation " + + "Optional. Render complete references for these structural or component names " + "instead of the list of available symbols. Entries render once each, in symbol order.", }, }, diff --git a/scripts/tests/plan-component-compiled.test.ts b/scripts/tests/plan-component-compiled.test.ts index 88e7a068e..30146480a 100644 --- a/scripts/tests/plan-component-compiled.test.ts +++ b/scripts/tests/plan-component-compiled.test.ts @@ -17,6 +17,7 @@ * missing binary is reported as the setup it is rather than as a failed assertion. */ +import { runCli } from "@executablemd/test-support/launch"; import { describe, it } from "@executablemd/test-support/bdd"; import { expect } from "@executablemd/test-support/expect"; import { ensure, until } from "effection"; @@ -160,11 +161,36 @@ describe("compiled xmd", { sanitizeOps: false, sanitizeResources: false }, () => if (lookup.timeout) { throw new Error("the compiled binary timed out documenting one component"); } + const sourceLookup = yield* runCli(["syntax", "Elicit", "--include", elsewhere], { + cwd: elsewhere, + }).expect(); + expect(lookup.value.stdout).toBe(sourceLookup.stdout); expect(lookup.value.code).toBe(0); expect(lookup.value.stdout).toContain("### ``"); expect(lookup.value.stdout).toContain("Asks a person a structured question"); expect(lookup.value.stdout).toContain("**Available in this evaluation:** yes"); + for (const name of ["If", "All"]) { + const structural = yield* timebox(TIMEOUT, function* () { + return yield* exec(BINARY, { + arguments: ["syntax", name, "--include", elsewhere], + cwd: elsewhere, + }).join(); + }); + if (structural.timeout) { + throw new Error("structural lookup timed out"); + } + const source = yield* runCli(["syntax", name, "--include", elsewhere], { + cwd: elsewhere, + }).expect(); + expect(structural.value.stdout).toBe(source.stdout); + expect(structural.value.code).toBe(0); + expect(structural.value.stdout).toContain(`### \`<${name}>\``); + expect(structural.value.stdout).toContain("**Syntax:**"); + expect(structural.value.stdout).toContain("**Body context:**"); + expect(structural.value.stdout).not.toContain("**Returns:**"); + } + // A component from a boundary *outside* core's own documentation file, so // the probe exercises a second copied asset path rather than proving only // that the first one shipped. diff --git a/scripts/tests/plugin-compiled.test.ts b/scripts/tests/plugin-compiled.test.ts index 217baae83..0052435e7 100644 --- a/scripts/tests/plugin-compiled.test.ts +++ b/scripts/tests/plugin-compiled.test.ts @@ -15,6 +15,7 @@ * missing binary is reported as the setup it is rather than as a failed assertion. */ +import { runCli } from "@executablemd/test-support/launch"; import { describe, it } from "@executablemd/test-support/bdd"; import { expect } from "@executablemd/test-support/expect"; import { ensure, scoped, until } from "effection"; @@ -97,6 +98,30 @@ describe("compiled xmd", { sanitizeOps: false, sanitizeResources: false }, () => }); }); + it("documents installed structural owners identically from source and binary outside the checkout", function* () { + const plugin = path.join(ROOT, "packages/cli/tests/fixtures/plugins/structural-reference.mjs"); + yield* useElsewhere(function* (dir) { + for (const name of ["Banner", "BannerLine"]) { + const args = ["syntax", name, `--plugin=${plugin}`, "--include", dir]; + const binary = yield* runBinary(args, dir); + const source = yield* runCli(args, { cwd: dir }).expect(); + expect(binary.code).toBe(0); + expect(binary.stdout).toBe(source.stdout); + expect(binary.stdout).toContain(`### \`<${name}>\``); + expect(binary.stdout).toContain("**Available in this evaluation:** yes"); + expect(binary.stdout).toContain("**Body context:**"); + expect(binary.stdout).not.toContain("**Returns:**"); + expect(binary.stdout + binary.stderr).not.toContain("handler invoked"); + if (name === "BannerLine") { + expect(binary.stdout).toContain("written directly inside ``, and nowhere else"); + } + } + const missing = yield* runBinary(["syntax", "Banner", "--include", dir], dir); + expect(missing.code).not.toBe(0); + expect(missing.stdout).toBe(""); + }); + }); + it("describes the engine's language and the bundled Plugin's, and nothing else", function* () { if (!(yield* exists(BINARY))) { throw new Error(`${BINARY} is missing — run \`deno task build\` before this case`); diff --git a/specs/executable-mdx-spec.md b/specs/executable-mdx-spec.md index 3d4f9ecd5..03149535e 100644 --- a/specs/executable-mdx-spec.md +++ b/specs/executable-mdx-spec.md @@ -2958,9 +2958,9 @@ engine-owned `as` captures the same text and emits nothing. ``` It is **self-closing only** and declares one optional prop, `names`: a non-empty -array of unique component-name strings. A paired spelling, any other prop, an +array of unique symbol-name strings. A paired spelling, any other prop, an empty list, a duplicate, a non-string member and a name this site has no -component for are each refused before the symbols are read, so a refusal +symbol for are each refused before the symbols are read, so a refusal produces no partial text and no successful retained result. **The named form renders documentation.** `` @@ -2992,9 +2992,17 @@ component — a repository file, a bundle member, a host's declared Markdown — takes its long-form documentation from its own document's body, read through the canonical frontmatter split; an empty body uses the sentence. -Named lookup selects **component entries**. A structural construct is not a -component, so `` refuses as an unknown component while -the bare form continues to list structural syntax alongside components. +Named lookup also selects **structural entries**. `` +renders the engine owner's authored forms, purpose and structural constraints. +Installed constructs and their regions retain their declared forms, props, +parent relationship and body context. Their declaration metadata is their usage +reference; they receive no component package-documentation fallback, return +schema or invented binding contract. Mixed structural/component requests render +once each in symbol order and refuse whole if any name is unknown. Inspection +invokes no structural expansion handler. Availability compares the full engine +or installed origin identity against effective symbols and grants no execution +authority. Bare ``, bare `xmd syntax` and version-1 JSON retain their +existing presentation. The documentation is read from the owning package through the direct filesystem, not through `API.Fs` or the document-facing `Files` provider. Both of those are @@ -13636,8 +13644,8 @@ component that observes one at an authored site. | SYN26 | Another loaded copy | A protected implementation built by a second loaded copy answers for nothing in the active execution | | SYN27 | Protected provenance | The symbols report the component under the `protected` origin kind in both the structured entry and the rendered Markdown, and never as a reserved registration; `inspectComponent` agrees | | SYN28 | Pinned provenance | A workflow-bundle component is reported at its canonical logical retained-source path *and* the retained source's own content hash, under the `workflow` origin kind, and stays in the user-provided category | -| SYN29 | The named form | Selected entries render their metadata and documentation once each in symbol order, not request order, with nothing else of the symbols; `as` binds identical text | -| SYN30 | Availability and absence | Each entry states whether it is available in the current evaluation; a selected entry with no authored documentation renders its metadata and says so | +| SYN29 | The named form | Selected component and structural entries render their complete owner references once each in symbol order, not request order; installed regions state their parent and props; `as` binds identical text | +| SYN30 | Availability and absence | Each entry states availability by full identity; custom components without authored documentation say so; structural references use owner metadata without a component fallback or handler invocation | | SYN31 | Atomic refusal | An unknown name, an empty list, a duplicate, a non-string member, a non-array value and an undeclared prop each refuse with no successful retained result | | SYN39 | Named retention | The occurrence retains its final rendered text, a continuation restores it without rereading documentation or rebuilding the symbols, and a corrupted record refuses | | SYN25c | The narrowing seam | A narrowed reference reports the narrowed vocabulary bare, documents the enclosing symbols by name, and marks each entry's availability truthfully in both directions | @@ -13728,7 +13736,7 @@ would bind differently — belongs to `EP`, where profile capture is tested. | SX7/SX8 | Includes | Repeated values select in caller order and replace the defaults; absent, the defaults apply | | SX9 | Failure | An unusable include exits 1, reports on stderr and prints no symbols | | SX10/SX11 | Formats | Markdown by default, version-1 JSON with `--json`; the symbols are inspection, and `xmd plan` is the command that writes with the same structured value | -| SX16 | Named lookup | `xmd syntax Elicit` renders that component's metadata and long-form documentation through the same selection, index and renderer `` uses; the compact symbols are unchanged and an unknown name refuses whole | +| SX16 | Named lookup | `xmd syntax Elicit` and `xmd syntax If` render complete component and structural references through the same selection, index and renderer `` uses; the compact symbols are unchanged and an unknown name refuses whole | | SX12 | A package tree | Bare `xmd syntax` succeeds with the default includes in a repository whose `node_modules` holds directory links | | SX13–SX15 | Delivery | A real pipeline reading symbols larger than one pipe buffer receives the bytes a regular-file redirect receives, in both forms; a consumer that closes early leaves the command reporting on stderr with exit 1 rather than an unhandled write failure | | SX18–SX19 | Run delivery | A real pipeline reading a run's output larger than one pipe buffer receives the bytes a regular-file redirect receives; a consumer that closes early is reported rather than raised, and on the runtimes that surface a refused write the run exits 1 | diff --git a/specs/repl-spec.md b/specs/repl-spec.md index ab35903d4..cbc25bcd9 100644 --- a/specs/repl-spec.md +++ b/specs/repl-spec.md @@ -3210,7 +3210,7 @@ layering those live values over retained head values. A reply's own vocabulary and an entry's are described separately, because they differ: a construct that is ordinary in an entry can be unavailable in a reply. What a reply may write is the compact surface derived from what is admitted; what -an entry may write is a read, using core's selection and renderer over the +an entry may write is a read, using core's structured symbols and selection over the ordinary entry's current registry, finalized includes and host declarations. It carries the existing assertion defaults, including Assert, AssertEquals and AssertThrows, without entering the broader CLI run profile's testing, Verbose @@ -3218,7 +3218,15 @@ or web bootstrap. Each ask reads current session component files; Plugin selecti captured once per command, and another configured command describes its own selection. Earlier saved discovery stays historical feedback. -Bare REPL.Syntax omits testing-package components absent from the ordinary +Bare `` returns a compact index: exact names in their existing +categories, one bounded short purpose per name and a copyable named lookup. +It projects the current structured symbols without prop tables, JSON or return +schemas, detailed usage or origin boilerplate. `` +returns complete selected references, including engine and installed structural +forms, props and parent constraints. Canonical bare ``, CLI syntax and +version-1 JSON keep their existing formats. + +The index omits testing-package components absent from the ordinary profile and points to Markdown tests. Named lookup can describe those components with availability `no`, their package documentation, a complete test example and the supported REPL.Test invocation. Ordinary same-named components keep their From 4f7d69726fda9b7f7ca81a8e34b25f53b7f6d54e Mon Sep 17 00:00:00 2001 From: Taras Mankovski Date: Tue, 10 Nov 2026 06:06:53 -0500 Subject: [PATCH 2/4] test: align REPL journeys with compact syntax discovery --- packages/cli/tests/repl-agent-journey.test.ts | 5 +++-- packages/cli/tests/repl-sidekick-journey.test.ts | 16 ++++++++-------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/packages/cli/tests/repl-agent-journey.test.ts b/packages/cli/tests/repl-agent-journey.test.ts index d3a75144c..090386b0e 100644 --- a/packages/cli/tests/repl-agent-journey.test.ts +++ b/packages/cli/tests/repl-agent-journey.test.ts @@ -559,8 +559,9 @@ describe("A2–A5 — the selected REPL component environment", () => { expect(Object.isFrozen(profile.includes)).toBe(true); const symbols = yield* profile.vocabulary.symbols(); const documentation = yield* profile.vocabulary.documentation(["Greeting"]); + expect(documentation).toContain(`${fixture.first}/Greeting.md`); + expect(symbols).not.toContain("**Origin:**"); for (const text of [symbols, documentation]) { - expect(text).toContain(`${fixture.first}/Greeting.md`); expect(text).toContain("First greeting contract."); expect(text).not.toContain("Second greeting contract."); expect(text).not.toContain(""); @@ -570,7 +571,7 @@ describe("A2–A5 — the selected REPL component environment", () => { const protectedNames = ["Syntax", "Evaluate", "File", "File.Delete", "Dir"]; const protectedDocs = yield* profile.vocabulary.documentation(protectedNames); for (const name of protectedNames) { - expect(symbols.split(`### \`<${name}>\``)).toHaveLength(2); + expect(symbols.split(`- \`<${name}>\` —`)).toHaveLength(2); expect(protectedDocs.split(`### \`<${name}>\``)).toHaveLength(2); } expect(protectedDocs.match(/\(protected component\)/g)).toHaveLength(5); diff --git a/packages/cli/tests/repl-sidekick-journey.test.ts b/packages/cli/tests/repl-sidekick-journey.test.ts index c4777de05..1741b9474 100644 --- a/packages/cli/tests/repl-sidekick-journey.test.ts +++ b/packages/cli/tests/repl-sidekick-journey.test.ts @@ -4396,13 +4396,13 @@ describe("REPL syntax matches ordinary entry execution (#1053)", () => { `, ); const listing = documented(discovery); - expect(listing).toContain("### ``"); - expect(listing).toContain("### ``"); + expect(listing).toContain("- `` —"); + expect(listing).toContain("- `` —"); for (const name of ["Assert", "AssertEquals"]) { - expect(listing).toContain(`### \`<${name}>\``); + expect(listing).toContain(`- \`<${name}>\` —`); } for (const name of ["Testing", "Verbose", "WebForm"]) { - expect(listing).not.toContain(`### \`<${name}>\``); + expect(listing).not.toContain(`- \`<${name}>\` —`); } expect(documented(discovery, 1)).toContain("**Available in this evaluation:** yes"); expect(documented(discovery, 4)).toContain("**Available in this evaluation:** yes"); @@ -4479,7 +4479,7 @@ Session body ${version}.`, ` `, ); - expect(documented(changed)).toContain("### ``"); + expect(documented(changed)).toContain("- `` —"); const named = documented(changed, 1); expect(named).toContain(path); expect(named).toContain(`Session assertion ${version}.`); @@ -4495,7 +4495,7 @@ Session body ${version}.`, ` `, ); - expect(documented(removed)).toContain("### ``"); + expect(documented(removed)).toContain("- `` —"); expect(documented(removed, 1)).toContain("**Available in this evaluation:** yes"); expect(documented(removed, 1)).not.toContain("Session assertion"); yield* exchange(held, submission("")); @@ -4536,7 +4536,7 @@ Session body ${version}.`, `, ); if (selected) { - expect(documented(discovery)).toContain("### ``"); + expect(documented(discovery)).toContain("- `` —"); expect(documented(discovery, 1)).toContain("syntax-1053"); yield* exchange(held, submission("")); expect(held.session.model.entries).toHaveLength(1); @@ -4544,7 +4544,7 @@ Session body ${version}.`, "Selected plugin body.", ); } else { - expect(documented(discovery)).not.toContain("### ``"); + expect(documented(discovery)).not.toContain("- `` —"); refused(discovery, "Selected1053"); refused( yield* exchange(held, submission("")), From c3ea655630d2097f78f7c8a6c14c0eba4cffcb94 Mon Sep 17 00:00:00 2001 From: Taras Mankovski Date: Tue, 10 Nov 2026 07:14:16 -0500 Subject: [PATCH 3/4] fix: describe generated structural syntax availability truthfully --- packages/core/src/components/Evaluate.ts | 7 +- packages/core/src/generated-xmd.ts | 17 ++++- packages/core/src/inspect.ts | 20 +----- packages/core/src/structural.ts | 19 ++++++ packages/core/src/syntax-admitted.ts | 14 ++-- packages/core/src/syntax-reference.ts | 51 +++++++++++--- .../core/tests/evaluate-component.test.ts | 52 +++++++++++++- .../tests/fixtures/syntax-generated-base.json | 10 +++ .../core/tests/generated-xmd-root.test.ts | 57 ++++++++++++++++ .../core/tests/support/syntax-availability.ts | 43 ++++++++++++ packages/core/tests/syntax-api.test.ts | 67 +++++++++++++++++++ scripts/tests/plan-component-compiled.test.ts | 57 ++++++++++++++++ specs/executable-mdx-spec.md | 8 ++- 13 files changed, 377 insertions(+), 45 deletions(-) create mode 100644 packages/core/tests/fixtures/syntax-generated-base.json create mode 100644 packages/core/tests/support/syntax-availability.ts diff --git a/packages/core/src/components/Evaluate.ts b/packages/core/src/components/Evaluate.ts index ed10ca511..51269ae87 100644 --- a/packages/core/src/components/Evaluate.ts +++ b/packages/core/src/components/Evaluate.ts @@ -82,7 +82,7 @@ import { selectedTables, } from "../evaluation-profile.ts"; import type { CapturedEntry, EvaluationProfile, SelectedTables } from "../evaluation-profile.ts"; -import { evaluateProtectedGeneratedXmd } from "../generated-xmd.ts"; +import { generatedStructuralEntries, evaluateProtectedGeneratedXmd } from "../generated-xmd.ts"; import type { GeneratedEffectClass, GeneratedImplementation, @@ -327,7 +327,10 @@ function narrow( enclosing: SyntaxReference | undefined, tables: SelectedTables, ): SyntaxReference | undefined { - return enclosing?.available(admittedSymbols(tables.admitted)); + return enclosing?.available( + admittedSymbols(tables.admitted), + generatedStructuralEntries("fragment"), + ); } /** diff --git a/packages/core/src/generated-xmd.ts b/packages/core/src/generated-xmd.ts index 94710e159..a15164016 100644 --- a/packages/core/src/generated-xmd.ts +++ b/packages/core/src/generated-xmd.ts @@ -142,7 +142,8 @@ import { renderSegments } from "./render.ts"; import { scanSegments } from "./scanner.ts"; import { readsBinding } from "./generated-interpolation.ts"; import { SourceOwner, sourceOwnerDescription } from "./source-owner.ts"; -import { RESERVED_STRUCTURAL } from "./structural.ts"; +import { RESERVED_STRUCTURAL, STRUCTURAL_DECLARATIONS, engineSyntaxEntry } from "./structural.ts"; +import type { EngineSyntaxEntry } from "./inspect.ts"; // The ordinary source rules, read rather than reimplemented: a construct means // one thing whether a person wrote it or an Agent did. import { InvocationTeardownError } from "./invocation.ts"; @@ -1846,6 +1847,15 @@ const CONSUMED_BY_PARENT: ReadonlySet = new Set([ */ const NO_GENERATED_CONTEXT: ReadonlySet = new Set(["Content", "Return"]); +/** Engine syntax supported at a valid placement in this generated language. */ +export function generatedStructuralEntries( + language: "fragment" | "root", +): readonly EngineSyntaxEntry[] { + return STRUCTURAL_DECLARATIONS.filter( + ({ name }) => !NO_GENERATED_CONTEXT.has(name) && (language === "root" || name !== "Output"), + ).map(({ name }) => engineSyntaxEntry(name)); +} + /** * One structural construct, held to the ordinary source rules. * @@ -2535,7 +2545,10 @@ function* evaluateGenerated( // `admittedSymbols` already describes an evaluation's vocabulary with — the // same call the authored site makes, so one description mechanism answers // for both kinds. - reference = resolved.reference?.available(admittedSymbols(resolved.describing)); + reference = resolved.reference?.available( + admittedSymbols(resolved.describing), + generatedStructuralEntries("root"), + ); } const stored = yield* persistAdmission( diff --git a/packages/core/src/inspect.ts b/packages/core/src/inspect.ts index d7718815d..3564a0d88 100644 --- a/packages/core/src/inspect.ts +++ b/packages/core/src/inspect.ts @@ -29,7 +29,7 @@ import { PROTECTED_COMPONENT_NAMES } from "./components/protected.ts"; import type { WorkflowComponentCatalog } from "./components/bundle.ts"; import { documentationOf } from "./components/documentation.ts"; import type { ComponentDocumentation } from "./components/documentation.ts"; -import { STRUCTURAL_DECLARATIONS } from "./structural.ts"; +import { STRUCTURAL_DECLARATIONS, engineSyntaxEntry } from "./structural.ts"; import { assertDistinctIdentityNames } from "./invocation-identity.ts"; import type { IdentityComponent } from "./invocation-identity.ts"; import { readRootSource, rootSourcePath } from "./root-source.ts"; @@ -615,7 +615,7 @@ export function* inspectSyntax(options: InspectSyntaxOptions): Operation candidate.name === construct); - if (declaration === undefined) { - throw new Error(`structural construct ${construct} has no declaration`); - } - return { - kind: "structural", - name: declaration.name, - origin: { kind: "structural", construct: declaration.name }, - syntax: declaration.syntax, - description: declaration.description, - ...(declaration.as === null ? {} : { as: declaration.as }), - ...(declaration.context === null ? {} : { context: declaration.context }), - }; -} - /** * The symbol entry one selection produces, or `undefined` when the selection * describes nothing a document can write here. diff --git a/packages/core/src/structural.ts b/packages/core/src/structural.ts index cef714723..7c728becc 100644 --- a/packages/core/src/structural.ts +++ b/packages/core/src/structural.ts @@ -12,6 +12,8 @@ * in it. */ +import type { EngineSyntaxEntry } from "./inspect.ts"; + /** * One construct the engine owns, as both a reservation and a description of * itself. @@ -251,3 +253,20 @@ const REFERENCE_PROPS: ReadonlyMap = new Map([["Let", "value"]]) export function bindsByReference(componentName: string, propName: string): boolean { return REFERENCE_PROPS.get(componentName) === propName; } + +/** The engine declaration projected into its inspected reference entry. */ +export function engineSyntaxEntry(construct: string): EngineSyntaxEntry { + const declaration = STRUCTURAL_DECLARATIONS.find((candidate) => candidate.name === construct); + if (declaration === undefined) { + throw new Error(`structural construct ${construct} has no declaration`); + } + return { + kind: "structural", + name: declaration.name, + origin: { kind: "structural", construct: declaration.name }, + syntax: declaration.syntax, + description: declaration.description, + ...(declaration.as === null ? {} : { as: declaration.as }), + ...(declaration.context === null ? {} : { context: declaration.context }), + }; +} diff --git a/packages/core/src/syntax-admitted.ts b/packages/core/src/syntax-admitted.ts index 3603e573d..8dc59aa36 100644 --- a/packages/core/src/syntax-admitted.ts +++ b/packages/core/src/syntax-admitted.ts @@ -4,16 +4,12 @@ * An agent asked to write a fragment is told what a fragment may contain. That * is not the vocabulary of the site the `` element was written at: * the evaluator admits the trusted composition table and the names the host - * selected for the selected classes, and nothing else — no executable code - * block, no interpolation, and none of the structural constructs an ordinary - * document has. + * selected for the selected classes. This bare presentation describes those + * components and keeps structural and built-in categories empty. * - * So the symbols built here say exactly that. The structural and built-in - * categories are empty, because a fragment writes neither, and the components - * are the composition entries beside the ones the selection resolved to. - * Anything else would describe a vocabulary the fragment does not have, and an - * agent told it had `` would produce a fragment the evaluator refuses - * whole. + * Generated source also supports engine language such as Loop at valid + * placements. Named references describe that support through the boundary's + * generated-language specialization, separately from this component listing. * * What an author may *read about* is a separate question, and this does not * answer it: `SyntaxReference.available()` keeps the enclosing documentation diff --git a/packages/core/src/syntax-reference.ts b/packages/core/src/syntax-reference.ts index 13274b125..12f338fbc 100644 --- a/packages/core/src/syntax-reference.ts +++ b/packages/core/src/syntax-reference.ts @@ -33,7 +33,7 @@ import { type Operation, scoped } from "effection"; import { NamedBasis, Syntax } from "./syntax-api.ts"; import { inspectSyntax } from "./inspect.ts"; -import type { SyntaxSymbols } from "./inspect.ts"; +import type { EngineSyntaxEntry, SyntaxSymbols } from "./inspect.ts"; import { renderSelectedDocumentation } from "./syntax-markdown.ts"; import type { SelectedEntry } from "./syntax-markdown.ts"; import { documentationIndexFor } from "./component-documentation.ts"; @@ -88,13 +88,21 @@ export interface SyntaxReference { * reports that vocabulary from `symbols()` and keeps *this* reference's * authoring symbols and documentation index for `documentation()`. * + * Generated boundaries may supply engine entries for named availability at + * valid placements. The reference snapshots them; bare component symbols stay + * unchanged. Omission keeps effective identity comparison, while an empty + * list explicitly supplies no generated engine language. + * * Deriving it any other way would mean the evaluator recovering the raw * contributions and rebuilding an index — which is both a hole (that list is * execution-private for a reason) and a way for the two indexes to drift. * Narrowing what may run is not narrowing what may be read about, and the * reference is the thing that already knows both. */ - available(symbols: SyntaxSymbols): SyntaxReference; + available( + symbols: SyntaxSymbols, + namedStructural?: readonly EngineSyntaxEntry[], + ): SyntaxReference; } /** The selection inputs an execution captured, as symbol construction reads them. */ @@ -163,15 +171,35 @@ function referencing( */ admitted: SyntaxSymbols | undefined, contributions: readonly DocumentationContribution[], + namedStructural?: readonly EngineSyntaxEntry[], ): SyntaxReference { + const structural = namedStructural?.map((entry) => + Object.freeze({ + ...entry, + origin: Object.freeze({ ...entry.origin }), + syntax: Object.freeze([...entry.syntax]), + }), + ); + if (structural !== undefined) { + Object.freeze(structural); + } return { *symbols(): Operation { - // A narrowed reference reports its admission and asks the enclosing - // symbols for nothing — the bare form is about what runs. Otherwise this - // is the default answer, and the basis below is consulted first so that - // the one occurrence already resolving a basis gets that same value back - // instead of resolving a moving root a second time. - return admitted ?? (yield* NamedBasis.get()) ?? (yield* authoring()); + // A named lookup adds its generated language to the admitted component + // presentation. Bare reads keep that presentation unchanged. At a root, + // reuse the lookup's basis instead of inspecting a moving source twice. + const basis = yield* NamedBasis.get(); + if (admitted !== undefined && structural !== undefined && basis !== undefined) { + return { + ...admitted, + categories: [ + { kind: "structural", entries: structural }, + admitted.categories[1], + admitted.categories[2], + ], + }; + } + return admitted ?? basis ?? (yield* authoring()); }, documentation(names: readonly string[]): Operation { return scoped(function* () { @@ -200,12 +228,15 @@ function referencing( return renderSelectedDocumentation(selected); }); }, - available(next: SyntaxSymbols): SyntaxReference { + available( + next: SyntaxSymbols, + namedStructural?: readonly EngineSyntaxEntry[], + ): SyntaxReference { // The enclosing authoring symbols and the enclosing contributions, // unchanged. Only what may execute is replaced, so a nested author keeps // the documentation they had and every entry reports its availability // against the admission. - return referencing(authoring, next, contributions); + return referencing(authoring, next, contributions, namedStructural); }, }; } diff --git a/packages/core/tests/evaluate-component.test.ts b/packages/core/tests/evaluate-component.test.ts index 2259d4e96..3054da2b0 100644 --- a/packages/core/tests/evaluate-component.test.ts +++ b/packages/core/tests/evaluate-component.test.ts @@ -43,6 +43,8 @@ import { captureEvaluationProfile, evaluationLifetime } from "../src/evaluation- import type { ResolvedAnswer, ResolvedAnswers } from "../src/evaluation-profile.ts"; import { coreComponentDefinition, CORE_ORIGIN } from "../src/components/registry.ts"; import { fixedFilesystemDefinition } from "../src/components/fixed-filesystem.ts"; +import baseline1178 from "./fixtures/syntax-generated-base.json" with { type: "json" }; +import { expectAvailability, syntaxInstallation } from "./support/syntax-availability.ts"; import { admittedSymbols } from "../src/syntax-admitted.ts"; function independentWrapper(answer: FunctionComponentDefinition): FunctionComponentDefinition { @@ -255,7 +257,7 @@ describe("protected generated component answers", () => { }, ]); const output = yield* run( - '\n\n\n\n', + '\n\n\n\n\n\n', [syntaxProfile()], stream, ); @@ -263,13 +265,19 @@ describe("protected generated component answers", () => { }); expect(told).toHaveLength(1); expect(told[0]).toContain("### ``"); + expectAvailability(told[0], "If", true); + expectAvailability(told[0], "Syntax", true); expect(told[0]).not.toContain("### ``"); expect(told[0]).not.toContain("### ``"); const reads = (yield* stream.readAll()).filter( (event) => event.type === "yield" && event.description.type === "syntax_symbols", ); - expect(reads).toHaveLength(2); - expect(reads[0]).not.toEqual(reads[1]); + expect(reads).toHaveLength(4); + expect(reads[0].result).toEqual(reads[2].result); + expect(reads[0].result).toEqual({ + status: "ok", + value: { symbols: baseline1178["fragment-base.txt"] }, + }); for (const text of ["", "", ""]) { expect( yield* refusal(run(``, [syntaxProfile()])), @@ -3026,3 +3034,41 @@ describe("Tier FE36 — canonical `` is a write a person answers", () => expect(yield* replayStream.readAll()).toEqual(complete); }); }); + +describe("1178 real fragment references", () => { + it("reports engine language, component admission and installed absence without changing bare output", function* () { + const calls: string[] = []; + const names = [ + "If", + "Syntax", + "Banner", + "BannerLine", + "Content", + "Return", + "Output", + "Loop", + "Else", + "All", + ]; + const source = `1178-CUT1178-FRAGMENT`; + const output = String( + yield* run(``, [ + syntaxProfile(), + syntaxInstallation(calls), + ]), + ); + const [captured, marker] = output.split("1178-CUT"); + const { before, reference, after } = JSON.parse(captured); + for (const name of ["If", "Syntax", "Loop", "Else", "All"]) { + expectAvailability(reference, name, true); + } + for (const name of ["Content", "Return", "Output", "Banner", "BannerLine"]) { + expectAvailability(reference, name, false); + } + expect(marker).toContain("1178-FRAGMENT"); + expect(before).toBe(baseline1178["fragment-base.txt"]); + expect(after).toBe(baseline1178["fragment-base.txt"]); + expect(calls).toEqual([]); + expect(String(yield* run("", []))).toBe(baseline1178["ordinary-base.txt"]); + }); +}); diff --git a/packages/core/tests/fixtures/syntax-generated-base.json b/packages/core/tests/fixtures/syntax-generated-base.json new file mode 100644 index 000000000..3e6e806d7 --- /dev/null +++ b/packages/core/tests/fixtures/syntax-generated-base.json @@ -0,0 +1,10 @@ +{ + "fragment-base.txt": "## Built-in structural syntax\n\nNo structural constructs are reserved.\n\n## Built-in components\n\nNo components are registered in this profile.\n\n## User-provided components\n\n### ``\n\nRender a value as JSON text. `` writes the JSON where you put it.\n\n**Forms:** ``\n\n#### Props\n\nThis component declares no individual props.\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {},\n \"additionalProperties\": false\n}\n```\n\n**Captures:** `value` — evaluated by the component itself, so these props are deliberately absent from the schema above.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/core` (registered default)\n\n### ``\n\nInspect available components and control-flow constructs. `` lists the symbols available here; `` renders selected documentation.\n\n**Forms:** ``\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `names` | `array` | no | Optional. Render complete references for these structural or component names instead of the list of available symbols. Entries render once each, in symbol order. |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"names\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n },\n \"minItems\": 1,\n \"uniqueItems\": true,\n \"description\": \"Optional. Render complete references for these structural or component names instead of the list of available symbols. Entries render once each, in symbol order.\"\n }\n },\n \"additionalProperties\": false\n}\n```\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/core` (protected component)\n", + "root-base.txt": "## Built-in structural syntax\n\nNo structural constructs are reserved.\n\n## Built-in components\n\nNo components are registered in this profile.\n\n## User-provided components\n\n### ``\n\nRender a value as JSON text. `` writes the JSON where you put it.\n\n**Forms:** ``\n\n#### Props\n\nThis component declares no individual props.\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {},\n \"additionalProperties\": false\n}\n```\n\n**Captures:** `value` — evaluated by the component itself, so these props are deliberately absent from the schema above.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/core` (registered default)\n\n### ``\n\n**Forms:** ``\n\n#### Props\n\nThis component declares no individual props.\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {},\n \"additionalProperties\": false\n}\n```\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `test://provider` (registered default)\n\n### ``\n\nInspect available components and control-flow constructs. `` lists the symbols available here; `` renders selected documentation.\n\n**Forms:** ``\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `names` | `array` | no | Optional. Render complete references for these structural or component names instead of the list of available symbols. Entries render once each, in symbol order. |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"names\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n },\n \"minItems\": 1,\n \"uniqueItems\": true,\n \"description\": \"Optional. Render complete references for these structural or component names instead of the list of available symbols. Entries render once each, in symbol order.\"\n }\n },\n \"additionalProperties\": false\n}\n```\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/core` (protected component)\n", + "canonical-base.txt": "## Built-in structural syntax\n\n### ``\n\nRun tasks in parallel. `firstsecond` expands every task at the same time, waits for them all to succeed, and preserves their Markdown order. Write at least two `` children directly inside it; if one fails, unfinished tasks are cancelled and `` produces no output.\n\n**Syntax:**\n\n```md\n……\n```\n\n**Body context:** The `` children this runs at the same time.\n\n### ``\n\nSupply one answer inside ``. `` answers any elicitation its template matches — `{?name}` matches any text. The first matching `` wins.\n\n**Syntax:**\n\n```md\n\n…\n```\n\n**Body context:** A multiline template, in place of the single-line `template` prop.\n\n### ``\n\nAnswer any `` in its content without asking a person. `…` replies from the `` matchers declared inside it, reaching elicitations from nested components too. `delegate` passes an unmatched one outward instead of failing.\n\n**Syntax:**\n\n```md\n…\n```\n\n**Body context:** `` matchers, and the body they answer for.\n\n### ``\n\nExit the nearest enclosing ``. `` stops the current iteration where it is; nothing after it in that iteration runs.\n\n**Syntax:**\n\n```md\n\n```\n\n### ``\n\nDefine one branch of a ``. `…` matches with `===`; `…` is the final fallback.\n\n**Syntax:**\n\n```md\n…\n…\n```\n\n**Body context:** Markdown expanded when this case is selected.\n\n### ``\n\nHandle a failure in the preceding Try body. `{error.message}` runs after clean release; its bindings stay local. Cancellation skips this branch.\n\n**Syntax:**\n\n```md\n…\n…\n```\n\n**`as`:** Optional. Binds the ordinary Error by reference in this branch.\n\n**Body context:** Recovery content.\n\n### ``\n\nRender what the caller wrote inside this component. `` renders all of it; `` renders just the part the caller marked `slot=\"footer\"`.\n\n**Syntax:**\n\n```md\n\n\n```\n\n### ``\n\nRepeat content for each item in an array. `…` binds each one to `item` inside.\n\n**Syntax:**\n\n```md\n…\n```\n\n**`as`:** Optional. Captures the whole rendered loop instead of emitting it.\n\n**Body context:** Markdown rendered once per element.\n\n### ``\n\nThe branch `` takes when its condition is false. `…` is written directly inside an ``, and is an error anywhere else.\n\n**Syntax:**\n\n```md\n…\n```\n\n**Body context:** The branch taken when the enclosing condition does not hold.\n\n### ``\n\nFinish a Try after its attempted body and recovery. `Cleanup.` also runs and joins on terminal Stop. Resumable Exit leaves an unentered branch pending; failed release and infrastructure failure prevent new entry.\n\n**Syntax:**\n\n```md\n…\n```\n\n**Body context:** Completion content using the surrounding bindings.\n\n### ``\n\nExpand content only when a condition is true. `…` expands its content, or the `` branch instead. The branch not taken never runs.\n\n**Syntax:**\n\n```md\n…\n```\n\n**Body context:** The branch taken when the condition holds, up to an ``.\n\n### ``\n\nBind a name for the rest of the region. `…` binds what its content rendered; `` binds the value. `select` narrows the rendered content to one CSS selection.\n\n**Syntax:**\n\n```md\n…\n\n```\n\n**`as`:** Required. The binding name the value is available under.\n\n**Body context:** Markdown whose rendered text becomes the binding, in the paired form.\n\n### ``\n\nRepeat content up to `max` times. `…` expands its content again and again until a `` inside it, or until `max` is reached. `max` is required.\n\n**Syntax:**\n\n```md\n…\n```\n\n**Body context:** Markdown expanded once per iteration.\n\n### ``\n\nRestrict what a document or component renders. `…` becomes its entire output; anything outside the region is not rendered.\n\n**Syntax:**\n\n```md\n…\n```\n\n**Body context:** The rendered output the run presents.\n\n### ``\n\nConvert thrown errors into output without failing. `…` renders any failure inside it as part of the output.\n\n**Syntax:**\n\n```md\n…\n```\n\n**Body context:** The region whose failures are printed rather than raised.\n\n### ``\n\nReturn a value instead of rendered markdown. `` hands the value to the caller, checked against the component's declared `returns` schema.\n\n**Syntax:**\n\n```md\n\n```\n\n### ``\n\nRun a task in parallel inside of ``. Write `…` directly inside ``; bindings made in its content stay with that task, and `` or `` cannot affect work outside it.\n\n**Syntax:**\n\n```md\n…\n```\n\n**Body context:** Markdown expanded in its own child, beside its siblings.\n\n### ``\n\nChoose one branch by comparing a value with `===`. `……` expands the first matching case, or the final default when none matches.\n\n**Syntax:**\n\n```md\n…\n```\n\n**Body context:** Direct `` branches considered in source order.\n\n### ``\n\nRecover an ordinary failure after its resources close. `…fallback` keeps the rendered prefix and stops the attempted body at failure. Write Catch, Finally, or both. Failed release and infrastructure failures end execution.\n\n**Syntax:**\n\n```md\n………\n```\n\n**Body context:** Attempted content followed by direct Catch and Finally branches.\n\n## Built-in components\n\n### ``\n\nShow arbitrary text as a fenced Markdown code block. `` chooses a fence the value cannot close.\n\n**Forms:** ``\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `value` | `string` | yes | |\n| `language` | `string` | no | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"value\": {\n \"type\": \"string\"\n },\n \"language\": {\n \"type\": \"string\",\n \"pattern\": \"^[A-Za-z0-9][A-Za-z0-9._+#-]*$\"\n }\n },\n \"required\": [\n \"value\"\n ],\n \"additionalProperties\": false\n}\n```\n\n**`as`:** Optional. Captures the exact fenced Markdown instead of emitting it.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/core` (registered default)\n\n### ``\n\nRead the working directory. `` renders its path without adding a newline.\n\n**Forms:** ``\n\n#### Props\n\nThis component declares no individual props.\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {},\n \"additionalProperties\": false\n}\n```\n\n**`as`:** Optional. Captures the directory path instead of emitting it.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/core` (registered default)\n\n### ``\n\nCreate or use a directory. `…` changes the working directory for its content.\n\n**Forms:** `…`\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `path` | `string` | yes | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"path\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n },\n \"required\": [\n \"path\"\n ],\n \"additionalProperties\": false\n}\n```\n\n**Body context:** The Markdown expanded in that directory.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/core` (protected component)\n\n### ``\n\nAsk a person a structured question. `…` shows the content as the request.\n\n**Forms:** ``, `…`\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `schema` | JSON Schema | yes | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"schema\": {}\n },\n \"required\": [\n \"schema\"\n ],\n \"additionalProperties\": false\n}\n```\n\n**`as`:** Required. The validated answer, as a structured value.\n\n**Body context:** The request message the person is shown.\n\n**Returns:** a value — it renders nothing, and `as` binds what it returns.\n\n```json\n{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\"\n}\n```\n\n**Origin:** `@executablemd/core` (registered default)\n\n### ``\n\nEvaluate program text. `` runs it.\n\n**Forms:** ``, `…`\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `text` | `string` | no | The program to evaluate, for the self-closing form. Written instead of content, never beside it. |\n| `allow` | `array` | no | Optional. Which effect classes the program may draw on, narrowing what this host already installed. Omitted asks for `read`. |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"The program to evaluate, for the self-closing form. Written instead of content, never beside it.\"\n },\n \"allow\": {\n \"type\": \"array\",\n \"minItems\": 1,\n \"uniqueItems\": true,\n \"items\": {\n \"enum\": [\n \"read\",\n \"write\"\n ]\n },\n \"description\": \"Optional. Which effect classes the program may draw on, narrowing what this host already installed. Omitted asks for `read`.\"\n }\n },\n \"additionalProperties\": false\n}\n```\n\n**`as`:** Optional. Captures the fragment's rendered output instead of emitting it.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/core` (protected component)\n\n### ``\n\nStop authored work with an actionable failure. `` raises the message where it is written.\n\n**Forms:** ``\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `message` | `string` | yes | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"message\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n },\n \"required\": [\n \"message\"\n ],\n \"additionalProperties\": false\n}\n```\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/core` (registered default)\n\n### ``\n\nFetch a URL. `` binds the response, and any status is data you can branch on. Without `as`, a non-2xx status fails. Only GET and HEAD methods currently supported.\n\n**Forms:** ``, `…`\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `url` | `string` | yes | |\n| `method` | `string` | no | |\n| `headers` | `object` | no | |\n| `timeout` | `string` | no | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"url\": {\n \"type\": \"string\"\n },\n \"method\": {\n \"type\": \"string\"\n },\n \"headers\": {\n \"type\": \"object\",\n \"additionalProperties\": {\n \"type\": \"string\"\n }\n },\n \"timeout\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"url\"\n ],\n \"additionalProperties\": false\n}\n```\n\n**`as`:** Optional. Captures the response, which is what makes a non-2xx status data instead of a failure.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/core` (registered default)\n\n### ``\n\nRead or write a file. `` reads the content; `…` writes the content. The path is relative to the working directory.\n\n**Forms:** ``, `…`\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `path` | `string` | yes | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"path\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"path\"\n ],\n \"additionalProperties\": false\n}\n```\n\n**`as`:** Optional. Captures the file's text instead of emitting it, in the reading form.\n\n**Body context:** The text to write, in the writing form.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/core` (protected component)\n\n### ``\n\nDelete a file. `` removes it. It does not error if the file doesn't exist, and produces no output.\n\n**Forms:** ``\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `path` | `string` | yes | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"path\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n },\n \"required\": [\n \"path\"\n ],\n \"additionalProperties\": false\n}\n```\n\n**`as`:** Optional. Captures the empty string this renders, as for any text component.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/core` (protected component)\n\n### ``\n\nList files by pattern. `` matches paths relative to the working directory. The list is sorted. Directories and symbolic links are never results.\n\n**Forms:** ``, `…`\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `include` | `array` | yes | |\n| `exclude` | `array` | no | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"include\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n },\n \"minItems\": 1\n },\n \"exclude\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n },\n \"default\": []\n }\n },\n \"required\": [\n \"include\"\n ],\n \"additionalProperties\": false\n}\n```\n\n**`as`:** Required. The matched paths, as a string array.\n\n**Returns:** a value — it renders nothing, and `as` binds what it returns.\n\n```json\n{\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n}\n```\n\n**Origin:** `@executablemd/core` (registered default)\n\n### ``\n\nRender a value as JSON text. `` writes the JSON where you put it.\n\n**Forms:** ``\n\n#### Props\n\nThis component declares no individual props.\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {},\n \"additionalProperties\": false\n}\n```\n\n**Captures:** `value` — evaluated by the component itself, so these props are deliberately absent from the schema above.\n\n**`as`:** Optional. Captures the JSON text instead of emitting it.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/core` (registered default)\n\n### ``\n\nParse a value using a JSON schema. `…` parses its content. Errors on invalid content.\n\n**Forms:** ``, `…`\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `schema` | JSON Schema | yes | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"schema\": {}\n },\n \"required\": [\n \"schema\"\n ],\n \"additionalProperties\": false\n}\n```\n\n**`as`:** Required. The validated value.\n\n**Body context:** The JSON text to parse.\n\n**Returns:** a value — it renders nothing, and `as` binds what it returns.\n\n```json\n{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\"\n}\n```\n\n**Origin:** `@executablemd/core` (registered default)\n\n### ``\n\nSelect part of a value with a yq expression. `` binds the scripts object; the same element without `as` writes the selected value as JSON. Text is decoded only where the expression says `from_json` or `from_yaml`, and an expression that selects nothing or several values says to collect them with `[ … ]`.\n\n**Forms:** ``\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `value` | JSON Schema | yes | |\n| `yq` | `string` | yes | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"value\": {},\n \"yq\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n },\n \"required\": [\n \"value\",\n \"yq\"\n ],\n \"additionalProperties\": false\n}\n```\n\n**`as`:** Optional. Binds the selected value as data instead of writing it as JSON.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/core` (registered default)\n\n### ``\n\nParse a value using a JSON schema. `…` parses its content. Binds a result object instead of erroring.\n\n**Forms:** ``, `…`\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `schema` | JSON Schema | yes | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"schema\": {}\n },\n \"required\": [\n \"schema\"\n ],\n \"additionalProperties\": false\n}\n```\n\n**`as`:** Required. The result: either the validated value or the issues that rejected it.\n\n**Body context:** The JSON text to parse.\n\n**Returns:** a value — it renders nothing, and `as` binds what it returns.\n\n```json\n{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"oneOf\": [\n {\n \"type\": \"object\",\n \"properties\": {\n \"ok\": {\n \"const\": true\n },\n \"value\": {}\n },\n \"required\": [\n \"ok\",\n \"value\"\n ],\n \"additionalProperties\": false\n },\n {\n \"type\": \"object\",\n \"properties\": {\n \"ok\": {\n \"const\": false\n },\n \"input\": {\n \"type\": \"string\"\n },\n \"errors\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"instancePath\": {\n \"type\": \"string\"\n },\n \"schemaPath\": {\n \"type\": \"string\"\n },\n \"keyword\": {\n \"type\": \"string\"\n },\n \"params\": {},\n \"message\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"instancePath\",\n \"schemaPath\",\n \"keyword\",\n \"params\",\n \"message\"\n ],\n \"additionalProperties\": false\n }\n }\n },\n \"required\": [\n \"ok\",\n \"input\",\n \"errors\"\n ],\n \"additionalProperties\": false\n }\n ]\n}\n```\n\n**Origin:** `@executablemd/core` (registered default)\n\n### ``\n\nShow a window of rendered text. `…` counts Unicode code points and labels partial excerpts.\n\n**Forms:** ``, `…`\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `offset` | `integer` | no | |\n| `length` | `integer` | no | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"offset\": {\n \"type\": \"integer\",\n \"default\": 0\n },\n \"length\": {\n \"type\": \"integer\",\n \"minimum\": 1,\n \"default\": 4096\n }\n },\n \"additionalProperties\": false\n}\n```\n\n**`as`:** Optional. Captures the resulting text, including any range note, instead of emitting it.\n\n**Body context:** The content whose completed rendering the window is taken from.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/core` (registered default)\n\n### ``\n\nInspect available components and control-flow constructs. `` lists the symbols available here; `` renders selected documentation.\n\n**Forms:** ``\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `names` | `array` | no | Optional. Render complete references for these structural or component names instead of the list of available symbols. Entries render once each, in symbol order. |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"names\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n },\n \"minItems\": 1,\n \"uniqueItems\": true,\n \"description\": \"Optional. Render complete references for these structural or component names instead of the list of available symbols. Entries render once each, in symbol order.\"\n }\n },\n \"additionalProperties\": false\n}\n```\n\n**`as`:** Optional. Captures the rendered text instead of emitting it.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/core` (protected component)\n\n### ``\n\nRun work in a temporary working directory. `…` expands its content with the temporary directory as the working directory, so `` and commands inside write there rather than in the current one. `` renders the path instead.\n\n**Forms:** ``, `…`\n\n#### Props\n\nThis component declares no individual props.\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {},\n \"additionalProperties\": false\n}\n```\n\n**`as`:** Optional. Captures the rendered directory path instead of emitting it.\n\n**Body context:** Markdown expanded with the temporary directory as its working directory.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/core` (registered default)\n\n### ``\n\nDefine a test. `…` runs under `xmd test`, or inside a `` region; elsewhere it is skipped. A failing command or assertion inside fails the test rather than the document.\n\n**Forms:** ``, `…`\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `name` | `string` | no | |\n| `timeout` | `string` | no | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\"\n },\n \"timeout\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n}\n```\n\n**Body context:** The body of the test: its assertions and the work they judge.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/core` (registered default)\n\n### ``\n\nRender a value as YAML text. `` writes the YAML where you put it.\n\n**Forms:** ``\n\n#### Props\n\nThis component declares no individual props.\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {},\n \"additionalProperties\": false\n}\n```\n\n**Captures:** `value` — evaluated by the component itself, so these props are deliberately absent from the schema above.\n\n**`as`:** Optional. Captures the YAML text instead of emitting it.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/core` (registered default)\n\n## User-provided components\n\nNo components were found in the configured includes.\n", + "catalog-base.json": "{\"version\":1,\"categories\":[{\"kind\":\"structural\",\"entries\":[{\"kind\":\"structural\",\"name\":\"All\",\"origin\":{\"kind\":\"structural\",\"construct\":\"All\"},\"syntax\":[\"……\"],\"description\":\"Run tasks in parallel. `firstsecond` expands every task at the same time, waits for them all to succeed, and preserves their Markdown order. Write at least two `` children directly inside it; if one fails, unfinished tasks are cancelled and `` produces no output.\",\"context\":\"The `` children this runs at the same time.\"},{\"kind\":\"structural\",\"name\":\"Answer\",\"origin\":{\"kind\":\"structural\",\"construct\":\"Answer\"},\"syntax\":[\"\",\"…\"],\"description\":\"Supply one answer inside ``. `` answers any elicitation its template matches — `{?name}` matches any text. The first matching `` wins.\",\"context\":\"A multiline template, in place of the single-line `template` prop.\"},{\"kind\":\"structural\",\"name\":\"Answers\",\"origin\":{\"kind\":\"structural\",\"construct\":\"Answers\"},\"syntax\":[\"…\"],\"description\":\"Answer any `` in its content without asking a person. `…` replies from the `` matchers declared inside it, reaching elicitations from nested components too. `delegate` passes an unmatched one outward instead of failing.\",\"context\":\"`` matchers, and the body they answer for.\"},{\"kind\":\"structural\",\"name\":\"Break\",\"origin\":{\"kind\":\"structural\",\"construct\":\"Break\"},\"syntax\":[\"\"],\"description\":\"Exit the nearest enclosing ``. `` stops the current iteration where it is; nothing after it in that iteration runs.\"},{\"kind\":\"structural\",\"name\":\"Case\",\"origin\":{\"kind\":\"structural\",\"construct\":\"Case\"},\"syntax\":[\"…\",\"…\"],\"description\":\"Define one branch of a ``. `…` matches with `===`; `…` is the final fallback.\",\"context\":\"Markdown expanded when this case is selected.\"},{\"kind\":\"structural\",\"name\":\"Catch\",\"origin\":{\"kind\":\"structural\",\"construct\":\"Catch\"},\"syntax\":[\"…\",\"…\"],\"description\":\"Handle a failure in the preceding Try body. `{error.message}` runs after clean release; its bindings stay local. Cancellation skips this branch.\",\"as\":\"Optional. Binds the ordinary Error by reference in this branch.\",\"context\":\"Recovery content.\"},{\"kind\":\"structural\",\"name\":\"Content\",\"origin\":{\"kind\":\"structural\",\"construct\":\"Content\"},\"syntax\":[\"\",\"\"],\"description\":\"Render what the caller wrote inside this component. `` renders all of it; `` renders just the part the caller marked `slot=\\\"footer\\\"`.\"},{\"kind\":\"structural\",\"name\":\"Each\",\"origin\":{\"kind\":\"structural\",\"construct\":\"Each\"},\"syntax\":[\"…\"],\"description\":\"Repeat content for each item in an array. `…` binds each one to `item` inside.\",\"as\":\"Optional. Captures the whole rendered loop instead of emitting it.\",\"context\":\"Markdown rendered once per element.\"},{\"kind\":\"structural\",\"name\":\"Else\",\"origin\":{\"kind\":\"structural\",\"construct\":\"Else\"},\"syntax\":[\"…\"],\"description\":\"The branch `` takes when its condition is false. `…` is written directly inside an ``, and is an error anywhere else.\",\"context\":\"The branch taken when the enclosing condition does not hold.\"},{\"kind\":\"structural\",\"name\":\"Finally\",\"origin\":{\"kind\":\"structural\",\"construct\":\"Finally\"},\"syntax\":[\"…\"],\"description\":\"Finish a Try after its attempted body and recovery. `Cleanup.` also runs and joins on terminal Stop. Resumable Exit leaves an unentered branch pending; failed release and infrastructure failure prevent new entry.\",\"context\":\"Completion content using the surrounding bindings.\"},{\"kind\":\"structural\",\"name\":\"If\",\"origin\":{\"kind\":\"structural\",\"construct\":\"If\"},\"syntax\":[\"…\"],\"description\":\"Expand content only when a condition is true. `…` expands its content, or the `` branch instead. The branch not taken never runs.\",\"context\":\"The branch taken when the condition holds, up to an ``.\"},{\"kind\":\"structural\",\"name\":\"Let\",\"origin\":{\"kind\":\"structural\",\"construct\":\"Let\"},\"syntax\":[\"…\",\"\"],\"description\":\"Bind a name for the rest of the region. `…` binds what its content rendered; `` binds the value. `select` narrows the rendered content to one CSS selection.\",\"as\":\"Required. The binding name the value is available under.\",\"context\":\"Markdown whose rendered text becomes the binding, in the paired form.\"},{\"kind\":\"structural\",\"name\":\"Loop\",\"origin\":{\"kind\":\"structural\",\"construct\":\"Loop\"},\"syntax\":[\"…\"],\"description\":\"Repeat content up to `max` times. `…` expands its content again and again until a `` inside it, or until `max` is reached. `max` is required.\",\"context\":\"Markdown expanded once per iteration.\"},{\"kind\":\"structural\",\"name\":\"Output\",\"origin\":{\"kind\":\"structural\",\"construct\":\"Output\"},\"syntax\":[\"…\"],\"description\":\"Restrict what a document or component renders. `…` becomes its entire output; anything outside the region is not rendered.\",\"context\":\"The rendered output the run presents.\"},{\"kind\":\"structural\",\"name\":\"PrintErrors\",\"origin\":{\"kind\":\"structural\",\"construct\":\"PrintErrors\"},\"syntax\":[\"…\"],\"description\":\"Convert thrown errors into output without failing. `…` renders any failure inside it as part of the output.\",\"context\":\"The region whose failures are printed rather than raised.\"},{\"kind\":\"structural\",\"name\":\"Return\",\"origin\":{\"kind\":\"structural\",\"construct\":\"Return\"},\"syntax\":[\"\"],\"description\":\"Return a value instead of rendered markdown. `` hands the value to the caller, checked against the component's declared `returns` schema.\"},{\"kind\":\"structural\",\"name\":\"Spawn\",\"origin\":{\"kind\":\"structural\",\"construct\":\"Spawn\"},\"syntax\":[\"…\"],\"description\":\"Run a task in parallel inside of ``. Write `…` directly inside ``; bindings made in its content stay with that task, and `` or `` cannot affect work outside it.\",\"context\":\"Markdown expanded in its own child, beside its siblings.\"},{\"kind\":\"structural\",\"name\":\"Switch\",\"origin\":{\"kind\":\"structural\",\"construct\":\"Switch\"},\"syntax\":[\"…\"],\"description\":\"Choose one branch by comparing a value with `===`. `……` expands the first matching case, or the final default when none matches.\",\"context\":\"Direct `` branches considered in source order.\"},{\"kind\":\"structural\",\"name\":\"Try\",\"origin\":{\"kind\":\"structural\",\"construct\":\"Try\"},\"syntax\":[\"………\"],\"description\":\"Recover an ordinary failure after its resources close. `…fallback` keeps the rendered prefix and stops the attempted body at failure. Write Catch, Finally, or both. Failed release and infrastructure failures end execution.\",\"context\":\"Attempted content followed by direct Catch and Finally branches.\"}]},{\"kind\":\"built-in\",\"entries\":[{\"kind\":\"component\",\"name\":\"CodeBlock\",\"origin\":{\"kind\":\"registered\",\"origin\":\"@executablemd/core\",\"reserved\":false},\"sourceKind\":\"registered\",\"inspectability\":\"complete\",\"forms\":[\"self-closing\"],\"props\":{\"type\":\"object\",\"properties\":{\"value\":{\"type\":\"string\"},\"language\":{\"type\":\"string\",\"pattern\":\"^[A-Za-z0-9][A-Za-z0-9._+#-]*$\"}},\"required\":[\"value\"],\"additionalProperties\":false},\"captures\":[],\"returnMode\":\"text\",\"returns\":{\"type\":\"string\"},\"description\":\"Show arbitrary text as a fenced Markdown code block. `` chooses a fence the value cannot close.\",\"as\":\"Optional. Captures the exact fenced Markdown instead of emitting it.\"},{\"kind\":\"component\",\"name\":\"Cwd\",\"origin\":{\"kind\":\"registered\",\"origin\":\"@executablemd/core\",\"reserved\":false},\"sourceKind\":\"registered\",\"inspectability\":\"complete\",\"forms\":[\"self-closing\"],\"props\":{\"type\":\"object\",\"properties\":{},\"additionalProperties\":false},\"captures\":[],\"returnMode\":\"text\",\"returns\":{\"type\":\"string\"},\"description\":\"Read the working directory. `` renders its path without adding a newline.\",\"as\":\"Optional. Captures the directory path instead of emitting it.\"},{\"kind\":\"component\",\"name\":\"Dir\",\"origin\":{\"kind\":\"protected\",\"origin\":\"@executablemd/core\"},\"sourceKind\":\"protected\",\"inspectability\":\"complete\",\"forms\":[\"paired\"],\"props\":{\"type\":\"object\",\"properties\":{\"path\":{\"type\":\"string\",\"minLength\":1}},\"required\":[\"path\"],\"additionalProperties\":false},\"captures\":[],\"returnMode\":\"text\",\"returns\":{\"type\":\"string\"},\"description\":\"Create or use a directory. `…` changes the working directory for its content.\",\"context\":\"The Markdown expanded in that directory.\"},{\"kind\":\"component\",\"name\":\"Elicit\",\"origin\":{\"kind\":\"registered\",\"origin\":\"@executablemd/core\",\"reserved\":false},\"sourceKind\":\"registered\",\"inspectability\":\"complete\",\"forms\":[\"self-closing\",\"paired\"],\"props\":{\"type\":\"object\",\"properties\":{\"schema\":{}},\"required\":[\"schema\"],\"additionalProperties\":false},\"captures\":[],\"returnMode\":\"value\",\"returns\":{\"$schema\":\"http://json-schema.org/draft-07/schema#\"},\"description\":\"Ask a person a structured question. `…` shows the content as the request.\",\"as\":\"Required. The validated answer, as a structured value.\",\"context\":\"The request message the person is shown.\"},{\"kind\":\"component\",\"name\":\"Evaluate\",\"origin\":{\"kind\":\"protected\",\"origin\":\"@executablemd/core\"},\"sourceKind\":\"protected\",\"inspectability\":\"complete\",\"forms\":[\"self-closing\",\"paired\"],\"props\":{\"type\":\"object\",\"properties\":{\"text\":{\"type\":\"string\",\"description\":\"The program to evaluate, for the self-closing form. Written instead of content, never beside it.\"},\"allow\":{\"type\":\"array\",\"minItems\":1,\"uniqueItems\":true,\"items\":{\"enum\":[\"read\",\"write\"]},\"description\":\"Optional. Which effect classes the program may draw on, narrowing what this host already installed. Omitted asks for `read`.\"}},\"additionalProperties\":false},\"captures\":[],\"returnMode\":\"text\",\"returns\":{\"type\":\"string\"},\"description\":\"Evaluate program text. `` runs it.\",\"as\":\"Optional. Captures the fragment's rendered output instead of emitting it.\"},{\"kind\":\"component\",\"name\":\"Fail\",\"origin\":{\"kind\":\"registered\",\"origin\":\"@executablemd/core\",\"reserved\":false},\"sourceKind\":\"registered\",\"inspectability\":\"complete\",\"forms\":[\"self-closing\"],\"props\":{\"type\":\"object\",\"properties\":{\"message\":{\"type\":\"string\",\"minLength\":1}},\"required\":[\"message\"],\"additionalProperties\":false},\"captures\":[],\"returnMode\":\"text\",\"returns\":{\"type\":\"string\"},\"description\":\"Stop authored work with an actionable failure. `` raises the message where it is written.\"},{\"kind\":\"component\",\"name\":\"Fetch\",\"origin\":{\"kind\":\"registered\",\"origin\":\"@executablemd/core\",\"reserved\":false},\"sourceKind\":\"registered\",\"inspectability\":\"complete\",\"forms\":[\"self-closing\",\"paired\"],\"props\":{\"type\":\"object\",\"properties\":{\"url\":{\"type\":\"string\"},\"method\":{\"type\":\"string\"},\"headers\":{\"type\":\"object\",\"additionalProperties\":{\"type\":\"string\"}},\"timeout\":{\"type\":\"string\"}},\"required\":[\"url\"],\"additionalProperties\":false},\"captures\":[],\"returnMode\":\"text\",\"returns\":{\"type\":\"string\"},\"description\":\"Fetch a URL. `` binds the response, and any status is data you can branch on. Without `as`, a non-2xx status fails. Only GET and HEAD methods currently supported.\",\"as\":\"Optional. Captures the response, which is what makes a non-2xx status data instead of a failure.\"},{\"kind\":\"component\",\"name\":\"File\",\"origin\":{\"kind\":\"protected\",\"origin\":\"@executablemd/core\"},\"sourceKind\":\"protected\",\"inspectability\":\"complete\",\"forms\":[\"self-closing\",\"paired\"],\"props\":{\"type\":\"object\",\"properties\":{\"path\":{\"type\":\"string\"}},\"required\":[\"path\"],\"additionalProperties\":false},\"captures\":[],\"returnMode\":\"text\",\"returns\":{\"type\":\"string\"},\"description\":\"Read or write a file. `` reads the content; `…` writes the content. The path is relative to the working directory.\",\"as\":\"Optional. Captures the file's text instead of emitting it, in the reading form.\",\"context\":\"The text to write, in the writing form.\"},{\"kind\":\"component\",\"name\":\"File.Delete\",\"origin\":{\"kind\":\"protected\",\"origin\":\"@executablemd/core\"},\"sourceKind\":\"protected\",\"inspectability\":\"complete\",\"forms\":[\"self-closing\"],\"props\":{\"type\":\"object\",\"properties\":{\"path\":{\"type\":\"string\",\"minLength\":1}},\"required\":[\"path\"],\"additionalProperties\":false},\"captures\":[],\"returnMode\":\"text\",\"returns\":{\"type\":\"string\"},\"description\":\"Delete a file. `` removes it. It does not error if the file doesn't exist, and produces no output.\",\"as\":\"Optional. Captures the empty string this renders, as for any text component.\"},{\"kind\":\"component\",\"name\":\"Glob\",\"origin\":{\"kind\":\"registered\",\"origin\":\"@executablemd/core\",\"reserved\":false},\"sourceKind\":\"registered\",\"inspectability\":\"complete\",\"forms\":[\"self-closing\",\"paired\"],\"props\":{\"type\":\"object\",\"properties\":{\"include\":{\"type\":\"array\",\"items\":{\"type\":\"string\"},\"minItems\":1},\"exclude\":{\"type\":\"array\",\"items\":{\"type\":\"string\"},\"default\":[]}},\"required\":[\"include\"],\"additionalProperties\":false},\"captures\":[],\"returnMode\":\"value\",\"returns\":{\"type\":\"array\",\"items\":{\"type\":\"string\"}},\"description\":\"List files by pattern. `` matches paths relative to the working directory. The list is sorted. Directories and symbolic links are never results.\",\"as\":\"Required. The matched paths, as a string array.\"},{\"kind\":\"component\",\"name\":\"Json\",\"origin\":{\"kind\":\"registered\",\"origin\":\"@executablemd/core\",\"reserved\":false},\"sourceKind\":\"registered\",\"inspectability\":\"complete\",\"forms\":[\"self-closing\"],\"props\":{\"type\":\"object\",\"properties\":{},\"additionalProperties\":false},\"captures\":[\"value\"],\"returnMode\":\"text\",\"returns\":{\"type\":\"string\"},\"description\":\"Render a value as JSON text. `` writes the JSON where you put it.\",\"as\":\"Optional. Captures the JSON text instead of emitting it.\"},{\"kind\":\"component\",\"name\":\"Parse\",\"origin\":{\"kind\":\"registered\",\"origin\":\"@executablemd/core\",\"reserved\":false},\"sourceKind\":\"registered\",\"inspectability\":\"complete\",\"forms\":[\"self-closing\",\"paired\"],\"props\":{\"type\":\"object\",\"properties\":{\"schema\":{}},\"required\":[\"schema\"],\"additionalProperties\":false},\"captures\":[],\"returnMode\":\"value\",\"returns\":{\"$schema\":\"http://json-schema.org/draft-07/schema#\"},\"description\":\"Parse a value using a JSON schema. `…` parses its content. Errors on invalid content.\",\"as\":\"Required. The validated value.\",\"context\":\"The JSON text to parse.\"},{\"kind\":\"component\",\"name\":\"Query\",\"origin\":{\"kind\":\"registered\",\"origin\":\"@executablemd/core\",\"reserved\":false},\"sourceKind\":\"registered\",\"inspectability\":\"complete\",\"forms\":[\"self-closing\"],\"props\":{\"type\":\"object\",\"properties\":{\"value\":{},\"yq\":{\"type\":\"string\",\"minLength\":1}},\"required\":[\"value\",\"yq\"],\"additionalProperties\":false},\"captures\":[],\"returnMode\":\"text\",\"returns\":{\"type\":\"string\"},\"description\":\"Select part of a value with a yq expression. `` binds the scripts object; the same element without `as` writes the selected value as JSON. Text is decoded only where the expression says `from_json` or `from_yaml`, and an expression that selects nothing or several values says to collect them with `[ … ]`.\",\"as\":\"Optional. Binds the selected value as data instead of writing it as JSON.\"},{\"kind\":\"component\",\"name\":\"SafeParse\",\"origin\":{\"kind\":\"registered\",\"origin\":\"@executablemd/core\",\"reserved\":false},\"sourceKind\":\"registered\",\"inspectability\":\"complete\",\"forms\":[\"self-closing\",\"paired\"],\"props\":{\"type\":\"object\",\"properties\":{\"schema\":{}},\"required\":[\"schema\"],\"additionalProperties\":false},\"captures\":[],\"returnMode\":\"value\",\"returns\":{\"$schema\":\"http://json-schema.org/draft-07/schema#\",\"oneOf\":[{\"type\":\"object\",\"properties\":{\"ok\":{\"const\":true},\"value\":{}},\"required\":[\"ok\",\"value\"],\"additionalProperties\":false},{\"type\":\"object\",\"properties\":{\"ok\":{\"const\":false},\"input\":{\"type\":\"string\"},\"errors\":{\"type\":\"array\",\"items\":{\"type\":\"object\",\"properties\":{\"instancePath\":{\"type\":\"string\"},\"schemaPath\":{\"type\":\"string\"},\"keyword\":{\"type\":\"string\"},\"params\":{},\"message\":{\"type\":\"string\"}},\"required\":[\"instancePath\",\"schemaPath\",\"keyword\",\"params\",\"message\"],\"additionalProperties\":false}}},\"required\":[\"ok\",\"input\",\"errors\"],\"additionalProperties\":false}]},\"description\":\"Parse a value using a JSON schema. `…` parses its content. Binds a result object instead of erroring.\",\"as\":\"Required. The result: either the validated value or the issues that rejected it.\",\"context\":\"The JSON text to parse.\"},{\"kind\":\"component\",\"name\":\"Slice\",\"origin\":{\"kind\":\"registered\",\"origin\":\"@executablemd/core\",\"reserved\":false},\"sourceKind\":\"registered\",\"inspectability\":\"complete\",\"forms\":[\"self-closing\",\"paired\"],\"props\":{\"type\":\"object\",\"properties\":{\"offset\":{\"type\":\"integer\",\"default\":0},\"length\":{\"type\":\"integer\",\"minimum\":1,\"default\":4096}},\"additionalProperties\":false},\"captures\":[],\"returnMode\":\"text\",\"returns\":{\"type\":\"string\"},\"description\":\"Show a window of rendered text. `…` counts Unicode code points and labels partial excerpts.\",\"as\":\"Optional. Captures the resulting text, including any range note, instead of emitting it.\",\"context\":\"The content whose completed rendering the window is taken from.\"},{\"kind\":\"component\",\"name\":\"Syntax\",\"origin\":{\"kind\":\"protected\",\"origin\":\"@executablemd/core\"},\"sourceKind\":\"protected\",\"inspectability\":\"complete\",\"forms\":[\"self-closing\"],\"props\":{\"type\":\"object\",\"properties\":{\"names\":{\"type\":\"array\",\"items\":{\"type\":\"string\"},\"minItems\":1,\"uniqueItems\":true,\"description\":\"Optional. Render complete references for these structural or component names instead of the list of available symbols. Entries render once each, in symbol order.\"}},\"additionalProperties\":false},\"captures\":[],\"returnMode\":\"text\",\"returns\":{\"type\":\"string\"},\"description\":\"Inspect available components and control-flow constructs. `` lists the symbols available here; `` renders selected documentation.\",\"as\":\"Optional. Captures the rendered text instead of emitting it.\"},{\"kind\":\"component\",\"name\":\"TempDir\",\"origin\":{\"kind\":\"registered\",\"origin\":\"@executablemd/core\",\"reserved\":false},\"sourceKind\":\"registered\",\"inspectability\":\"complete\",\"forms\":[\"self-closing\",\"paired\"],\"props\":{\"type\":\"object\",\"properties\":{},\"additionalProperties\":false},\"captures\":[],\"returnMode\":\"text\",\"returns\":{\"type\":\"string\"},\"description\":\"Run work in a temporary working directory. `…` expands its content with the temporary directory as the working directory, so `` and commands inside write there rather than in the current one. `` renders the path instead.\",\"as\":\"Optional. Captures the rendered directory path instead of emitting it.\",\"context\":\"Markdown expanded with the temporary directory as its working directory.\"},{\"kind\":\"component\",\"name\":\"Test\",\"origin\":{\"kind\":\"registered\",\"origin\":\"@executablemd/core\",\"reserved\":false},\"sourceKind\":\"registered\",\"inspectability\":\"complete\",\"forms\":[\"self-closing\",\"paired\"],\"props\":{\"type\":\"object\",\"properties\":{\"name\":{\"type\":\"string\"},\"timeout\":{\"type\":\"string\"}},\"additionalProperties\":false},\"captures\":[],\"returnMode\":\"text\",\"returns\":{\"type\":\"string\"},\"description\":\"Define a test. `…` runs under `xmd test`, or inside a `` region; elsewhere it is skipped. A failing command or assertion inside fails the test rather than the document.\",\"context\":\"The body of the test: its assertions and the work they judge.\"},{\"kind\":\"component\",\"name\":\"Yaml\",\"origin\":{\"kind\":\"registered\",\"origin\":\"@executablemd/core\",\"reserved\":false},\"sourceKind\":\"registered\",\"inspectability\":\"complete\",\"forms\":[\"self-closing\"],\"props\":{\"type\":\"object\",\"properties\":{},\"additionalProperties\":false},\"captures\":[\"value\"],\"returnMode\":\"text\",\"returns\":{\"type\":\"string\"},\"description\":\"Render a value as YAML text. `` writes the YAML where you put it.\",\"as\":\"Optional. Captures the YAML text instead of emitting it.\"}]},{\"kind\":\"user-provided\",\"entries\":[]}]}", + "ordinary-base.txt": "## Built-in structural syntax\n\n### ``\n\nRun tasks in parallel. `firstsecond` expands every task at the same time, waits for them all to succeed, and preserves their Markdown order. Write at least two `` children directly inside it; if one fails, unfinished tasks are cancelled and `` produces no output.\n\n**Syntax:**\n\n```md\n……\n```\n\n**Body context:** The `` children this runs at the same time.\n\n### ``\n\nSupply one answer inside ``. `` answers any elicitation its template matches — `{?name}` matches any text. The first matching `` wins.\n\n**Syntax:**\n\n```md\n\n…\n```\n\n**Body context:** A multiline template, in place of the single-line `template` prop.\n\n### ``\n\nAnswer any `` in its content without asking a person. `…` replies from the `` matchers declared inside it, reaching elicitations from nested components too. `delegate` passes an unmatched one outward instead of failing.\n\n**Syntax:**\n\n```md\n…\n```\n\n**Body context:** `` matchers, and the body they answer for.\n\n### ``\n\nExit the nearest enclosing ``. `` stops the current iteration where it is; nothing after it in that iteration runs.\n\n**Syntax:**\n\n```md\n\n```\n\n### ``\n\nDefine one branch of a ``. `…` matches with `===`; `…` is the final fallback.\n\n**Syntax:**\n\n```md\n…\n…\n```\n\n**Body context:** Markdown expanded when this case is selected.\n\n### ``\n\nHandle a failure in the preceding Try body. `{error.message}` runs after clean release; its bindings stay local. Cancellation skips this branch.\n\n**Syntax:**\n\n```md\n…\n…\n```\n\n**`as`:** Optional. Binds the ordinary Error by reference in this branch.\n\n**Body context:** Recovery content.\n\n### ``\n\nRender what the caller wrote inside this component. `` renders all of it; `` renders just the part the caller marked `slot=\"footer\"`.\n\n**Syntax:**\n\n```md\n\n\n```\n\n### ``\n\nRepeat content for each item in an array. `…` binds each one to `item` inside.\n\n**Syntax:**\n\n```md\n…\n```\n\n**`as`:** Optional. Captures the whole rendered loop instead of emitting it.\n\n**Body context:** Markdown rendered once per element.\n\n### ``\n\nThe branch `` takes when its condition is false. `…` is written directly inside an ``, and is an error anywhere else.\n\n**Syntax:**\n\n```md\n…\n```\n\n**Body context:** The branch taken when the enclosing condition does not hold.\n\n### ``\n\nFinish a Try after its attempted body and recovery. `Cleanup.` also runs and joins on terminal Stop. Resumable Exit leaves an unentered branch pending; failed release and infrastructure failure prevent new entry.\n\n**Syntax:**\n\n```md\n…\n```\n\n**Body context:** Completion content using the surrounding bindings.\n\n### ``\n\nExpand content only when a condition is true. `…` expands its content, or the `` branch instead. The branch not taken never runs.\n\n**Syntax:**\n\n```md\n…\n```\n\n**Body context:** The branch taken when the condition holds, up to an ``.\n\n### ``\n\nBind a name for the rest of the region. `…` binds what its content rendered; `` binds the value. `select` narrows the rendered content to one CSS selection.\n\n**Syntax:**\n\n```md\n…\n\n```\n\n**`as`:** Required. The binding name the value is available under.\n\n**Body context:** Markdown whose rendered text becomes the binding, in the paired form.\n\n### ``\n\nRepeat content up to `max` times. `…` expands its content again and again until a `` inside it, or until `max` is reached. `max` is required.\n\n**Syntax:**\n\n```md\n…\n```\n\n**Body context:** Markdown expanded once per iteration.\n\n### ``\n\nRestrict what a document or component renders. `…` becomes its entire output; anything outside the region is not rendered.\n\n**Syntax:**\n\n```md\n…\n```\n\n**Body context:** The rendered output the run presents.\n\n### ``\n\nConvert thrown errors into output without failing. `…` renders any failure inside it as part of the output.\n\n**Syntax:**\n\n```md\n…\n```\n\n**Body context:** The region whose failures are printed rather than raised.\n\n### ``\n\nReturn a value instead of rendered markdown. `` hands the value to the caller, checked against the component's declared `returns` schema.\n\n**Syntax:**\n\n```md\n\n```\n\n### ``\n\nRun a task in parallel inside of ``. Write `…` directly inside ``; bindings made in its content stay with that task, and `` or `` cannot affect work outside it.\n\n**Syntax:**\n\n```md\n…\n```\n\n**Body context:** Markdown expanded in its own child, beside its siblings.\n\n### ``\n\nChoose one branch by comparing a value with `===`. `……` expands the first matching case, or the final default when none matches.\n\n**Syntax:**\n\n```md\n…\n```\n\n**Body context:** Direct `` branches considered in source order.\n\n### ``\n\nRecover an ordinary failure after its resources close. `…fallback` keeps the rendered prefix and stops the attempted body at failure. Write Catch, Finally, or both. Failed release and infrastructure failures end execution.\n\n**Syntax:**\n\n```md\n………\n```\n\n**Body context:** Attempted content followed by direct Catch and Finally branches.\n\n## Built-in components\n\n### ``\n\nShow arbitrary text as a fenced Markdown code block. `` chooses a fence the value cannot close.\n\n**Forms:** ``\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `value` | `string` | yes | |\n| `language` | `string` | no | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"value\": {\n \"type\": \"string\"\n },\n \"language\": {\n \"type\": \"string\",\n \"pattern\": \"^[A-Za-z0-9][A-Za-z0-9._+#-]*$\"\n }\n },\n \"required\": [\n \"value\"\n ],\n \"additionalProperties\": false\n}\n```\n\n**`as`:** Optional. Captures the exact fenced Markdown instead of emitting it.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/core` (registered default)\n\n### ``\n\nRead the working directory. `` renders its path without adding a newline.\n\n**Forms:** ``\n\n#### Props\n\nThis component declares no individual props.\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {},\n \"additionalProperties\": false\n}\n```\n\n**`as`:** Optional. Captures the directory path instead of emitting it.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/core` (registered default)\n\n### ``\n\nCreate or use a directory. `…` changes the working directory for its content.\n\n**Forms:** `…`\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `path` | `string` | yes | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"path\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n },\n \"required\": [\n \"path\"\n ],\n \"additionalProperties\": false\n}\n```\n\n**Body context:** The Markdown expanded in that directory.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/core` (protected component)\n\n### ``\n\nAsk a person a structured question. `…` shows the content as the request.\n\n**Forms:** ``, `…`\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `schema` | JSON Schema | yes | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"schema\": {}\n },\n \"required\": [\n \"schema\"\n ],\n \"additionalProperties\": false\n}\n```\n\n**`as`:** Required. The validated answer, as a structured value.\n\n**Body context:** The request message the person is shown.\n\n**Returns:** a value — it renders nothing, and `as` binds what it returns.\n\n```json\n{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\"\n}\n```\n\n**Origin:** `@executablemd/core` (registered default)\n\n### ``\n\nEvaluate program text. `` runs it.\n\n**Forms:** ``, `…`\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `text` | `string` | no | The program to evaluate, for the self-closing form. Written instead of content, never beside it. |\n| `allow` | `array` | no | Optional. Which effect classes the program may draw on, narrowing what this host already installed. Omitted asks for `read`. |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"The program to evaluate, for the self-closing form. Written instead of content, never beside it.\"\n },\n \"allow\": {\n \"type\": \"array\",\n \"minItems\": 1,\n \"uniqueItems\": true,\n \"items\": {\n \"enum\": [\n \"read\",\n \"write\"\n ]\n },\n \"description\": \"Optional. Which effect classes the program may draw on, narrowing what this host already installed. Omitted asks for `read`.\"\n }\n },\n \"additionalProperties\": false\n}\n```\n\n**`as`:** Optional. Captures the fragment's rendered output instead of emitting it.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/core` (protected component)\n\n### ``\n\nStop authored work with an actionable failure. `` raises the message where it is written.\n\n**Forms:** ``\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `message` | `string` | yes | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"message\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n },\n \"required\": [\n \"message\"\n ],\n \"additionalProperties\": false\n}\n```\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/core` (registered default)\n\n### ``\n\nFetch a URL. `` binds the response, and any status is data you can branch on. Without `as`, a non-2xx status fails. Only GET and HEAD methods currently supported.\n\n**Forms:** ``, `…`\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `url` | `string` | yes | |\n| `method` | `string` | no | |\n| `headers` | `object` | no | |\n| `timeout` | `string` | no | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"url\": {\n \"type\": \"string\"\n },\n \"method\": {\n \"type\": \"string\"\n },\n \"headers\": {\n \"type\": \"object\",\n \"additionalProperties\": {\n \"type\": \"string\"\n }\n },\n \"timeout\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"url\"\n ],\n \"additionalProperties\": false\n}\n```\n\n**`as`:** Optional. Captures the response, which is what makes a non-2xx status data instead of a failure.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/core` (registered default)\n\n### ``\n\nRead or write a file. `` reads the content; `…` writes the content. The path is relative to the working directory.\n\n**Forms:** ``, `…`\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `path` | `string` | yes | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"path\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"path\"\n ],\n \"additionalProperties\": false\n}\n```\n\n**`as`:** Optional. Captures the file's text instead of emitting it, in the reading form.\n\n**Body context:** The text to write, in the writing form.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/core` (protected component)\n\n### ``\n\nDelete a file. `` removes it. It does not error if the file doesn't exist, and produces no output.\n\n**Forms:** ``\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `path` | `string` | yes | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"path\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n },\n \"required\": [\n \"path\"\n ],\n \"additionalProperties\": false\n}\n```\n\n**`as`:** Optional. Captures the empty string this renders, as for any text component.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/core` (protected component)\n\n### ``\n\nList files by pattern. `` matches paths relative to the working directory. The list is sorted. Directories and symbolic links are never results.\n\n**Forms:** ``, `…`\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `include` | `array` | yes | |\n| `exclude` | `array` | no | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"include\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n },\n \"minItems\": 1\n },\n \"exclude\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n },\n \"default\": []\n }\n },\n \"required\": [\n \"include\"\n ],\n \"additionalProperties\": false\n}\n```\n\n**`as`:** Required. The matched paths, as a string array.\n\n**Returns:** a value — it renders nothing, and `as` binds what it returns.\n\n```json\n{\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n}\n```\n\n**Origin:** `@executablemd/core` (registered default)\n\n### ``\n\nRender a value as JSON text. `` writes the JSON where you put it.\n\n**Forms:** ``\n\n#### Props\n\nThis component declares no individual props.\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {},\n \"additionalProperties\": false\n}\n```\n\n**Captures:** `value` — evaluated by the component itself, so these props are deliberately absent from the schema above.\n\n**`as`:** Optional. Captures the JSON text instead of emitting it.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/core` (registered default)\n\n### ``\n\nParse a value using a JSON schema. `…` parses its content. Errors on invalid content.\n\n**Forms:** ``, `…`\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `schema` | JSON Schema | yes | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"schema\": {}\n },\n \"required\": [\n \"schema\"\n ],\n \"additionalProperties\": false\n}\n```\n\n**`as`:** Required. The validated value.\n\n**Body context:** The JSON text to parse.\n\n**Returns:** a value — it renders nothing, and `as` binds what it returns.\n\n```json\n{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\"\n}\n```\n\n**Origin:** `@executablemd/core` (registered default)\n\n### ``\n\nSelect part of a value with a yq expression. `` binds the scripts object; the same element without `as` writes the selected value as JSON. Text is decoded only where the expression says `from_json` or `from_yaml`, and an expression that selects nothing or several values says to collect them with `[ … ]`.\n\n**Forms:** ``\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `value` | JSON Schema | yes | |\n| `yq` | `string` | yes | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"value\": {},\n \"yq\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n },\n \"required\": [\n \"value\",\n \"yq\"\n ],\n \"additionalProperties\": false\n}\n```\n\n**`as`:** Optional. Binds the selected value as data instead of writing it as JSON.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/core` (registered default)\n\n### ``\n\nParse a value using a JSON schema. `…` parses its content. Binds a result object instead of erroring.\n\n**Forms:** ``, `…`\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `schema` | JSON Schema | yes | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"schema\": {}\n },\n \"required\": [\n \"schema\"\n ],\n \"additionalProperties\": false\n}\n```\n\n**`as`:** Required. The result: either the validated value or the issues that rejected it.\n\n**Body context:** The JSON text to parse.\n\n**Returns:** a value — it renders nothing, and `as` binds what it returns.\n\n```json\n{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"oneOf\": [\n {\n \"type\": \"object\",\n \"properties\": {\n \"ok\": {\n \"const\": true\n },\n \"value\": {}\n },\n \"required\": [\n \"ok\",\n \"value\"\n ],\n \"additionalProperties\": false\n },\n {\n \"type\": \"object\",\n \"properties\": {\n \"ok\": {\n \"const\": false\n },\n \"input\": {\n \"type\": \"string\"\n },\n \"errors\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"instancePath\": {\n \"type\": \"string\"\n },\n \"schemaPath\": {\n \"type\": \"string\"\n },\n \"keyword\": {\n \"type\": \"string\"\n },\n \"params\": {},\n \"message\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"instancePath\",\n \"schemaPath\",\n \"keyword\",\n \"params\",\n \"message\"\n ],\n \"additionalProperties\": false\n }\n }\n },\n \"required\": [\n \"ok\",\n \"input\",\n \"errors\"\n ],\n \"additionalProperties\": false\n }\n ]\n}\n```\n\n**Origin:** `@executablemd/core` (registered default)\n\n### ``\n\nShow a window of rendered text. `…` counts Unicode code points and labels partial excerpts.\n\n**Forms:** ``, `…`\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `offset` | `integer` | no | |\n| `length` | `integer` | no | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"offset\": {\n \"type\": \"integer\",\n \"default\": 0\n },\n \"length\": {\n \"type\": \"integer\",\n \"minimum\": 1,\n \"default\": 4096\n }\n },\n \"additionalProperties\": false\n}\n```\n\n**`as`:** Optional. Captures the resulting text, including any range note, instead of emitting it.\n\n**Body context:** The content whose completed rendering the window is taken from.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/core` (registered default)\n\n### ``\n\nInspect available components and control-flow constructs. `` lists the symbols available here; `` renders selected documentation.\n\n**Forms:** ``\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `names` | `array` | no | Optional. Render complete references for these structural or component names instead of the list of available symbols. Entries render once each, in symbol order. |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"names\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n },\n \"minItems\": 1,\n \"uniqueItems\": true,\n \"description\": \"Optional. Render complete references for these structural or component names instead of the list of available symbols. Entries render once each, in symbol order.\"\n }\n },\n \"additionalProperties\": false\n}\n```\n\n**`as`:** Optional. Captures the rendered text instead of emitting it.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/core` (protected component)\n\n### ``\n\nRun work in a temporary working directory. `…` expands its content with the temporary directory as the working directory, so `` and commands inside write there rather than in the current one. `` renders the path instead.\n\n**Forms:** ``, `…`\n\n#### Props\n\nThis component declares no individual props.\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {},\n \"additionalProperties\": false\n}\n```\n\n**`as`:** Optional. Captures the rendered directory path instead of emitting it.\n\n**Body context:** Markdown expanded with the temporary directory as its working directory.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/core` (registered default)\n\n### ``\n\nDefine a test. `…` runs under `xmd test`, or inside a `` region; elsewhere it is skipped. A failing command or assertion inside fails the test rather than the document.\n\n**Forms:** ``, `…`\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `name` | `string` | no | |\n| `timeout` | `string` | no | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\"\n },\n \"timeout\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n}\n```\n\n**Body context:** The body of the test: its assertions and the work they judge.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/core` (registered default)\n\n### ``\n\nRender a value as YAML text. `` writes the YAML where you put it.\n\n**Forms:** ``\n\n#### Props\n\nThis component declares no individual props.\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {},\n \"additionalProperties\": false\n}\n```\n\n**Captures:** `value` — evaluated by the component itself, so these props are deliberately absent from the schema above.\n\n**`as`:** Optional. Captures the YAML text instead of emitting it.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/core` (registered default)\n\n## User-provided components\n\n### ``\n\n**Forms:** ``, `…`\n\n#### Props\n\nThis component declares no individual props.\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {},\n \"additionalProperties\": false\n}\n```\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `AGENTS.md`\n\n### ``\n\n**Forms:** ``, `…`\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `package` | `string` | yes | Workspace package directory, e.g. packages/workflow |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"package\": {\n \"type\": \"string\",\n \"pattern\": \"^packages/[a-z0-9][a-z0-9._-]*$\",\n \"description\": \"Workspace package directory, e.g. packages/workflow\"\n }\n },\n \"required\": [\n \"package\"\n ],\n \"additionalProperties\": false\n}\n```\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `components/BootstrapNpmPackage.md`\n\n### ``\n\n**Forms:** ``, `…`\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `package` | `string` | no | Workspace package to reserve on npm, e.g. packages/workflow |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"package\": {\n \"type\": \"string\",\n \"pattern\": \"^packages/[a-z0-9][a-z0-9._-]*$\",\n \"description\": \"Workspace package to reserve on npm, e.g. packages/workflow\"\n }\n },\n \"additionalProperties\": false\n}\n```\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `README.md`\n", + "cli-bare-base.txt": "## Built-in structural syntax\n\n### ``\n\nRun tasks in parallel. `firstsecond` expands every task at the same time, waits for them all to succeed, and preserves their Markdown order. Write at least two `` children directly inside it; if one fails, unfinished tasks are cancelled and `` produces no output.\n\n**Syntax:**\n\n```md\n……\n```\n\n**Body context:** The `` children this runs at the same time.\n\n### ``\n\nSupply one answer inside ``. `` answers any elicitation its template matches — `{?name}` matches any text. The first matching `` wins.\n\n**Syntax:**\n\n```md\n\n…\n```\n\n**Body context:** A multiline template, in place of the single-line `template` prop.\n\n### ``\n\nAnswer any `` in its content without asking a person. `…` replies from the `` matchers declared inside it, reaching elicitations from nested components too. `delegate` passes an unmatched one outward instead of failing.\n\n**Syntax:**\n\n```md\n…\n```\n\n**Body context:** `` matchers, and the body they answer for.\n\n### ``\n\nExit the nearest enclosing ``. `` stops the current iteration where it is; nothing after it in that iteration runs.\n\n**Syntax:**\n\n```md\n\n```\n\n### ``\n\nDefine one branch of a ``. `…` matches with `===`; `…` is the final fallback.\n\n**Syntax:**\n\n```md\n…\n…\n```\n\n**Body context:** Markdown expanded when this case is selected.\n\n### ``\n\nHandle a failure in the preceding Try body. `{error.message}` runs after clean release; its bindings stay local. Cancellation skips this branch.\n\n**Syntax:**\n\n```md\n…\n…\n```\n\n**`as`:** Optional. Binds the ordinary Error by reference in this branch.\n\n**Body context:** Recovery content.\n\n### ``\n\nRender what the caller wrote inside this component. `` renders all of it; `` renders just the part the caller marked `slot=\"footer\"`.\n\n**Syntax:**\n\n```md\n\n\n```\n\n### ``\n\nRepeat content for each item in an array. `…` binds each one to `item` inside.\n\n**Syntax:**\n\n```md\n…\n```\n\n**`as`:** Optional. Captures the whole rendered loop instead of emitting it.\n\n**Body context:** Markdown rendered once per element.\n\n### ``\n\nThe branch `` takes when its condition is false. `…` is written directly inside an ``, and is an error anywhere else.\n\n**Syntax:**\n\n```md\n…\n```\n\n**Body context:** The branch taken when the enclosing condition does not hold.\n\n### ``\n\nFinish a Try after its attempted body and recovery. `Cleanup.` also runs and joins on terminal Stop. Resumable Exit leaves an unentered branch pending; failed release and infrastructure failure prevent new entry.\n\n**Syntax:**\n\n```md\n…\n```\n\n**Body context:** Completion content using the surrounding bindings.\n\n### ``\n\nExpand content only when a condition is true. `…` expands its content, or the `` branch instead. The branch not taken never runs.\n\n**Syntax:**\n\n```md\n…\n```\n\n**Body context:** The branch taken when the condition holds, up to an ``.\n\n### ``\n\nBind a name for the rest of the region. `…` binds what its content rendered; `` binds the value. `select` narrows the rendered content to one CSS selection.\n\n**Syntax:**\n\n```md\n…\n\n```\n\n**`as`:** Required. The binding name the value is available under.\n\n**Body context:** Markdown whose rendered text becomes the binding, in the paired form.\n\n### ``\n\nRepeat content up to `max` times. `…` expands its content again and again until a `` inside it, or until `max` is reached. `max` is required.\n\n**Syntax:**\n\n```md\n…\n```\n\n**Body context:** Markdown expanded once per iteration.\n\n### ``\n\nRestrict what a document or component renders. `…` becomes its entire output; anything outside the region is not rendered.\n\n**Syntax:**\n\n```md\n…\n```\n\n**Body context:** The rendered output the run presents.\n\n### ``\n\nConvert thrown errors into output without failing. `…` renders any failure inside it as part of the output.\n\n**Syntax:**\n\n```md\n…\n```\n\n**Body context:** The region whose failures are printed rather than raised.\n\n### ``\n\nReturn a value instead of rendered markdown. `` hands the value to the caller, checked against the component's declared `returns` schema.\n\n**Syntax:**\n\n```md\n\n```\n\n### ``\n\nRun a task in parallel inside of ``. Write `…` directly inside ``; bindings made in its content stay with that task, and `` or `` cannot affect work outside it.\n\n**Syntax:**\n\n```md\n…\n```\n\n**Body context:** Markdown expanded in its own child, beside its siblings.\n\n### ``\n\nChoose one branch by comparing a value with `===`. `……` expands the first matching case, or the final default when none matches.\n\n**Syntax:**\n\n```md\n…\n```\n\n**Body context:** Direct `` branches considered in source order.\n\n### ``\n\nRecover an ordinary failure after its resources close. `…fallback` keeps the rendered prefix and stops the attempted body at failure. Write Catch, Finally, or both. Failed release and infrastructure failures end execution.\n\n**Syntax:**\n\n```md\n………\n```\n\n**Body context:** Attempted content followed by direct Catch and Finally branches.\n\n## Built-in components\n\n### ``\n\nSet the agent for every prompt in its content. `…` reaches prompts sent from nested components too. `` checks the agent is available.\n\n**Forms:** ``, `…`\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `name` | `string` | no | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n}\n```\n\n**Body context:** Markdown whose prompts and launches use this agent.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/core` (registered default)\n\n### ``\n\nSet the agent provider for its content. `…` applies to everything inside, where `defaultAgent` sets the agent to use when none is named and `timeout` bounds each prompt. An unknown provider fails before the content runs.\n\n**Forms:** ``, `…`\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `name` | `string` | yes | |\n| `defaultAgent` | `string` | no | |\n| `timeout` | `string` | no | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\"\n },\n \"defaultAgent\": {\n \"type\": \"string\"\n },\n \"timeout\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"name\"\n ],\n \"additionalProperties\": false\n}\n```\n\n**Body context:** Markdown expanded with this provider installed.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/core` (registered default)\n\n### ``\n\nApprove every permission request in its content. `…` answers for the agent so it never stops to ask you; requests offering no allow option are denied.\n\n**Forms:** ``, `…`\n\n#### Props\n\nThis component declares no individual props.\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {},\n \"additionalProperties\": false\n}\n```\n\n**Body context:** Markdown whose permission requests are approved.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/core` (registered default)\n\n### ``\n\nAsk about every permission request in its content. `…` puts each request to you; with no interactive terminal, or no valid answer, it denies.\n\n**Forms:** ``, `…`\n\n#### Props\n\nThis component declares no individual props.\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {},\n \"additionalProperties\": false\n}\n```\n\n**Body context:** Markdown whose permission requests are asked about.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/core` (registered default)\n\n### ``\n\nAssert that a value is truthy — ``. The optional `msg` prop replaces the reported failure message.\n\n**Forms:** ``\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `msg` | `string` | no | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"msg\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n}\n```\n\n**Captures:** `expr` — evaluated by the component itself, so these props are deliberately absent from the schema above.\n\n**`as`:** Optional. The diagnostic report this assertion rendered, as text — a passing assertion renders one only while testing or verbose output is on, so the binding is empty otherwise. A failing assertion does not return.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/testing` (registered default)\n\n### ``\n\nAssert that two values are deeply equal — ``. The optional `msg` prop replaces the reported failure message.\n\n**Forms:** ``, `…`\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `msg` | `string` | no | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"msg\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n}\n```\n\n**Captures:** `actual`, `expected` — evaluated by the component itself, so these props are deliberately absent from the schema above.\n\n**`as`:** Optional. The diagnostic report this assertion rendered, as text — a passing assertion renders one only while testing or verbose output is on, so the binding is empty otherwise. A failing assertion does not return.\n\n**Body context:** The expected value, in place of the `expected` prop.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/testing` (registered default)\n\n### ``\n\nAssert that a value is neither null nor undefined — ``. The optional `msg` prop replaces the reported failure message.\n\n**Forms:** ``\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `msg` | `string` | no | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"msg\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n}\n```\n\n**Captures:** `actual` — evaluated by the component itself, so these props are deliberately absent from the schema above.\n\n**`as`:** Optional. The diagnostic report this assertion rendered, as text — a passing assertion renders one only while testing or verbose output is on, so the binding is empty otherwise. A failing assertion does not return.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/testing` (registered default)\n\n### ``\n\nAssert that a value is falsy — ``. The optional `msg` prop replaces the reported failure message.\n\n**Forms:** ``\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `msg` | `string` | no | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"msg\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n}\n```\n\n**Captures:** `expr` — evaluated by the component itself, so these props are deliberately absent from the schema above.\n\n**`as`:** Optional. The diagnostic report this assertion rendered, as text — a passing assertion renders one only while testing or verbose output is on, so the binding is empty otherwise. A failing assertion does not return.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/testing` (registered default)\n\n### ``\n\nAssert that one number is greater than another — ``. The optional `msg` prop replaces the reported failure message.\n\n**Forms:** ``\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `msg` | `string` | no | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"msg\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n}\n```\n\n**Captures:** `actual`, `expected` — evaluated by the component itself, so these props are deliberately absent from the schema above.\n\n**`as`:** Optional. The diagnostic report this assertion rendered, as text — a passing assertion renders one only while testing or verbose output is on, so the binding is empty otherwise. A failing assertion does not return.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/testing` (registered default)\n\n### ``\n\nAssert that one number is greater than or equal to another — ``. The optional `msg` prop replaces the reported failure message.\n\n**Forms:** ``\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `msg` | `string` | no | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"msg\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n}\n```\n\n**Captures:** `actual`, `expected` — evaluated by the component itself, so these props are deliberately absent from the schema above.\n\n**`as`:** Optional. The diagnostic report this assertion rendered, as text — a passing assertion renders one only while testing or verbose output is on, so the binding is empty otherwise. A failing assertion does not return.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/testing` (registered default)\n\n### ``\n\nAssert that one number is less than another — ``. The optional `msg` prop replaces the reported failure message.\n\n**Forms:** ``\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `msg` | `string` | no | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"msg\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n}\n```\n\n**Captures:** `actual`, `expected` — evaluated by the component itself, so these props are deliberately absent from the schema above.\n\n**`as`:** Optional. The diagnostic report this assertion rendered, as text — a passing assertion renders one only while testing or verbose output is on, so the binding is empty otherwise. A failing assertion does not return.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/testing` (registered default)\n\n### ``\n\nAssert that one number is less than or equal to another — ``. The optional `msg` prop replaces the reported failure message.\n\n**Forms:** ``\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `msg` | `string` | no | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"msg\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n}\n```\n\n**Captures:** `actual`, `expected` — evaluated by the component itself, so these props are deliberately absent from the schema above.\n\n**`as`:** Optional. The diagnostic report this assertion rendered, as text — a passing assertion renders one only while testing or verbose output is on, so the binding is empty otherwise. A failing assertion does not return.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/testing` (registered default)\n\n### ``\n\nAssert that a string matches a pattern — ``. The optional `msg` prop replaces the reported failure message.\n\n**Forms:** ``\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `msg` | `string` | no | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"msg\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n}\n```\n\n**Captures:** `actual`, `expected` — evaluated by the component itself, so these props are deliberately absent from the schema above.\n\n**`as`:** Optional. The diagnostic report this assertion rendered, as text — a passing assertion renders one only while testing or verbose output is on, so the binding is empty otherwise. A failing assertion does not return.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/testing` (registered default)\n\n### ``\n\nAssert that two values are not deeply equal — ``. The optional `msg` prop replaces the reported failure message.\n\n**Forms:** ``, `…`\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `msg` | `string` | no | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"msg\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n}\n```\n\n**Captures:** `actual`, `expected` — evaluated by the component itself, so these props are deliberately absent from the schema above.\n\n**`as`:** Optional. The diagnostic report this assertion rendered, as text — a passing assertion renders one only while testing or verbose output is on, so the binding is empty otherwise. A failing assertion does not return.\n\n**Body context:** The expected value, in place of the `expected` prop.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/testing` (registered default)\n\n### ``\n\nAssert that a string does not match a pattern — ``. The optional `msg` prop replaces the reported failure message.\n\n**Forms:** ``\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `msg` | `string` | no | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"msg\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n}\n```\n\n**Captures:** `actual`, `expected` — evaluated by the component itself, so these props are deliberately absent from the schema above.\n\n**`as`:** Optional. The diagnostic report this assertion rendered, as text — a passing assertion renders one only while testing or verbose output is on, so the binding is empty otherwise. A failing assertion does not return.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/testing` (registered default)\n\n### ``\n\nAssert that two values are not the same, compared with `===` — ``. The optional `msg` prop replaces the reported failure message.\n\n**Forms:** ``, `…`\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `msg` | `string` | no | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"msg\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n}\n```\n\n**Captures:** `actual`, `expected` — evaluated by the component itself, so these props are deliberately absent from the schema above.\n\n**`as`:** Optional. The diagnostic report this assertion rendered, as text — a passing assertion renders one only while testing or verbose output is on, so the binding is empty otherwise. A failing assertion does not return.\n\n**Body context:** The expected value, in place of the `expected` prop.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/testing` (registered default)\n\n### ``\n\nAssert that two values are the same, compared with `===` — ``. The optional `msg` prop replaces the reported failure message.\n\n**Forms:** ``, `…`\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `msg` | `string` | no | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"msg\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n}\n```\n\n**Captures:** `actual`, `expected` — evaluated by the component itself, so these props are deliberately absent from the schema above.\n\n**`as`:** Optional. The diagnostic report this assertion rendered, as text — a passing assertion renders one only while testing or verbose output is on, so the binding is empty otherwise. A failing assertion does not return.\n\n**Body context:** The expected value, in place of the `expected` prop.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/testing` (registered default)\n\n### ``\n\nAssert that a string contains a substring — ``. The optional `msg` prop replaces the reported failure message.\n\n**Forms:** ``, `…`\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `msg` | `string` | no | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"msg\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n}\n```\n\n**Captures:** `actual`, `expected` — evaluated by the component itself, so these props are deliberately absent from the schema above.\n\n**`as`:** Optional. The diagnostic report this assertion rendered, as text — a passing assertion renders one only while testing or verbose output is on, so the binding is empty otherwise. A failing assertion does not return.\n\n**Body context:** The expected value, in place of the `expected` prop.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/testing` (registered default)\n\n### ``\n\nAssert that its content fails. `…` passes only if the content fails with a matching message. `message` is required and takes a string or a regular expression.\n\n**Forms:** ``, `…`\n\n#### Props\n\nThis component declares no individual props.\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {},\n \"additionalProperties\": false\n}\n```\n\n**Captures:** `message` — evaluated by the component itself, so these props are deliberately absent from the schema above.\n\n**`as`:** Optional. The complete caught error segment, bound by reference — its `message`, `source` and structured `cause` as they were raised, not a description of them.\n\n**Body context:** The Markdown expected to fail.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/testing` (registered default)\n\n### ``\n\nShow arbitrary text as a fenced Markdown code block. `` chooses a fence the value cannot close.\n\n**Forms:** ``\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `value` | `string` | yes | |\n| `language` | `string` | no | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"value\": {\n \"type\": \"string\"\n },\n \"language\": {\n \"type\": \"string\",\n \"pattern\": \"^[A-Za-z0-9][A-Za-z0-9._+#-]*$\"\n }\n },\n \"required\": [\n \"value\"\n ],\n \"additionalProperties\": false\n}\n```\n\n**`as`:** Optional. Captures the exact fenced Markdown instead of emitting it.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/core` (registered default)\n\n### ``\n\nCapture a child execution's journal so a test can assert on it. `` goes inside ``, beside ``. It reads a journal the run already has — pair it with `` to create one.\n\n**Forms:** ``, `…`\n\n#### Props\n\nThis component declares no individual props.\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {},\n \"additionalProperties\": false\n}\n```\n\n**`as`:** Required. The journal snapshot.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/testing` (registered default)\n\n### ``\n\nCapture a child execution's output so a test can assert on it. `` goes inside ``, before the assertions, and is invalid anywhere else. It changes nothing about the run, and a child that fails partway still leaves what it printed.\n\n**Forms:** ``, `…`\n\n#### Props\n\nThis component declares no individual props.\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {},\n \"additionalProperties\": false\n}\n```\n\n**`as`:** Required. The child's accumulated output.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/testing` (registered default)\n\n### ``\n\nRead the working directory. `` renders its path without adding a newline.\n\n**Forms:** ``\n\n#### Props\n\nThis component declares no individual props.\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {},\n \"additionalProperties\": false\n}\n```\n\n**`as`:** Optional. Captures the directory path instead of emitting it.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/core` (registered default)\n\n### ``\n\nGive a child execution a journal of its own. `` goes inside ``, before the assertions, and is invalid anywhere else. Without it the child keeps no journal you can collect — with it, `` has one to read.\n\n**Forms:** ``, `…`\n\n#### Props\n\nThis component declares no individual props.\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {},\n \"additionalProperties\": false\n}\n```\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/testing` (registered default)\n\n### ``\n\nCreate or use a directory. `…` changes the working directory for its content.\n\n**Forms:** `…`\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `path` | `string` | yes | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"path\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n },\n \"required\": [\n \"path\"\n ],\n \"additionalProperties\": false\n}\n```\n\n**Body context:** The Markdown expanded in that directory.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/core` (protected component)\n\n### ``\n\nAsk a person a structured question. `…` shows the content as the request.\n\n**Forms:** ``, `…`\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `schema` | JSON Schema | yes | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"schema\": {}\n },\n \"required\": [\n \"schema\"\n ],\n \"additionalProperties\": false\n}\n```\n\n**`as`:** Required. The validated answer, as a structured value.\n\n**Body context:** The request message the person is shown.\n\n**Returns:** a value — it renders nothing, and `as` binds what it returns.\n\n```json\n{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\"\n}\n```\n\n**Origin:** `@executablemd/core` (registered default)\n\n### ``\n\nEvaluate program text. `` runs it.\n\n**Forms:** ``, `…`\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `text` | `string` | no | The program to evaluate, for the self-closing form. Written instead of content, never beside it. |\n| `allow` | `array` | no | Optional. Which effect classes the program may draw on, narrowing what this host already installed. Omitted asks for `read`. |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"The program to evaluate, for the self-closing form. Written instead of content, never beside it.\"\n },\n \"allow\": {\n \"type\": \"array\",\n \"minItems\": 1,\n \"uniqueItems\": true,\n \"items\": {\n \"enum\": [\n \"read\",\n \"write\"\n ]\n },\n \"description\": \"Optional. Which effect classes the program may draw on, narrowing what this host already installed. Omitted asks for `read`.\"\n }\n },\n \"additionalProperties\": false\n}\n```\n\n**`as`:** Optional. Captures the fragment's rendered output instead of emitting it.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/core` (protected component)\n\n### ``\n\nRun another document from inside a test, and assert on how it finished. `…` runs it for real, with its own journal and output. Pass `source` instead of `target` to supply the markdown directly, and `props` for the document's properties.\n\n**Forms:** ``, `…`\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `host` | `string` | yes | |\n| `target` | `string` | no | |\n| `source` | `string` | no | |\n| `action` | `string` | no | |\n| `props` | `object` | no | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"host\": {\n \"type\": \"string\"\n },\n \"target\": {\n \"type\": \"string\"\n },\n \"source\": {\n \"type\": \"string\"\n },\n \"action\": {\n \"type\": \"string\"\n },\n \"props\": {\n \"type\": \"object\"\n }\n },\n \"required\": [\n \"host\"\n ],\n \"additionalProperties\": false\n}\n```\n\n**`as`:** Optional. The child's outcome: a settled result, or a suspension. Without it a settled failure fails the owning test rather than passing vacuously.\n\n**Body context:** The declarations for the child, then the assertions about it.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/testing` (registered default)\n\n### ``\n\nStop authored work with an actionable failure. `` raises the message where it is written.\n\n**Forms:** ``\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `message` | `string` | yes | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"message\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n },\n \"required\": [\n \"message\"\n ],\n \"additionalProperties\": false\n}\n```\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/core` (registered default)\n\n### ``\n\nFetch a URL. `` binds the response, and any status is data you can branch on. Without `as`, a non-2xx status fails. Only GET and HEAD methods currently supported.\n\n**Forms:** ``, `…`\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `url` | `string` | yes | |\n| `method` | `string` | no | |\n| `headers` | `object` | no | |\n| `timeout` | `string` | no | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"url\": {\n \"type\": \"string\"\n },\n \"method\": {\n \"type\": \"string\"\n },\n \"headers\": {\n \"type\": \"object\",\n \"additionalProperties\": {\n \"type\": \"string\"\n }\n },\n \"timeout\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"url\"\n ],\n \"additionalProperties\": false\n}\n```\n\n**`as`:** Optional. Captures the response, which is what makes a non-2xx status data instead of a failure.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/core` (registered default)\n\n### ``\n\nRead or write a file. `` reads the content; `…` writes the content. The path is relative to the working directory.\n\n**Forms:** ``, `…`\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `path` | `string` | yes | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"path\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"path\"\n ],\n \"additionalProperties\": false\n}\n```\n\n**`as`:** Optional. Captures the file's text instead of emitting it, in the reading form.\n\n**Body context:** The text to write, in the writing form.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/core` (protected component)\n\n### ``\n\nDelete a file. `` removes it. It does not error if the file doesn't exist, and produces no output.\n\n**Forms:** ``\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `path` | `string` | yes | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"path\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n },\n \"required\": [\n \"path\"\n ],\n \"additionalProperties\": false\n}\n```\n\n**`as`:** Optional. Captures the empty string this renders, as for any text component.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/core` (protected component)\n\n### ``\n\nStage paths for commit. `` resolves Git pathspecs from the working directory.\n\n**Forms:** ``, `…`\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `paths` | JSON Schema | yes | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"paths\": {\n \"anyOf\": [\n {\n \"type\": \"string\",\n \"minLength\": 1\n },\n {\n \"type\": \"array\",\n \"minItems\": 1,\n \"items\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n }\n ]\n }\n },\n \"required\": [\n \"paths\"\n ],\n \"additionalProperties\": false\n}\n```\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/workflow/composition` (registered default)\n\n### ``\n\nCompare what changed. `` reports each changed path and its status for unstaged, staged or two commits.\n\n**Forms:** ``, `…`\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `compare` | JSON Schema | yes | |\n| `base` | `string` | no | |\n| `head` | `string` | no | |\n| `paths` | `array` | no | |\n| `limit` | `integer` | no | |\n| `cursor` | `string` | no | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"compare\": {\n \"enum\": [\n \"unstaged\",\n \"staged\",\n \"commits\"\n ]\n },\n \"base\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"head\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"paths\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n },\n \"limit\": {\n \"type\": \"integer\",\n \"minimum\": 1\n },\n \"cursor\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n },\n \"required\": [\n \"compare\"\n ],\n \"additionalProperties\": false\n}\n```\n\n**`as`:** Required. The comparison, each change's path, status and previous path, and the next page or null.\n\n**Returns:** a value — it renders nothing, and `as` binds what it returns.\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"comparison\": {\n \"oneOf\": [\n {\n \"type\": \"object\",\n \"properties\": {\n \"compare\": {\n \"const\": \"unstaged\"\n }\n },\n \"required\": [\n \"compare\"\n ],\n \"additionalProperties\": false\n },\n {\n \"type\": \"object\",\n \"properties\": {\n \"compare\": {\n \"const\": \"staged\"\n },\n \"base\": {\n \"type\": [\n \"string\",\n \"null\"\n ]\n }\n },\n \"required\": [\n \"compare\",\n \"base\"\n ],\n \"additionalProperties\": false\n },\n {\n \"type\": \"object\",\n \"properties\": {\n \"compare\": {\n \"const\": \"commits\"\n },\n \"base\": {\n \"type\": \"string\"\n },\n \"head\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"compare\",\n \"base\",\n \"head\"\n ],\n \"additionalProperties\": false\n }\n ]\n },\n \"changes\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"path\": {\n \"type\": \"string\"\n },\n \"status\": {\n \"enum\": [\n \"A\",\n \"M\",\n \"D\",\n \"R\",\n \"T\",\n \"U\"\n ]\n },\n \"previousPath\": {\n \"type\": [\n \"string\",\n \"null\"\n ]\n }\n },\n \"required\": [\n \"path\",\n \"status\",\n \"previousPath\"\n ],\n \"additionalProperties\": false\n }\n },\n \"next\": {\n \"type\": [\n \"object\",\n \"null\"\n ],\n \"properties\": {\n \"compare\": {\n \"enum\": [\n \"unstaged\",\n \"staged\",\n \"commits\"\n ]\n },\n \"base\": {\n \"type\": \"string\"\n },\n \"head\": {\n \"type\": \"string\"\n },\n \"paths\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n },\n \"limit\": {\n \"type\": \"integer\",\n \"minimum\": 1\n },\n \"cursor\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n },\n \"required\": [\n \"compare\",\n \"limit\",\n \"cursor\"\n ],\n \"additionalProperties\": false\n }\n },\n \"required\": [\n \"comparison\",\n \"changes\",\n \"next\"\n ],\n \"additionalProperties\": false\n}\n```\n\n**Origin:** `@executablemd/workflow/composition` (registered default)\n\n### ``\n\nCommit staged changes, or read an existing commit. `Prepare 1.4` uses its expanded content as the commit message. `` reads that commit's metadata and runs the checkout's configured signature verifier; your Markdown decides what the result permits.\n\n**Forms:** ``, `…`\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `message` | `string` | no | |\n| `ref` | `string` | no | |\n| `verify` | `boolean` | no | |\n| `yq` | `string` | no | |\n| `maxBytes` | `integer` | no | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"message\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"ref\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"verify\": {\n \"type\": \"boolean\"\n },\n \"yq\": {\n \"type\": \"string\"\n },\n \"maxBytes\": {\n \"type\": \"integer\",\n \"minimum\": 1\n }\n },\n \"additionalProperties\": false\n}\n```\n\n**`as`:** Required. Creating binds the full object id of the new commit. A ref read binds value, next, prev and last: the yq selection and the queries that read its neighbouring pages.\n\n**Body context:** The message body, expanded before the commit is made. A ref read takes none.\n\n**Returns:** a value — it renders nothing, and `as` binds what it returns.\n\n```json\n{\n \"anyOf\": [\n {\n \"type\": \"string\",\n \"pattern\": \"^([0-9a-f]{40}|[0-9a-f]{64})$\"\n },\n {\n \"type\": \"object\",\n \"properties\": {\n \"value\": {},\n \"next\": {\n \"type\": [\n \"string\",\n \"null\"\n ]\n },\n \"prev\": {\n \"type\": [\n \"string\",\n \"null\"\n ]\n },\n \"last\": {\n \"type\": [\n \"string\",\n \"null\"\n ]\n }\n },\n \"required\": [\n \"value\",\n \"next\",\n \"prev\",\n \"last\"\n ],\n \"additionalProperties\": false\n }\n ]\n}\n```\n\n**Origin:** `@executablemd/workflow/composition` (registered default)\n\n### ``\n\nRead a comparison's patch. `` reads a window of the unified diff text.\n\n**Forms:** ``, `…`\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `compare` | JSON Schema | yes | |\n| `base` | `string` | no | |\n| `head` | `string` | no | |\n| `paths` | `array` | no | |\n| `offset` | `integer` | no | |\n| `limit` | `integer` | no | |\n| `cursor` | `string` | no | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"compare\": {\n \"enum\": [\n \"unstaged\",\n \"staged\",\n \"commits\"\n ]\n },\n \"base\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"head\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"paths\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n },\n \"offset\": {\n \"type\": \"integer\",\n \"minimum\": 0\n },\n \"limit\": {\n \"type\": \"integer\",\n \"minimum\": 1\n },\n \"cursor\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n },\n \"required\": [\n \"compare\"\n ],\n \"additionalProperties\": false\n}\n```\n\n**`as`:** Required. The comparison, the patch window, its offset, the whole length, and the next page or null.\n\n**Returns:** a value — it renders nothing, and `as` binds what it returns.\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"comparison\": {\n \"oneOf\": [\n {\n \"type\": \"object\",\n \"properties\": {\n \"compare\": {\n \"const\": \"unstaged\"\n }\n },\n \"required\": [\n \"compare\"\n ],\n \"additionalProperties\": false\n },\n {\n \"type\": \"object\",\n \"properties\": {\n \"compare\": {\n \"const\": \"staged\"\n },\n \"base\": {\n \"type\": [\n \"string\",\n \"null\"\n ]\n }\n },\n \"required\": [\n \"compare\",\n \"base\"\n ],\n \"additionalProperties\": false\n },\n {\n \"type\": \"object\",\n \"properties\": {\n \"compare\": {\n \"const\": \"commits\"\n },\n \"base\": {\n \"type\": \"string\"\n },\n \"head\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"compare\",\n \"base\",\n \"head\"\n ],\n \"additionalProperties\": false\n }\n ]\n },\n \"text\": {\n \"type\": \"string\"\n },\n \"offset\": {\n \"type\": \"integer\",\n \"minimum\": 0\n },\n \"length\": {\n \"type\": \"integer\",\n \"minimum\": 0\n },\n \"next\": {\n \"type\": [\n \"object\",\n \"null\"\n ],\n \"properties\": {\n \"compare\": {\n \"enum\": [\n \"unstaged\",\n \"staged\",\n \"commits\"\n ]\n },\n \"base\": {\n \"type\": \"string\"\n },\n \"head\": {\n \"type\": \"string\"\n },\n \"paths\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n },\n \"offset\": {\n \"type\": \"integer\",\n \"minimum\": 0\n },\n \"limit\": {\n \"type\": \"integer\",\n \"minimum\": 1\n },\n \"cursor\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n },\n \"required\": [\n \"compare\",\n \"offset\",\n \"limit\",\n \"cursor\"\n ],\n \"additionalProperties\": false\n }\n },\n \"required\": [\n \"comparison\",\n \"text\",\n \"offset\",\n \"length\",\n \"next\"\n ],\n \"additionalProperties\": false\n}\n```\n\n**Origin:** `@executablemd/workflow/composition` (registered default)\n\n### ``\n\nRead a committed file. `` reads the text that commit holds, not the working copy.\n\n**Forms:** ``, `…`\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `commit` | `string` | yes | |\n| `path` | `string` | yes | |\n| `offset` | `integer` | no | |\n| `limit` | `integer` | no | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"commit\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"path\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"offset\": {\n \"type\": \"integer\",\n \"minimum\": 0\n },\n \"limit\": {\n \"type\": \"integer\",\n \"minimum\": 1\n }\n },\n \"required\": [\n \"commit\",\n \"path\"\n ],\n \"additionalProperties\": false\n}\n```\n\n**`as`:** Required. The resolved commit, the path, the text window, its offset, the whole length, and the next page or null.\n\n**Returns:** a value — it renders nothing, and `as` binds what it returns.\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"commit\": {\n \"type\": \"string\"\n },\n \"path\": {\n \"type\": \"string\"\n },\n \"text\": {\n \"type\": \"string\"\n },\n \"offset\": {\n \"type\": \"integer\",\n \"minimum\": 0\n },\n \"length\": {\n \"type\": \"integer\",\n \"minimum\": 0\n },\n \"next\": {\n \"type\": [\n \"object\",\n \"null\"\n ],\n \"properties\": {\n \"commit\": {\n \"type\": \"string\"\n },\n \"path\": {\n \"type\": \"string\"\n },\n \"offset\": {\n \"type\": \"integer\",\n \"minimum\": 0\n },\n \"limit\": {\n \"type\": \"integer\",\n \"minimum\": 1\n }\n },\n \"required\": [\n \"commit\",\n \"path\",\n \"offset\",\n \"limit\"\n ],\n \"additionalProperties\": false\n }\n },\n \"required\": [\n \"commit\",\n \"path\",\n \"text\",\n \"offset\",\n \"length\",\n \"next\"\n ],\n \"additionalProperties\": false\n}\n```\n\n**Origin:** `@executablemd/workflow/composition` (registered default)\n\n### ``\n\nList tracked files. `` lists the selected repository's tracked paths, bounded and continuable.\n\n**Forms:** ``, `…`\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `prefix` | `string` | no | |\n| `limit` | `integer` | no | |\n| `cursor` | `string` | no | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"prefix\": {\n \"type\": \"string\"\n },\n \"limit\": {\n \"type\": \"integer\",\n \"minimum\": 1\n },\n \"cursor\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n },\n \"required\": [],\n \"additionalProperties\": false\n}\n```\n\n**`as`:** Required. The tracked paths, and the arguments of the next page or null.\n\n**Returns:** a value — it renders nothing, and `as` binds what it returns.\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"paths\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n },\n \"next\": {\n \"type\": [\n \"object\",\n \"null\"\n ],\n \"properties\": {\n \"prefix\": {\n \"type\": \"string\"\n },\n \"limit\": {\n \"type\": \"integer\",\n \"minimum\": 1\n },\n \"cursor\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n },\n \"required\": [\n \"limit\",\n \"cursor\"\n ],\n \"additionalProperties\": false\n }\n },\n \"required\": [\n \"paths\",\n \"next\"\n ],\n \"additionalProperties\": false\n}\n```\n\n**Origin:** `@executablemd/workflow/composition` (registered default)\n\n### ``\n\nPublish the current branch. `` pushes its current commit to the same branch on `origin` without forcing.\n\n**Forms:** ``\n\n#### Props\n\nThis component declares no individual props.\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {},\n \"additionalProperties\": false\n}\n```\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/workflow/composition` (registered default)\n\n### ``\n\nSwitch or create a branch. `` starts a missing branch at the specified base.\n\n**Forms:** ``, `…`\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `branch` | `string` | yes | |\n| `base` | `string` | no | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"branch\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"base\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n },\n \"required\": [\n \"branch\"\n ],\n \"additionalProperties\": false\n}\n```\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/workflow/composition` (registered default)\n\n### ``\n\nList files by pattern. `` matches paths relative to the working directory. The list is sorted. Directories and symbolic links are never results.\n\n**Forms:** ``, `…`\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `include` | `array` | yes | |\n| `exclude` | `array` | no | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"include\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n },\n \"minItems\": 1\n },\n \"exclude\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n },\n \"default\": []\n }\n },\n \"required\": [\n \"include\"\n ],\n \"additionalProperties\": false\n}\n```\n\n**`as`:** Required. The matched paths, as a string array.\n\n**Returns:** a value — it renders nothing, and `as` binds what it returns.\n\n```json\n{\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n}\n```\n\n**Origin:** `@executablemd/core` (registered default)\n\n### ``\n\nRead or file an issue. `` reads one. `…` files its content in the issue tracker in scope.\n\n**Forms:** ``, `…`\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `url` | `string` | no | |\n| `title` | `string` | no | |\n| `tags` | `array` | no | |\n| `assignee` | `string` | no | |\n| `provider` | `string` | no | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"url\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"title\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"tags\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n },\n \"assignee\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"provider\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n}\n```\n\n**`as`:** Required for a read, which binds url, title, description, tags and assignee. A file binds the url alone.\n\n**Body context:** The issue's description, for the form that files one.\n\n**Returns:** a value — it renders nothing, and `as` binds what it returns.\n\n```json\n{\n \"oneOf\": [\n {\n \"type\": \"object\",\n \"properties\": {\n \"url\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n },\n \"required\": [\n \"url\"\n ],\n \"additionalProperties\": false\n },\n {\n \"type\": \"object\",\n \"properties\": {\n \"url\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"title\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"description\": {\n \"type\": \"string\"\n },\n \"tags\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n },\n \"assignee\": {\n \"type\": [\n \"string\",\n \"null\"\n ]\n }\n },\n \"required\": [\n \"url\",\n \"title\",\n \"description\",\n \"tags\",\n \"assignee\"\n ],\n \"additionalProperties\": false\n }\n ]\n}\n```\n\n**Origin:** `@executablemd/workflow/composition` (registered default)\n\n### ``\n\nSelect an issue tracker. `…` expands its content with the specified tracker in scope.\n\n**Forms:** ``, `…`\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `url` | `string` | yes | |\n| `provider` | `string` | no | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"url\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"provider\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"url\"\n ],\n \"additionalProperties\": false\n}\n```\n\n**Body context:** The Markdown whose issues are filed there.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/workflow/composition` (registered default)\n\n### ``\n\nRender a value as JSON text. `` writes the JSON where you put it.\n\n**Forms:** ``\n\n#### Props\n\nThis component declares no individual props.\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {},\n \"additionalProperties\": false\n}\n```\n\n**Captures:** `value` — evaluated by the component itself, so these props are deliberately absent from the schema above.\n\n**`as`:** Optional. Captures the JSON text instead of emitting it.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/core` (registered default)\n\n### ``\n\nParse a value using a JSON schema. `…` parses its content. Errors on invalid content.\n\n**Forms:** ``, `…`\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `schema` | JSON Schema | yes | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"schema\": {}\n },\n \"required\": [\n \"schema\"\n ],\n \"additionalProperties\": false\n}\n```\n\n**`as`:** Required. The validated value.\n\n**Body context:** The JSON text to parse.\n\n**Returns:** a value — it renders nothing, and `as` binds what it returns.\n\n```json\n{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\"\n}\n```\n\n**Origin:** `@executablemd/core` (registered default)\n\n### ``\n\nGenerate program text from a prompt. `Ask for the user's age.` emits the approved program text; `` runs it.\n\n**Forms:** `…`\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `session` | `string` | no | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"session\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n },\n \"additionalProperties\": false\n}\n```\n\n**`as`:** Binds the exact approved program source and emits nothing. Omitted, that source is emitted where the component is written.\n\n**Body context:** The complete prompt, expanded once before authorship.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/cli/Plan.md` (declared Markdown)\n\n### ``\n\nSend a prompt and render the reply. `…` sends its content; `` sends the prop. `agent`, `session` and `timeout` override the surrounding scope. A failed prompt renders what it got and the document continues — `throwOnError` stops it instead.\n\n**Forms:** ``, `…`\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `text` | `string` | no | |\n| `agent` | `string` | no | |\n| `session` | `string` | no | |\n| `timeout` | `string` | no | |\n| `throwOnError` | `boolean` | no | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\"\n },\n \"agent\": {\n \"type\": \"string\"\n },\n \"session\": {\n \"type\": \"string\"\n },\n \"timeout\": {\n \"type\": \"string\"\n },\n \"throwOnError\": {\n \"type\": \"boolean\"\n }\n },\n \"additionalProperties\": false\n}\n```\n\n**`as`:** Optional. Captures the reply instead of emitting it.\n\n**Body context:** The prompt text, in the paired form.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/core` (registered default)\n\n### ``\n\nOpen or update a pull request. `…` uses its content as the body after ``.\n\n**Forms:** ``, `…`\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `number` | `integer` | no | |\n| `title` | `string` | yes | |\n| `base` | `string` | no | |\n| `draft` | `boolean` | no | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"number\": {\n \"type\": \"integer\",\n \"minimum\": 1\n },\n \"title\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"base\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"draft\": {\n \"type\": \"boolean\",\n \"default\": false\n }\n },\n \"required\": [\n \"title\"\n ],\n \"additionalProperties\": false\n}\n```\n\n**`as`:** Optional. The pull request's repository, number, url, state and head and base commits.\n\n**Body context:** The pull request's body.\n\n**Returns:** a value — it renders nothing, and `as` binds what it returns.\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"repository\": {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"locatorFingerprint\": {\n \"type\": \"string\",\n \"pattern\": \"^[0-9a-f]{64}$\"\n },\n \"requestedBase\": {\n \"type\": [\n \"string\",\n \"null\"\n ]\n },\n \"creationCommit\": {\n \"type\": \"string\",\n \"pattern\": \"^([0-9a-f]{40}|[0-9a-f]{64})$\"\n },\n \"primaryBranch\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"objectFormat\": {\n \"enum\": [\n \"sha1\",\n \"sha256\"\n ]\n }\n },\n \"required\": [\n \"name\",\n \"locatorFingerprint\",\n \"requestedBase\",\n \"creationCommit\",\n \"primaryBranch\",\n \"objectFormat\"\n ],\n \"additionalProperties\": false\n },\n \"providerId\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"number\": {\n \"type\": \"integer\",\n \"minimum\": 1\n },\n \"url\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"state\": {\n \"const\": \"open\"\n },\n \"headSha\": {\n \"type\": \"string\",\n \"pattern\": \"^([0-9a-f]{40}|[0-9a-f]{64})$\"\n },\n \"baseSha\": {\n \"type\": \"string\",\n \"pattern\": \"^([0-9a-f]{40}|[0-9a-f]{64})$\"\n }\n },\n \"required\": [\n \"repository\",\n \"providerId\",\n \"number\",\n \"url\",\n \"state\",\n \"headSha\",\n \"baseSha\"\n ],\n \"additionalProperties\": false\n}\n```\n\n**Origin:** `@executablemd/workflow/composition` (registered default)\n\n### ``\n\nRead pull request checks. `` reads check runs and commit statuses for its head.\n\n**Forms:** ``\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `url` | `string` | yes | |\n| `provider` | `string` | no | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"url\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"provider\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n },\n \"required\": [\n \"url\"\n ],\n \"additionalProperties\": false\n}\n```\n\n**`as`:** Required. Each check's kind, name, head commit and outcome.\n\n**Returns:** a value — it renders nothing, and `as` binds what it returns.\n\n```json\n{\n \"type\": \"array\",\n \"items\": {\n \"oneOf\": [\n {\n \"type\": \"object\",\n \"properties\": {\n \"kind\": {\n \"const\": \"check-run\"\n },\n \"id\": {\n \"type\": \"string\"\n },\n \"headSha\": {\n \"type\": \"string\"\n },\n \"name\": {\n \"type\": \"string\"\n },\n \"status\": {\n \"enum\": [\n \"queued\",\n \"in_progress\",\n \"completed\",\n \"waiting\",\n \"requested\",\n \"pending\"\n ]\n },\n \"conclusion\": {\n \"enum\": [\n \"success\",\n \"failure\",\n \"neutral\",\n \"cancelled\",\n \"skipped\",\n \"timed_out\",\n \"action_required\",\n null\n ]\n },\n \"url\": {\n \"type\": [\n \"string\",\n \"null\"\n ]\n },\n \"startedAt\": {\n \"type\": [\n \"string\",\n \"null\"\n ]\n },\n \"completedAt\": {\n \"type\": [\n \"string\",\n \"null\"\n ]\n },\n \"title\": {\n \"type\": [\n \"string\",\n \"null\"\n ]\n },\n \"summary\": {\n \"type\": [\n \"string\",\n \"null\"\n ]\n },\n \"text\": {\n \"type\": [\n \"string\",\n \"null\"\n ]\n }\n },\n \"required\": [\n \"kind\",\n \"id\",\n \"headSha\",\n \"name\",\n \"status\",\n \"conclusion\",\n \"url\",\n \"startedAt\",\n \"completedAt\",\n \"title\",\n \"summary\",\n \"text\"\n ],\n \"additionalProperties\": false\n },\n {\n \"type\": \"object\",\n \"properties\": {\n \"kind\": {\n \"const\": \"commit-status\"\n },\n \"id\": {\n \"type\": \"string\"\n },\n \"headSha\": {\n \"type\": \"string\"\n },\n \"name\": {\n \"type\": \"string\"\n },\n \"state\": {\n \"enum\": [\n \"error\",\n \"failure\",\n \"pending\",\n \"success\"\n ]\n },\n \"description\": {\n \"type\": [\n \"string\",\n \"null\"\n ]\n },\n \"url\": {\n \"type\": [\n \"string\",\n \"null\"\n ]\n },\n \"createdAt\": {\n \"type\": \"string\"\n },\n \"updatedAt\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"kind\",\n \"id\",\n \"headSha\",\n \"name\",\n \"state\",\n \"description\",\n \"url\",\n \"createdAt\",\n \"updatedAt\"\n ],\n \"additionalProperties\": false\n }\n ]\n }\n}\n```\n\n**Origin:** `@executablemd/workflow/composition` (registered default)\n\n### ``\n\nRead pull request comments. `` reads both conversation and review comments.\n\n**Forms:** ``\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `url` | `string` | yes | |\n| `provider` | `string` | no | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"url\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"provider\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n },\n \"required\": [\n \"url\"\n ],\n \"additionalProperties\": false\n}\n```\n\n**`as`:** Required. Each comment's kind, author, body, timestamps and url, and a review comment's file, hunk and line.\n\n**Returns:** a value — it renders nothing, and `as` binds what it returns.\n\n```json\n{\n \"type\": \"array\",\n \"items\": {\n \"oneOf\": [\n {\n \"type\": \"object\",\n \"properties\": {\n \"kind\": {\n \"const\": \"conversation\"\n },\n \"id\": {\n \"type\": \"string\"\n },\n \"author\": {\n \"type\": [\n \"string\",\n \"null\"\n ]\n },\n \"body\": {\n \"type\": \"string\"\n },\n \"createdAt\": {\n \"type\": \"string\"\n },\n \"updatedAt\": {\n \"type\": \"string\"\n },\n \"url\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"kind\",\n \"id\",\n \"author\",\n \"body\",\n \"createdAt\",\n \"updatedAt\",\n \"url\"\n ],\n \"additionalProperties\": false\n },\n {\n \"type\": \"object\",\n \"properties\": {\n \"kind\": {\n \"const\": \"review\"\n },\n \"id\": {\n \"type\": \"string\"\n },\n \"reviewId\": {\n \"type\": [\n \"string\",\n \"null\"\n ]\n },\n \"author\": {\n \"type\": [\n \"string\",\n \"null\"\n ]\n },\n \"body\": {\n \"type\": \"string\"\n },\n \"createdAt\": {\n \"type\": \"string\"\n },\n \"updatedAt\": {\n \"type\": \"string\"\n },\n \"url\": {\n \"type\": \"string\"\n },\n \"path\": {\n \"type\": \"string\"\n },\n \"diffHunk\": {\n \"type\": \"string\"\n },\n \"commitSha\": {\n \"type\": \"string\"\n },\n \"originalCommitSha\": {\n \"type\": \"string\"\n },\n \"line\": {\n \"type\": [\n \"integer\",\n \"null\"\n ]\n },\n \"side\": {\n \"enum\": [\n \"left\",\n \"right\",\n null\n ]\n },\n \"startLine\": {\n \"type\": [\n \"integer\",\n \"null\"\n ]\n },\n \"startSide\": {\n \"enum\": [\n \"left\",\n \"right\",\n null\n ]\n },\n \"inReplyToId\": {\n \"type\": [\n \"string\",\n \"null\"\n ]\n }\n },\n \"required\": [\n \"kind\",\n \"id\",\n \"reviewId\",\n \"author\",\n \"body\",\n \"createdAt\",\n \"updatedAt\",\n \"url\",\n \"path\",\n \"diffHunk\",\n \"commitSha\",\n \"originalCommitSha\",\n \"line\",\n \"side\",\n \"startLine\",\n \"startSide\",\n \"inReplyToId\"\n ],\n \"additionalProperties\": false\n }\n ]\n }\n}\n```\n\n**Origin:** `@executablemd/workflow/composition` (registered default)\n\n### ``\n\nRead pull request reviews. `` reads reviews from the specified pull request.\n\n**Forms:** ``\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `url` | `string` | yes | |\n| `provider` | `string` | no | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"url\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"provider\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n },\n \"required\": [\n \"url\"\n ],\n \"additionalProperties\": false\n}\n```\n\n**`as`:** Required. Each review's author, state, body, submission time, commit and url.\n\n**Returns:** a value — it renders nothing, and `as` binds what it returns.\n\n```json\n{\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\"\n },\n \"author\": {\n \"type\": [\n \"string\",\n \"null\"\n ]\n },\n \"state\": {\n \"enum\": [\n \"approved\",\n \"changes-requested\",\n \"commented\",\n \"dismissed\",\n \"pending\"\n ]\n },\n \"body\": {\n \"type\": \"string\"\n },\n \"submittedAt\": {\n \"type\": [\n \"string\",\n \"null\"\n ]\n },\n \"commitSha\": {\n \"type\": [\n \"string\",\n \"null\"\n ]\n },\n \"url\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"id\",\n \"author\",\n \"state\",\n \"body\",\n \"submittedAt\",\n \"commitSha\",\n \"url\"\n ],\n \"additionalProperties\": false\n }\n}\n```\n\n**Origin:** `@executablemd/workflow/composition` (registered default)\n\n### ``\n\nSelect part of a value with a yq expression. `` binds the scripts object; the same element without `as` writes the selected value as JSON. Text is decoded only where the expression says `from_json` or `from_yaml`, and an expression that selects nothing or several values says to collect them with `[ … ]`.\n\n**Forms:** ``\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `value` | JSON Schema | yes | |\n| `yq` | `string` | yes | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"value\": {},\n \"yq\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n },\n \"required\": [\n \"value\",\n \"yq\"\n ],\n \"additionalProperties\": false\n}\n```\n\n**`as`:** Optional. Binds the selected value as data instead of writing it as JSON.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/core` (registered default)\n\n### ``\n\nClone or use a repository. `…` expands its content in the specified checkout.\n\n**Forms:** ``, `…`\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `name` | `string` | yes | |\n| `url` | `string` | yes | |\n| `base` | `string` | no | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"url\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"base\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n },\n \"required\": [\n \"name\",\n \"url\"\n ],\n \"additionalProperties\": false\n}\n```\n\n**`as`:** Optional. The path of the selected checkout.\n\n**Body context:** The Markdown expanded in that checkout.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/workflow/composition` (registered default)\n\n### ``\n\nParse a value using a JSON schema. `…` parses its content. Binds a result object instead of erroring.\n\n**Forms:** ``, `…`\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `schema` | JSON Schema | yes | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"schema\": {}\n },\n \"required\": [\n \"schema\"\n ],\n \"additionalProperties\": false\n}\n```\n\n**`as`:** Required. The result: either the validated value or the issues that rejected it.\n\n**Body context:** The JSON text to parse.\n\n**Returns:** a value — it renders nothing, and `as` binds what it returns.\n\n```json\n{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"oneOf\": [\n {\n \"type\": \"object\",\n \"properties\": {\n \"ok\": {\n \"const\": true\n },\n \"value\": {}\n },\n \"required\": [\n \"ok\",\n \"value\"\n ],\n \"additionalProperties\": false\n },\n {\n \"type\": \"object\",\n \"properties\": {\n \"ok\": {\n \"const\": false\n },\n \"input\": {\n \"type\": \"string\"\n },\n \"errors\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"instancePath\": {\n \"type\": \"string\"\n },\n \"schemaPath\": {\n \"type\": \"string\"\n },\n \"keyword\": {\n \"type\": \"string\"\n },\n \"params\": {},\n \"message\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"instancePath\",\n \"schemaPath\",\n \"keyword\",\n \"params\",\n \"message\"\n ],\n \"additionalProperties\": false\n }\n }\n },\n \"required\": [\n \"ok\",\n \"input\",\n \"errors\"\n ],\n \"additionalProperties\": false\n }\n ]\n}\n```\n\n**Origin:** `@executablemd/core` (registered default)\n\n### ``\n\nConfigure one Agent conversation for its content. `…` uses that exact session and configuration for prompts and native launches from nested components. A self-closing Session places or validates the conversation without sending a prompt.\n\n**Forms:** ``, `…`\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `name` | `string` | no | |\n| `model` | `string` | no | |\n| `effort` | `string` | no | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\"\n },\n \"model\": {\n \"type\": \"string\"\n },\n \"effort\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n}\n```\n\n**Body context:** Markdown whose prompts and launches run in this session.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/core` (registered default)\n\n### ``\n\nLaunch a coding agent with prepared context. `…` makes its content the agent's starting context, hands the agent's own interface the terminal, and continues when you exit it.\n\n**Forms:** ``, `…`\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `agent` | `string` | no | |\n| `session` | `string` | no | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"agent\": {\n \"type\": \"string\"\n },\n \"session\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n}\n```\n\n**Body context:** The instructions the native session starts from.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/core` (registered default)\n\n### ``\n\nShow a window of rendered text. `…` counts Unicode code points and labels partial excerpts.\n\n**Forms:** ``, `…`\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `offset` | `integer` | no | |\n| `length` | `integer` | no | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"offset\": {\n \"type\": \"integer\",\n \"default\": 0\n },\n \"length\": {\n \"type\": \"integer\",\n \"minimum\": 1,\n \"default\": 4096\n }\n },\n \"additionalProperties\": false\n}\n```\n\n**`as`:** Optional. Captures the resulting text, including any range note, instead of emitting it.\n\n**Body context:** The content whose completed rendering the window is taken from.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/core` (registered default)\n\n### ``\n\nInspect available components and control-flow constructs. `` lists the symbols available here; `` renders selected documentation.\n\n**Forms:** ``\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `names` | `array` | no | Optional. Render complete references for these structural or component names instead of the list of available symbols. Entries render once each, in symbol order. |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"names\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n },\n \"minItems\": 1,\n \"uniqueItems\": true,\n \"description\": \"Optional. Render complete references for these structural or component names instead of the list of available symbols. Entries render once each, in symbol order.\"\n }\n },\n \"additionalProperties\": false\n}\n```\n\n**`as`:** Optional. Captures the rendered text instead of emitting it.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/core` (protected component)\n\n### ``\n\nRun work in a temporary working directory. `…` expands its content with the temporary directory as the working directory, so `` and commands inside write there rather than in the current one. `` renders the path instead.\n\n**Forms:** ``, `…`\n\n#### Props\n\nThis component declares no individual props.\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {},\n \"additionalProperties\": false\n}\n```\n\n**`as`:** Optional. Captures the rendered directory path instead of emitting it.\n\n**Body context:** Markdown expanded with the temporary directory as its working directory.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/core` (registered default)\n\n### ``\n\nDefine a test. `…` runs under `xmd test`, or inside a `` region; elsewhere it is skipped. A failing command or assertion inside fails the test rather than the document.\n\n**Forms:** ``, `…`\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `name` | `string` | no | |\n| `timeout` | `string` | no | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\"\n },\n \"timeout\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n}\n```\n\n**Body context:** The body of the test: its assertions and the work they judge.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/core` (registered default)\n\n### ``\n\nTurn on testing for its content. `…` runs the `` elements inside and reports them; a failing test fails the document, and so does finding no tests at all.\n\n**Forms:** ``, `…`\n\n#### Props\n\nThis component declares no individual props.\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {},\n \"additionalProperties\": false\n}\n```\n\n**Body context:** The Markdown expanded in testing mode.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/testing` (registered default)\n\n### ``\n\nExpand content when run verbosity is enabled. `--verbose` enables it for the run; a component may override verbosity for its content.\n\n**Forms:** ``, `…`\n\n#### Props\n\nThis component declares no individual props.\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {},\n \"additionalProperties\": false\n}\n```\n\n**`as`:** Optional. Captures the rendered verbose text, or an empty string when verbosity is off.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/cli` (registered default)\n\n### ``\n\nAsk a person a question in a browser form. `…` builds the form from the schema and shows its content above it. `uiSchema` sets presentation options. `` asks the same question without choosing the browser.\n\n**Forms:** ``, `…`\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `schema` | JSON Schema | yes | |\n| `uiSchema` | JSON Schema | no | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"schema\": {},\n \"uiSchema\": {}\n },\n \"required\": [\n \"schema\"\n ],\n \"additionalProperties\": false\n}\n```\n\n**`as`:** Required. The validated response.\n\n**Body context:** The Markdown shown above the form.\n\n**Returns:** a value — it renders nothing, and `as` binds what it returns.\n\n```json\n{}\n```\n\n**Origin:** `@executablemd/web` (registered default)\n\n### ``\n\nScope a workflow-hosted execution. `…` holds `` children, and refuses unless the host supplies a workflow profile.\n\n**Forms:** ``, `…`\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `id` | `string` | no | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n}\n```\n\n**Body context:** The workflow-hosted executions this scope owns.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/testing` (registered default)\n\n### ``\n\nCreate or use a worktree. `…` expands its content in the worktree.\n\n**Forms:** ``, `…`\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `name` | `string` | yes | |\n| `branch` | `string` | yes | |\n| `base` | `string` | no | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"branch\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"base\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n },\n \"required\": [\n \"name\",\n \"branch\"\n ],\n \"additionalProperties\": false\n}\n```\n\n**`as`:** Optional. The path of the linked checkout.\n\n**Body context:** The Markdown expanded in that checkout.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/workflow/composition` (registered default)\n\n### ``\n\nRender a value as YAML text. `` writes the YAML where you put it.\n\n**Forms:** ``\n\n#### Props\n\nThis component declares no individual props.\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {},\n \"additionalProperties\": false\n}\n```\n\n**Captures:** `value` — evaluated by the component itself, so these props are deliberately absent from the schema above.\n\n**`as`:** Optional. Captures the YAML text instead of emitting it.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/core` (registered default)\n\n## User-provided components\n\nNo components were found in the configured includes.\n", + "cli-json-base.txt": "{\n \"version\": 1,\n \"categories\": [\n {\n \"kind\": \"structural\",\n \"entries\": [\n {\n \"kind\": \"structural\",\n \"name\": \"All\",\n \"origin\": {\n \"kind\": \"structural\",\n \"construct\": \"All\"\n },\n \"syntax\": [\n \"……\"\n ],\n \"description\": \"Run tasks in parallel. `firstsecond` expands every task at the same time, waits for them all to succeed, and preserves their Markdown order. Write at least two `` children directly inside it; if one fails, unfinished tasks are cancelled and `` produces no output.\",\n \"context\": \"The `` children this runs at the same time.\"\n },\n {\n \"kind\": \"structural\",\n \"name\": \"Answer\",\n \"origin\": {\n \"kind\": \"structural\",\n \"construct\": \"Answer\"\n },\n \"syntax\": [\n \"\",\n \"…\"\n ],\n \"description\": \"Supply one answer inside ``. `` answers any elicitation its template matches — `{?name}` matches any text. The first matching `` wins.\",\n \"context\": \"A multiline template, in place of the single-line `template` prop.\"\n },\n {\n \"kind\": \"structural\",\n \"name\": \"Answers\",\n \"origin\": {\n \"kind\": \"structural\",\n \"construct\": \"Answers\"\n },\n \"syntax\": [\n \"…\"\n ],\n \"description\": \"Answer any `` in its content without asking a person. `…` replies from the `` matchers declared inside it, reaching elicitations from nested components too. `delegate` passes an unmatched one outward instead of failing.\",\n \"context\": \"`` matchers, and the body they answer for.\"\n },\n {\n \"kind\": \"structural\",\n \"name\": \"Break\",\n \"origin\": {\n \"kind\": \"structural\",\n \"construct\": \"Break\"\n },\n \"syntax\": [\n \"\"\n ],\n \"description\": \"Exit the nearest enclosing ``. `` stops the current iteration where it is; nothing after it in that iteration runs.\"\n },\n {\n \"kind\": \"structural\",\n \"name\": \"Case\",\n \"origin\": {\n \"kind\": \"structural\",\n \"construct\": \"Case\"\n },\n \"syntax\": [\n \"…\",\n \"…\"\n ],\n \"description\": \"Define one branch of a ``. `…` matches with `===`; `…` is the final fallback.\",\n \"context\": \"Markdown expanded when this case is selected.\"\n },\n {\n \"kind\": \"structural\",\n \"name\": \"Catch\",\n \"origin\": {\n \"kind\": \"structural\",\n \"construct\": \"Catch\"\n },\n \"syntax\": [\n \"…\",\n \"…\"\n ],\n \"description\": \"Handle a failure in the preceding Try body. `{error.message}` runs after clean release; its bindings stay local. Cancellation skips this branch.\",\n \"as\": \"Optional. Binds the ordinary Error by reference in this branch.\",\n \"context\": \"Recovery content.\"\n },\n {\n \"kind\": \"structural\",\n \"name\": \"Content\",\n \"origin\": {\n \"kind\": \"structural\",\n \"construct\": \"Content\"\n },\n \"syntax\": [\n \"\",\n \"\"\n ],\n \"description\": \"Render what the caller wrote inside this component. `` renders all of it; `` renders just the part the caller marked `slot=\\\"footer\\\"`.\"\n },\n {\n \"kind\": \"structural\",\n \"name\": \"Each\",\n \"origin\": {\n \"kind\": \"structural\",\n \"construct\": \"Each\"\n },\n \"syntax\": [\n \"…\"\n ],\n \"description\": \"Repeat content for each item in an array. `…` binds each one to `item` inside.\",\n \"as\": \"Optional. Captures the whole rendered loop instead of emitting it.\",\n \"context\": \"Markdown rendered once per element.\"\n },\n {\n \"kind\": \"structural\",\n \"name\": \"Else\",\n \"origin\": {\n \"kind\": \"structural\",\n \"construct\": \"Else\"\n },\n \"syntax\": [\n \"…\"\n ],\n \"description\": \"The branch `` takes when its condition is false. `…` is written directly inside an ``, and is an error anywhere else.\",\n \"context\": \"The branch taken when the enclosing condition does not hold.\"\n },\n {\n \"kind\": \"structural\",\n \"name\": \"Finally\",\n \"origin\": {\n \"kind\": \"structural\",\n \"construct\": \"Finally\"\n },\n \"syntax\": [\n \"…\"\n ],\n \"description\": \"Finish a Try after its attempted body and recovery. `Cleanup.` also runs and joins on terminal Stop. Resumable Exit leaves an unentered branch pending; failed release and infrastructure failure prevent new entry.\",\n \"context\": \"Completion content using the surrounding bindings.\"\n },\n {\n \"kind\": \"structural\",\n \"name\": \"If\",\n \"origin\": {\n \"kind\": \"structural\",\n \"construct\": \"If\"\n },\n \"syntax\": [\n \"…\"\n ],\n \"description\": \"Expand content only when a condition is true. `…` expands its content, or the `` branch instead. The branch not taken never runs.\",\n \"context\": \"The branch taken when the condition holds, up to an ``.\"\n },\n {\n \"kind\": \"structural\",\n \"name\": \"Let\",\n \"origin\": {\n \"kind\": \"structural\",\n \"construct\": \"Let\"\n },\n \"syntax\": [\n \"…\",\n \"\"\n ],\n \"description\": \"Bind a name for the rest of the region. `…` binds what its content rendered; `` binds the value. `select` narrows the rendered content to one CSS selection.\",\n \"as\": \"Required. The binding name the value is available under.\",\n \"context\": \"Markdown whose rendered text becomes the binding, in the paired form.\"\n },\n {\n \"kind\": \"structural\",\n \"name\": \"Loop\",\n \"origin\": {\n \"kind\": \"structural\",\n \"construct\": \"Loop\"\n },\n \"syntax\": [\n \"…\"\n ],\n \"description\": \"Repeat content up to `max` times. `…` expands its content again and again until a `` inside it, or until `max` is reached. `max` is required.\",\n \"context\": \"Markdown expanded once per iteration.\"\n },\n {\n \"kind\": \"structural\",\n \"name\": \"Output\",\n \"origin\": {\n \"kind\": \"structural\",\n \"construct\": \"Output\"\n },\n \"syntax\": [\n \"…\"\n ],\n \"description\": \"Restrict what a document or component renders. `…` becomes its entire output; anything outside the region is not rendered.\",\n \"context\": \"The rendered output the run presents.\"\n },\n {\n \"kind\": \"structural\",\n \"name\": \"PrintErrors\",\n \"origin\": {\n \"kind\": \"structural\",\n \"construct\": \"PrintErrors\"\n },\n \"syntax\": [\n \"…\"\n ],\n \"description\": \"Convert thrown errors into output without failing. `…` renders any failure inside it as part of the output.\",\n \"context\": \"The region whose failures are printed rather than raised.\"\n },\n {\n \"kind\": \"structural\",\n \"name\": \"Return\",\n \"origin\": {\n \"kind\": \"structural\",\n \"construct\": \"Return\"\n },\n \"syntax\": [\n \"\"\n ],\n \"description\": \"Return a value instead of rendered markdown. `` hands the value to the caller, checked against the component's declared `returns` schema.\"\n },\n {\n \"kind\": \"structural\",\n \"name\": \"Spawn\",\n \"origin\": {\n \"kind\": \"structural\",\n \"construct\": \"Spawn\"\n },\n \"syntax\": [\n \"…\"\n ],\n \"description\": \"Run a task in parallel inside of ``. Write `…` directly inside ``; bindings made in its content stay with that task, and `` or `` cannot affect work outside it.\",\n \"context\": \"Markdown expanded in its own child, beside its siblings.\"\n },\n {\n \"kind\": \"structural\",\n \"name\": \"Switch\",\n \"origin\": {\n \"kind\": \"structural\",\n \"construct\": \"Switch\"\n },\n \"syntax\": [\n \"…\"\n ],\n \"description\": \"Choose one branch by comparing a value with `===`. `……` expands the first matching case, or the final default when none matches.\",\n \"context\": \"Direct `` branches considered in source order.\"\n },\n {\n \"kind\": \"structural\",\n \"name\": \"Try\",\n \"origin\": {\n \"kind\": \"structural\",\n \"construct\": \"Try\"\n },\n \"syntax\": [\n \"………\"\n ],\n \"description\": \"Recover an ordinary failure after its resources close. `…fallback` keeps the rendered prefix and stops the attempted body at failure. Write Catch, Finally, or both. Failed release and infrastructure failures end execution.\",\n \"context\": \"Attempted content followed by direct Catch and Finally branches.\"\n }\n ]\n },\n {\n \"kind\": \"built-in\",\n \"entries\": [\n {\n \"kind\": \"component\",\n \"name\": \"Agent\",\n \"origin\": {\n \"kind\": \"registered\",\n \"origin\": \"@executablemd/core\",\n \"reserved\": false\n },\n \"sourceKind\": \"registered\",\n \"inspectability\": \"complete\",\n \"forms\": [\n \"self-closing\",\n \"paired\"\n ],\n \"props\": {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n },\n \"captures\": [],\n \"returnMode\": \"text\",\n \"returns\": {\n \"type\": \"string\"\n },\n \"description\": \"Set the agent for every prompt in its content. `…` reaches prompts sent from nested components too. `` checks the agent is available.\",\n \"context\": \"Markdown whose prompts and launches use this agent.\"\n },\n {\n \"kind\": \"component\",\n \"name\": \"AgentProvider\",\n \"origin\": {\n \"kind\": \"registered\",\n \"origin\": \"@executablemd/core\",\n \"reserved\": false\n },\n \"sourceKind\": \"registered\",\n \"inspectability\": \"complete\",\n \"forms\": [\n \"self-closing\",\n \"paired\"\n ],\n \"props\": {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\"\n },\n \"defaultAgent\": {\n \"type\": \"string\"\n },\n \"timeout\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"name\"\n ],\n \"additionalProperties\": false\n },\n \"captures\": [],\n \"returnMode\": \"text\",\n \"returns\": {\n \"type\": \"string\"\n },\n \"description\": \"Set the agent provider for its content. `…` applies to everything inside, where `defaultAgent` sets the agent to use when none is named and `timeout` bounds each prompt. An unknown provider fails before the content runs.\",\n \"context\": \"Markdown expanded with this provider installed.\"\n },\n {\n \"kind\": \"component\",\n \"name\": \"ApproveAll\",\n \"origin\": {\n \"kind\": \"registered\",\n \"origin\": \"@executablemd/core\",\n \"reserved\": false\n },\n \"sourceKind\": \"registered\",\n \"inspectability\": \"complete\",\n \"forms\": [\n \"self-closing\",\n \"paired\"\n ],\n \"props\": {\n \"type\": \"object\",\n \"properties\": {},\n \"additionalProperties\": false\n },\n \"captures\": [],\n \"returnMode\": \"text\",\n \"returns\": {\n \"type\": \"string\"\n },\n \"description\": \"Approve every permission request in its content. `…` answers for the agent so it never stops to ask you; requests offering no allow option are denied.\",\n \"context\": \"Markdown whose permission requests are approved.\"\n },\n {\n \"kind\": \"component\",\n \"name\": \"AskPermission\",\n \"origin\": {\n \"kind\": \"registered\",\n \"origin\": \"@executablemd/core\",\n \"reserved\": false\n },\n \"sourceKind\": \"registered\",\n \"inspectability\": \"complete\",\n \"forms\": [\n \"self-closing\",\n \"paired\"\n ],\n \"props\": {\n \"type\": \"object\",\n \"properties\": {},\n \"additionalProperties\": false\n },\n \"captures\": [],\n \"returnMode\": \"text\",\n \"returns\": {\n \"type\": \"string\"\n },\n \"description\": \"Ask about every permission request in its content. `…` puts each request to you; with no interactive terminal, or no valid answer, it denies.\",\n \"context\": \"Markdown whose permission requests are asked about.\"\n },\n {\n \"kind\": \"component\",\n \"name\": \"Assert\",\n \"origin\": {\n \"kind\": \"registered\",\n \"origin\": \"@executablemd/testing\",\n \"reserved\": false\n },\n \"sourceKind\": \"registered\",\n \"inspectability\": \"complete\",\n \"forms\": [\n \"self-closing\"\n ],\n \"props\": {\n \"type\": \"object\",\n \"properties\": {\n \"msg\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n },\n \"captures\": [\n \"expr\"\n ],\n \"returnMode\": \"text\",\n \"returns\": {\n \"type\": \"string\"\n },\n \"description\": \"Assert that a value is truthy — ``. The optional `msg` prop replaces the reported failure message.\",\n \"as\": \"Optional. The diagnostic report this assertion rendered, as text — a passing assertion renders one only while testing or verbose output is on, so the binding is empty otherwise. A failing assertion does not return.\"\n },\n {\n \"kind\": \"component\",\n \"name\": \"AssertEquals\",\n \"origin\": {\n \"kind\": \"registered\",\n \"origin\": \"@executablemd/testing\",\n \"reserved\": false\n },\n \"sourceKind\": \"registered\",\n \"inspectability\": \"complete\",\n \"forms\": [\n \"self-closing\",\n \"paired\"\n ],\n \"props\": {\n \"type\": \"object\",\n \"properties\": {\n \"msg\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n },\n \"captures\": [\n \"actual\",\n \"expected\"\n ],\n \"returnMode\": \"text\",\n \"returns\": {\n \"type\": \"string\"\n },\n \"description\": \"Assert that two values are deeply equal — ``. The optional `msg` prop replaces the reported failure message.\",\n \"as\": \"Optional. The diagnostic report this assertion rendered, as text — a passing assertion renders one only while testing or verbose output is on, so the binding is empty otherwise. A failing assertion does not return.\",\n \"context\": \"The expected value, in place of the `expected` prop.\"\n },\n {\n \"kind\": \"component\",\n \"name\": \"AssertExists\",\n \"origin\": {\n \"kind\": \"registered\",\n \"origin\": \"@executablemd/testing\",\n \"reserved\": false\n },\n \"sourceKind\": \"registered\",\n \"inspectability\": \"complete\",\n \"forms\": [\n \"self-closing\"\n ],\n \"props\": {\n \"type\": \"object\",\n \"properties\": {\n \"msg\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n },\n \"captures\": [\n \"actual\"\n ],\n \"returnMode\": \"text\",\n \"returns\": {\n \"type\": \"string\"\n },\n \"description\": \"Assert that a value is neither null nor undefined — ``. The optional `msg` prop replaces the reported failure message.\",\n \"as\": \"Optional. The diagnostic report this assertion rendered, as text — a passing assertion renders one only while testing or verbose output is on, so the binding is empty otherwise. A failing assertion does not return.\"\n },\n {\n \"kind\": \"component\",\n \"name\": \"AssertFalse\",\n \"origin\": {\n \"kind\": \"registered\",\n \"origin\": \"@executablemd/testing\",\n \"reserved\": false\n },\n \"sourceKind\": \"registered\",\n \"inspectability\": \"complete\",\n \"forms\": [\n \"self-closing\"\n ],\n \"props\": {\n \"type\": \"object\",\n \"properties\": {\n \"msg\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n },\n \"captures\": [\n \"expr\"\n ],\n \"returnMode\": \"text\",\n \"returns\": {\n \"type\": \"string\"\n },\n \"description\": \"Assert that a value is falsy — ``. The optional `msg` prop replaces the reported failure message.\",\n \"as\": \"Optional. The diagnostic report this assertion rendered, as text — a passing assertion renders one only while testing or verbose output is on, so the binding is empty otherwise. A failing assertion does not return.\"\n },\n {\n \"kind\": \"component\",\n \"name\": \"AssertGreater\",\n \"origin\": {\n \"kind\": \"registered\",\n \"origin\": \"@executablemd/testing\",\n \"reserved\": false\n },\n \"sourceKind\": \"registered\",\n \"inspectability\": \"complete\",\n \"forms\": [\n \"self-closing\"\n ],\n \"props\": {\n \"type\": \"object\",\n \"properties\": {\n \"msg\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n },\n \"captures\": [\n \"actual\",\n \"expected\"\n ],\n \"returnMode\": \"text\",\n \"returns\": {\n \"type\": \"string\"\n },\n \"description\": \"Assert that one number is greater than another — ``. The optional `msg` prop replaces the reported failure message.\",\n \"as\": \"Optional. The diagnostic report this assertion rendered, as text — a passing assertion renders one only while testing or verbose output is on, so the binding is empty otherwise. A failing assertion does not return.\"\n },\n {\n \"kind\": \"component\",\n \"name\": \"AssertGreaterOrEqual\",\n \"origin\": {\n \"kind\": \"registered\",\n \"origin\": \"@executablemd/testing\",\n \"reserved\": false\n },\n \"sourceKind\": \"registered\",\n \"inspectability\": \"complete\",\n \"forms\": [\n \"self-closing\"\n ],\n \"props\": {\n \"type\": \"object\",\n \"properties\": {\n \"msg\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n },\n \"captures\": [\n \"actual\",\n \"expected\"\n ],\n \"returnMode\": \"text\",\n \"returns\": {\n \"type\": \"string\"\n },\n \"description\": \"Assert that one number is greater than or equal to another — ``. The optional `msg` prop replaces the reported failure message.\",\n \"as\": \"Optional. The diagnostic report this assertion rendered, as text — a passing assertion renders one only while testing or verbose output is on, so the binding is empty otherwise. A failing assertion does not return.\"\n },\n {\n \"kind\": \"component\",\n \"name\": \"AssertLess\",\n \"origin\": {\n \"kind\": \"registered\",\n \"origin\": \"@executablemd/testing\",\n \"reserved\": false\n },\n \"sourceKind\": \"registered\",\n \"inspectability\": \"complete\",\n \"forms\": [\n \"self-closing\"\n ],\n \"props\": {\n \"type\": \"object\",\n \"properties\": {\n \"msg\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n },\n \"captures\": [\n \"actual\",\n \"expected\"\n ],\n \"returnMode\": \"text\",\n \"returns\": {\n \"type\": \"string\"\n },\n \"description\": \"Assert that one number is less than another — ``. The optional `msg` prop replaces the reported failure message.\",\n \"as\": \"Optional. The diagnostic report this assertion rendered, as text — a passing assertion renders one only while testing or verbose output is on, so the binding is empty otherwise. A failing assertion does not return.\"\n },\n {\n \"kind\": \"component\",\n \"name\": \"AssertLessOrEqual\",\n \"origin\": {\n \"kind\": \"registered\",\n \"origin\": \"@executablemd/testing\",\n \"reserved\": false\n },\n \"sourceKind\": \"registered\",\n \"inspectability\": \"complete\",\n \"forms\": [\n \"self-closing\"\n ],\n \"props\": {\n \"type\": \"object\",\n \"properties\": {\n \"msg\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n },\n \"captures\": [\n \"actual\",\n \"expected\"\n ],\n \"returnMode\": \"text\",\n \"returns\": {\n \"type\": \"string\"\n },\n \"description\": \"Assert that one number is less than or equal to another — ``. The optional `msg` prop replaces the reported failure message.\",\n \"as\": \"Optional. The diagnostic report this assertion rendered, as text — a passing assertion renders one only while testing or verbose output is on, so the binding is empty otherwise. A failing assertion does not return.\"\n },\n {\n \"kind\": \"component\",\n \"name\": \"AssertMatch\",\n \"origin\": {\n \"kind\": \"registered\",\n \"origin\": \"@executablemd/testing\",\n \"reserved\": false\n },\n \"sourceKind\": \"registered\",\n \"inspectability\": \"complete\",\n \"forms\": [\n \"self-closing\"\n ],\n \"props\": {\n \"type\": \"object\",\n \"properties\": {\n \"msg\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n },\n \"captures\": [\n \"actual\",\n \"expected\"\n ],\n \"returnMode\": \"text\",\n \"returns\": {\n \"type\": \"string\"\n },\n \"description\": \"Assert that a string matches a pattern — ``. The optional `msg` prop replaces the reported failure message.\",\n \"as\": \"Optional. The diagnostic report this assertion rendered, as text — a passing assertion renders one only while testing or verbose output is on, so the binding is empty otherwise. A failing assertion does not return.\"\n },\n {\n \"kind\": \"component\",\n \"name\": \"AssertNotEquals\",\n \"origin\": {\n \"kind\": \"registered\",\n \"origin\": \"@executablemd/testing\",\n \"reserved\": false\n },\n \"sourceKind\": \"registered\",\n \"inspectability\": \"complete\",\n \"forms\": [\n \"self-closing\",\n \"paired\"\n ],\n \"props\": {\n \"type\": \"object\",\n \"properties\": {\n \"msg\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n },\n \"captures\": [\n \"actual\",\n \"expected\"\n ],\n \"returnMode\": \"text\",\n \"returns\": {\n \"type\": \"string\"\n },\n \"description\": \"Assert that two values are not deeply equal — ``. The optional `msg` prop replaces the reported failure message.\",\n \"as\": \"Optional. The diagnostic report this assertion rendered, as text — a passing assertion renders one only while testing or verbose output is on, so the binding is empty otherwise. A failing assertion does not return.\",\n \"context\": \"The expected value, in place of the `expected` prop.\"\n },\n {\n \"kind\": \"component\",\n \"name\": \"AssertNotMatch\",\n \"origin\": {\n \"kind\": \"registered\",\n \"origin\": \"@executablemd/testing\",\n \"reserved\": false\n },\n \"sourceKind\": \"registered\",\n \"inspectability\": \"complete\",\n \"forms\": [\n \"self-closing\"\n ],\n \"props\": {\n \"type\": \"object\",\n \"properties\": {\n \"msg\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n },\n \"captures\": [\n \"actual\",\n \"expected\"\n ],\n \"returnMode\": \"text\",\n \"returns\": {\n \"type\": \"string\"\n },\n \"description\": \"Assert that a string does not match a pattern — ``. The optional `msg` prop replaces the reported failure message.\",\n \"as\": \"Optional. The diagnostic report this assertion rendered, as text — a passing assertion renders one only while testing or verbose output is on, so the binding is empty otherwise. A failing assertion does not return.\"\n },\n {\n \"kind\": \"component\",\n \"name\": \"AssertNotStrictEquals\",\n \"origin\": {\n \"kind\": \"registered\",\n \"origin\": \"@executablemd/testing\",\n \"reserved\": false\n },\n \"sourceKind\": \"registered\",\n \"inspectability\": \"complete\",\n \"forms\": [\n \"self-closing\",\n \"paired\"\n ],\n \"props\": {\n \"type\": \"object\",\n \"properties\": {\n \"msg\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n },\n \"captures\": [\n \"actual\",\n \"expected\"\n ],\n \"returnMode\": \"text\",\n \"returns\": {\n \"type\": \"string\"\n },\n \"description\": \"Assert that two values are not the same, compared with `===` — ``. The optional `msg` prop replaces the reported failure message.\",\n \"as\": \"Optional. The diagnostic report this assertion rendered, as text — a passing assertion renders one only while testing or verbose output is on, so the binding is empty otherwise. A failing assertion does not return.\",\n \"context\": \"The expected value, in place of the `expected` prop.\"\n },\n {\n \"kind\": \"component\",\n \"name\": \"AssertStrictEquals\",\n \"origin\": {\n \"kind\": \"registered\",\n \"origin\": \"@executablemd/testing\",\n \"reserved\": false\n },\n \"sourceKind\": \"registered\",\n \"inspectability\": \"complete\",\n \"forms\": [\n \"self-closing\",\n \"paired\"\n ],\n \"props\": {\n \"type\": \"object\",\n \"properties\": {\n \"msg\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n },\n \"captures\": [\n \"actual\",\n \"expected\"\n ],\n \"returnMode\": \"text\",\n \"returns\": {\n \"type\": \"string\"\n },\n \"description\": \"Assert that two values are the same, compared with `===` — ``. The optional `msg` prop replaces the reported failure message.\",\n \"as\": \"Optional. The diagnostic report this assertion rendered, as text — a passing assertion renders one only while testing or verbose output is on, so the binding is empty otherwise. A failing assertion does not return.\",\n \"context\": \"The expected value, in place of the `expected` prop.\"\n },\n {\n \"kind\": \"component\",\n \"name\": \"AssertStringIncludes\",\n \"origin\": {\n \"kind\": \"registered\",\n \"origin\": \"@executablemd/testing\",\n \"reserved\": false\n },\n \"sourceKind\": \"registered\",\n \"inspectability\": \"complete\",\n \"forms\": [\n \"self-closing\",\n \"paired\"\n ],\n \"props\": {\n \"type\": \"object\",\n \"properties\": {\n \"msg\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n },\n \"captures\": [\n \"actual\",\n \"expected\"\n ],\n \"returnMode\": \"text\",\n \"returns\": {\n \"type\": \"string\"\n },\n \"description\": \"Assert that a string contains a substring — ``. The optional `msg` prop replaces the reported failure message.\",\n \"as\": \"Optional. The diagnostic report this assertion rendered, as text — a passing assertion renders one only while testing or verbose output is on, so the binding is empty otherwise. A failing assertion does not return.\",\n \"context\": \"The expected value, in place of the `expected` prop.\"\n },\n {\n \"kind\": \"component\",\n \"name\": \"AssertThrows\",\n \"origin\": {\n \"kind\": \"registered\",\n \"origin\": \"@executablemd/testing\",\n \"reserved\": false\n },\n \"sourceKind\": \"registered\",\n \"inspectability\": \"complete\",\n \"forms\": [\n \"self-closing\",\n \"paired\"\n ],\n \"props\": {\n \"type\": \"object\",\n \"properties\": {},\n \"additionalProperties\": false\n },\n \"captures\": [\n \"message\"\n ],\n \"returnMode\": \"text\",\n \"returns\": {\n \"type\": \"string\"\n },\n \"description\": \"Assert that its content fails. `…` passes only if the content fails with a matching message. `message` is required and takes a string or a regular expression.\",\n \"as\": \"Optional. The complete caught error segment, bound by reference — its `message`, `source` and structured `cause` as they were raised, not a description of them.\",\n \"context\": \"The Markdown expected to fail.\"\n },\n {\n \"kind\": \"component\",\n \"name\": \"CodeBlock\",\n \"origin\": {\n \"kind\": \"registered\",\n \"origin\": \"@executablemd/core\",\n \"reserved\": false\n },\n \"sourceKind\": \"registered\",\n \"inspectability\": \"complete\",\n \"forms\": [\n \"self-closing\"\n ],\n \"props\": {\n \"type\": \"object\",\n \"properties\": {\n \"value\": {\n \"type\": \"string\"\n },\n \"language\": {\n \"type\": \"string\",\n \"pattern\": \"^[A-Za-z0-9][A-Za-z0-9._+#-]*$\"\n }\n },\n \"required\": [\n \"value\"\n ],\n \"additionalProperties\": false\n },\n \"captures\": [],\n \"returnMode\": \"text\",\n \"returns\": {\n \"type\": \"string\"\n },\n \"description\": \"Show arbitrary text as a fenced Markdown code block. `` chooses a fence the value cannot close.\",\n \"as\": \"Optional. Captures the exact fenced Markdown instead of emitting it.\"\n },\n {\n \"kind\": \"component\",\n \"name\": \"CollectJournal\",\n \"origin\": {\n \"kind\": \"registered\",\n \"origin\": \"@executablemd/testing\",\n \"reserved\": false\n },\n \"sourceKind\": \"registered\",\n \"inspectability\": \"complete\",\n \"forms\": [\n \"self-closing\",\n \"paired\"\n ],\n \"props\": {\n \"type\": \"object\",\n \"properties\": {},\n \"additionalProperties\": false\n },\n \"captures\": [],\n \"returnMode\": \"text\",\n \"returns\": {\n \"type\": \"string\"\n },\n \"description\": \"Capture a child execution's journal so a test can assert on it. `` goes inside ``, beside ``. It reads a journal the run already has — pair it with `` to create one.\",\n \"as\": \"Required. The journal snapshot.\"\n },\n {\n \"kind\": \"component\",\n \"name\": \"CollectOutput\",\n \"origin\": {\n \"kind\": \"registered\",\n \"origin\": \"@executablemd/testing\",\n \"reserved\": false\n },\n \"sourceKind\": \"registered\",\n \"inspectability\": \"complete\",\n \"forms\": [\n \"self-closing\",\n \"paired\"\n ],\n \"props\": {\n \"type\": \"object\",\n \"properties\": {},\n \"additionalProperties\": false\n },\n \"captures\": [],\n \"returnMode\": \"text\",\n \"returns\": {\n \"type\": \"string\"\n },\n \"description\": \"Capture a child execution's output so a test can assert on it. `` goes inside ``, before the assertions, and is invalid anywhere else. It changes nothing about the run, and a child that fails partway still leaves what it printed.\",\n \"as\": \"Required. The child's accumulated output.\"\n },\n {\n \"kind\": \"component\",\n \"name\": \"Cwd\",\n \"origin\": {\n \"kind\": \"registered\",\n \"origin\": \"@executablemd/core\",\n \"reserved\": false\n },\n \"sourceKind\": \"registered\",\n \"inspectability\": \"complete\",\n \"forms\": [\n \"self-closing\"\n ],\n \"props\": {\n \"type\": \"object\",\n \"properties\": {},\n \"additionalProperties\": false\n },\n \"captures\": [],\n \"returnMode\": \"text\",\n \"returns\": {\n \"type\": \"string\"\n },\n \"description\": \"Read the working directory. `` renders its path without adding a newline.\",\n \"as\": \"Optional. Captures the directory path instead of emitting it.\"\n },\n {\n \"kind\": \"component\",\n \"name\": \"DiagnosticJournal\",\n \"origin\": {\n \"kind\": \"registered\",\n \"origin\": \"@executablemd/testing\",\n \"reserved\": false\n },\n \"sourceKind\": \"registered\",\n \"inspectability\": \"complete\",\n \"forms\": [\n \"self-closing\",\n \"paired\"\n ],\n \"props\": {\n \"type\": \"object\",\n \"properties\": {},\n \"additionalProperties\": false\n },\n \"captures\": [],\n \"returnMode\": \"text\",\n \"returns\": {\n \"type\": \"string\"\n },\n \"description\": \"Give a child execution a journal of its own. `` goes inside ``, before the assertions, and is invalid anywhere else. Without it the child keeps no journal you can collect — with it, `` has one to read.\"\n },\n {\n \"kind\": \"component\",\n \"name\": \"Dir\",\n \"origin\": {\n \"kind\": \"protected\",\n \"origin\": \"@executablemd/core\"\n },\n \"sourceKind\": \"protected\",\n \"inspectability\": \"complete\",\n \"forms\": [\n \"paired\"\n ],\n \"props\": {\n \"type\": \"object\",\n \"properties\": {\n \"path\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n },\n \"required\": [\n \"path\"\n ],\n \"additionalProperties\": false\n },\n \"captures\": [],\n \"returnMode\": \"text\",\n \"returns\": {\n \"type\": \"string\"\n },\n \"description\": \"Create or use a directory. `…` changes the working directory for its content.\",\n \"context\": \"The Markdown expanded in that directory.\"\n },\n {\n \"kind\": \"component\",\n \"name\": \"Elicit\",\n \"origin\": {\n \"kind\": \"registered\",\n \"origin\": \"@executablemd/core\",\n \"reserved\": false\n },\n \"sourceKind\": \"registered\",\n \"inspectability\": \"complete\",\n \"forms\": [\n \"self-closing\",\n \"paired\"\n ],\n \"props\": {\n \"type\": \"object\",\n \"properties\": {\n \"schema\": {}\n },\n \"required\": [\n \"schema\"\n ],\n \"additionalProperties\": false\n },\n \"captures\": [],\n \"returnMode\": \"value\",\n \"returns\": {\n \"$schema\": \"http://json-schema.org/draft-07/schema#\"\n },\n \"description\": \"Ask a person a structured question. `…` shows the content as the request.\",\n \"as\": \"Required. The validated answer, as a structured value.\",\n \"context\": \"The request message the person is shown.\"\n },\n {\n \"kind\": \"component\",\n \"name\": \"Evaluate\",\n \"origin\": {\n \"kind\": \"protected\",\n \"origin\": \"@executablemd/core\"\n },\n \"sourceKind\": \"protected\",\n \"inspectability\": \"complete\",\n \"forms\": [\n \"self-closing\",\n \"paired\"\n ],\n \"props\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"The program to evaluate, for the self-closing form. Written instead of content, never beside it.\"\n },\n \"allow\": {\n \"type\": \"array\",\n \"minItems\": 1,\n \"uniqueItems\": true,\n \"items\": {\n \"enum\": [\n \"read\",\n \"write\"\n ]\n },\n \"description\": \"Optional. Which effect classes the program may draw on, narrowing what this host already installed. Omitted asks for `read`.\"\n }\n },\n \"additionalProperties\": false\n },\n \"captures\": [],\n \"returnMode\": \"text\",\n \"returns\": {\n \"type\": \"string\"\n },\n \"description\": \"Evaluate program text. `` runs it.\",\n \"as\": \"Optional. Captures the fragment's rendered output instead of emitting it.\"\n },\n {\n \"kind\": \"component\",\n \"name\": \"Execution\",\n \"origin\": {\n \"kind\": \"registered\",\n \"origin\": \"@executablemd/testing\",\n \"reserved\": false\n },\n \"sourceKind\": \"registered\",\n \"inspectability\": \"complete\",\n \"forms\": [\n \"self-closing\",\n \"paired\"\n ],\n \"props\": {\n \"type\": \"object\",\n \"properties\": {\n \"host\": {\n \"type\": \"string\"\n },\n \"target\": {\n \"type\": \"string\"\n },\n \"source\": {\n \"type\": \"string\"\n },\n \"action\": {\n \"type\": \"string\"\n },\n \"props\": {\n \"type\": \"object\"\n }\n },\n \"required\": [\n \"host\"\n ],\n \"additionalProperties\": false\n },\n \"captures\": [],\n \"returnMode\": \"text\",\n \"returns\": {\n \"type\": \"string\"\n },\n \"description\": \"Run another document from inside a test, and assert on how it finished. `…` runs it for real, with its own journal and output. Pass `source` instead of `target` to supply the markdown directly, and `props` for the document's properties.\",\n \"as\": \"Optional. The child's outcome: a settled result, or a suspension. Without it a settled failure fails the owning test rather than passing vacuously.\",\n \"context\": \"The declarations for the child, then the assertions about it.\"\n },\n {\n \"kind\": \"component\",\n \"name\": \"Fail\",\n \"origin\": {\n \"kind\": \"registered\",\n \"origin\": \"@executablemd/core\",\n \"reserved\": false\n },\n \"sourceKind\": \"registered\",\n \"inspectability\": \"complete\",\n \"forms\": [\n \"self-closing\"\n ],\n \"props\": {\n \"type\": \"object\",\n \"properties\": {\n \"message\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n },\n \"required\": [\n \"message\"\n ],\n \"additionalProperties\": false\n },\n \"captures\": [],\n \"returnMode\": \"text\",\n \"returns\": {\n \"type\": \"string\"\n },\n \"description\": \"Stop authored work with an actionable failure. `` raises the message where it is written.\"\n },\n {\n \"kind\": \"component\",\n \"name\": \"Fetch\",\n \"origin\": {\n \"kind\": \"registered\",\n \"origin\": \"@executablemd/core\",\n \"reserved\": false\n },\n \"sourceKind\": \"registered\",\n \"inspectability\": \"complete\",\n \"forms\": [\n \"self-closing\",\n \"paired\"\n ],\n \"props\": {\n \"type\": \"object\",\n \"properties\": {\n \"url\": {\n \"type\": \"string\"\n },\n \"method\": {\n \"type\": \"string\"\n },\n \"headers\": {\n \"type\": \"object\",\n \"additionalProperties\": {\n \"type\": \"string\"\n }\n },\n \"timeout\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"url\"\n ],\n \"additionalProperties\": false\n },\n \"captures\": [],\n \"returnMode\": \"text\",\n \"returns\": {\n \"type\": \"string\"\n },\n \"description\": \"Fetch a URL. `` binds the response, and any status is data you can branch on. Without `as`, a non-2xx status fails. Only GET and HEAD methods currently supported.\",\n \"as\": \"Optional. Captures the response, which is what makes a non-2xx status data instead of a failure.\"\n },\n {\n \"kind\": \"component\",\n \"name\": \"File\",\n \"origin\": {\n \"kind\": \"protected\",\n \"origin\": \"@executablemd/core\"\n },\n \"sourceKind\": \"protected\",\n \"inspectability\": \"complete\",\n \"forms\": [\n \"self-closing\",\n \"paired\"\n ],\n \"props\": {\n \"type\": \"object\",\n \"properties\": {\n \"path\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"path\"\n ],\n \"additionalProperties\": false\n },\n \"captures\": [],\n \"returnMode\": \"text\",\n \"returns\": {\n \"type\": \"string\"\n },\n \"description\": \"Read or write a file. `` reads the content; `…` writes the content. The path is relative to the working directory.\",\n \"as\": \"Optional. Captures the file's text instead of emitting it, in the reading form.\",\n \"context\": \"The text to write, in the writing form.\"\n },\n {\n \"kind\": \"component\",\n \"name\": \"File.Delete\",\n \"origin\": {\n \"kind\": \"protected\",\n \"origin\": \"@executablemd/core\"\n },\n \"sourceKind\": \"protected\",\n \"inspectability\": \"complete\",\n \"forms\": [\n \"self-closing\"\n ],\n \"props\": {\n \"type\": \"object\",\n \"properties\": {\n \"path\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n },\n \"required\": [\n \"path\"\n ],\n \"additionalProperties\": false\n },\n \"captures\": [],\n \"returnMode\": \"text\",\n \"returns\": {\n \"type\": \"string\"\n },\n \"description\": \"Delete a file. `` removes it. It does not error if the file doesn't exist, and produces no output.\",\n \"as\": \"Optional. Captures the empty string this renders, as for any text component.\"\n },\n {\n \"kind\": \"component\",\n \"name\": \"Git.Add\",\n \"origin\": {\n \"kind\": \"registered\",\n \"origin\": \"@executablemd/workflow/composition\",\n \"reserved\": false\n },\n \"sourceKind\": \"registered\",\n \"inspectability\": \"complete\",\n \"forms\": [\n \"self-closing\",\n \"paired\"\n ],\n \"props\": {\n \"type\": \"object\",\n \"properties\": {\n \"paths\": {\n \"anyOf\": [\n {\n \"type\": \"string\",\n \"minLength\": 1\n },\n {\n \"type\": \"array\",\n \"minItems\": 1,\n \"items\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n }\n ]\n }\n },\n \"required\": [\n \"paths\"\n ],\n \"additionalProperties\": false\n },\n \"captures\": [],\n \"returnMode\": \"text\",\n \"returns\": {\n \"type\": \"string\"\n },\n \"description\": \"Stage paths for commit. `` resolves Git pathspecs from the working directory.\"\n },\n {\n \"kind\": \"component\",\n \"name\": \"Git.Changes\",\n \"origin\": {\n \"kind\": \"registered\",\n \"origin\": \"@executablemd/workflow/composition\",\n \"reserved\": false\n },\n \"sourceKind\": \"registered\",\n \"inspectability\": \"complete\",\n \"forms\": [\n \"self-closing\",\n \"paired\"\n ],\n \"props\": {\n \"type\": \"object\",\n \"properties\": {\n \"compare\": {\n \"enum\": [\n \"unstaged\",\n \"staged\",\n \"commits\"\n ]\n },\n \"base\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"head\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"paths\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n },\n \"limit\": {\n \"type\": \"integer\",\n \"minimum\": 1\n },\n \"cursor\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n },\n \"required\": [\n \"compare\"\n ],\n \"additionalProperties\": false\n },\n \"captures\": [],\n \"returnMode\": \"value\",\n \"returns\": {\n \"type\": \"object\",\n \"properties\": {\n \"comparison\": {\n \"oneOf\": [\n {\n \"type\": \"object\",\n \"properties\": {\n \"compare\": {\n \"const\": \"unstaged\"\n }\n },\n \"required\": [\n \"compare\"\n ],\n \"additionalProperties\": false\n },\n {\n \"type\": \"object\",\n \"properties\": {\n \"compare\": {\n \"const\": \"staged\"\n },\n \"base\": {\n \"type\": [\n \"string\",\n \"null\"\n ]\n }\n },\n \"required\": [\n \"compare\",\n \"base\"\n ],\n \"additionalProperties\": false\n },\n {\n \"type\": \"object\",\n \"properties\": {\n \"compare\": {\n \"const\": \"commits\"\n },\n \"base\": {\n \"type\": \"string\"\n },\n \"head\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"compare\",\n \"base\",\n \"head\"\n ],\n \"additionalProperties\": false\n }\n ]\n },\n \"changes\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"path\": {\n \"type\": \"string\"\n },\n \"status\": {\n \"enum\": [\n \"A\",\n \"M\",\n \"D\",\n \"R\",\n \"T\",\n \"U\"\n ]\n },\n \"previousPath\": {\n \"type\": [\n \"string\",\n \"null\"\n ]\n }\n },\n \"required\": [\n \"path\",\n \"status\",\n \"previousPath\"\n ],\n \"additionalProperties\": false\n }\n },\n \"next\": {\n \"type\": [\n \"object\",\n \"null\"\n ],\n \"properties\": {\n \"compare\": {\n \"enum\": [\n \"unstaged\",\n \"staged\",\n \"commits\"\n ]\n },\n \"base\": {\n \"type\": \"string\"\n },\n \"head\": {\n \"type\": \"string\"\n },\n \"paths\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n },\n \"limit\": {\n \"type\": \"integer\",\n \"minimum\": 1\n },\n \"cursor\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n },\n \"required\": [\n \"compare\",\n \"limit\",\n \"cursor\"\n ],\n \"additionalProperties\": false\n }\n },\n \"required\": [\n \"comparison\",\n \"changes\",\n \"next\"\n ],\n \"additionalProperties\": false\n },\n \"description\": \"Compare what changed. `` reports each changed path and its status for unstaged, staged or two commits.\",\n \"as\": \"Required. The comparison, each change's path, status and previous path, and the next page or null.\"\n },\n {\n \"kind\": \"component\",\n \"name\": \"Git.Commit\",\n \"origin\": {\n \"kind\": \"registered\",\n \"origin\": \"@executablemd/workflow/composition\",\n \"reserved\": false\n },\n \"sourceKind\": \"registered\",\n \"inspectability\": \"complete\",\n \"forms\": [\n \"self-closing\",\n \"paired\"\n ],\n \"props\": {\n \"type\": \"object\",\n \"properties\": {\n \"message\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"ref\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"verify\": {\n \"type\": \"boolean\"\n },\n \"yq\": {\n \"type\": \"string\"\n },\n \"maxBytes\": {\n \"type\": \"integer\",\n \"minimum\": 1\n }\n },\n \"additionalProperties\": false\n },\n \"captures\": [],\n \"returnMode\": \"value\",\n \"returns\": {\n \"anyOf\": [\n {\n \"type\": \"string\",\n \"pattern\": \"^([0-9a-f]{40}|[0-9a-f]{64})$\"\n },\n {\n \"type\": \"object\",\n \"properties\": {\n \"value\": {},\n \"next\": {\n \"type\": [\n \"string\",\n \"null\"\n ]\n },\n \"prev\": {\n \"type\": [\n \"string\",\n \"null\"\n ]\n },\n \"last\": {\n \"type\": [\n \"string\",\n \"null\"\n ]\n }\n },\n \"required\": [\n \"value\",\n \"next\",\n \"prev\",\n \"last\"\n ],\n \"additionalProperties\": false\n }\n ]\n },\n \"description\": \"Commit staged changes, or read an existing commit. `Prepare 1.4` uses its expanded content as the commit message. `` reads that commit's metadata and runs the checkout's configured signature verifier; your Markdown decides what the result permits.\",\n \"as\": \"Required. Creating binds the full object id of the new commit. A ref read binds value, next, prev and last: the yq selection and the queries that read its neighbouring pages.\",\n \"context\": \"The message body, expanded before the commit is made. A ref read takes none.\"\n },\n {\n \"kind\": \"component\",\n \"name\": \"Git.Diff\",\n \"origin\": {\n \"kind\": \"registered\",\n \"origin\": \"@executablemd/workflow/composition\",\n \"reserved\": false\n },\n \"sourceKind\": \"registered\",\n \"inspectability\": \"complete\",\n \"forms\": [\n \"self-closing\",\n \"paired\"\n ],\n \"props\": {\n \"type\": \"object\",\n \"properties\": {\n \"compare\": {\n \"enum\": [\n \"unstaged\",\n \"staged\",\n \"commits\"\n ]\n },\n \"base\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"head\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"paths\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n },\n \"offset\": {\n \"type\": \"integer\",\n \"minimum\": 0\n },\n \"limit\": {\n \"type\": \"integer\",\n \"minimum\": 1\n },\n \"cursor\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n },\n \"required\": [\n \"compare\"\n ],\n \"additionalProperties\": false\n },\n \"captures\": [],\n \"returnMode\": \"value\",\n \"returns\": {\n \"type\": \"object\",\n \"properties\": {\n \"comparison\": {\n \"oneOf\": [\n {\n \"type\": \"object\",\n \"properties\": {\n \"compare\": {\n \"const\": \"unstaged\"\n }\n },\n \"required\": [\n \"compare\"\n ],\n \"additionalProperties\": false\n },\n {\n \"type\": \"object\",\n \"properties\": {\n \"compare\": {\n \"const\": \"staged\"\n },\n \"base\": {\n \"type\": [\n \"string\",\n \"null\"\n ]\n }\n },\n \"required\": [\n \"compare\",\n \"base\"\n ],\n \"additionalProperties\": false\n },\n {\n \"type\": \"object\",\n \"properties\": {\n \"compare\": {\n \"const\": \"commits\"\n },\n \"base\": {\n \"type\": \"string\"\n },\n \"head\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"compare\",\n \"base\",\n \"head\"\n ],\n \"additionalProperties\": false\n }\n ]\n },\n \"text\": {\n \"type\": \"string\"\n },\n \"offset\": {\n \"type\": \"integer\",\n \"minimum\": 0\n },\n \"length\": {\n \"type\": \"integer\",\n \"minimum\": 0\n },\n \"next\": {\n \"type\": [\n \"object\",\n \"null\"\n ],\n \"properties\": {\n \"compare\": {\n \"enum\": [\n \"unstaged\",\n \"staged\",\n \"commits\"\n ]\n },\n \"base\": {\n \"type\": \"string\"\n },\n \"head\": {\n \"type\": \"string\"\n },\n \"paths\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n },\n \"offset\": {\n \"type\": \"integer\",\n \"minimum\": 0\n },\n \"limit\": {\n \"type\": \"integer\",\n \"minimum\": 1\n },\n \"cursor\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n },\n \"required\": [\n \"compare\",\n \"offset\",\n \"limit\",\n \"cursor\"\n ],\n \"additionalProperties\": false\n }\n },\n \"required\": [\n \"comparison\",\n \"text\",\n \"offset\",\n \"length\",\n \"next\"\n ],\n \"additionalProperties\": false\n },\n \"description\": \"Read a comparison's patch. `` reads a window of the unified diff text.\",\n \"as\": \"Required. The comparison, the patch window, its offset, the whole length, and the next page or null.\"\n },\n {\n \"kind\": \"component\",\n \"name\": \"Git.File\",\n \"origin\": {\n \"kind\": \"registered\",\n \"origin\": \"@executablemd/workflow/composition\",\n \"reserved\": false\n },\n \"sourceKind\": \"registered\",\n \"inspectability\": \"complete\",\n \"forms\": [\n \"self-closing\",\n \"paired\"\n ],\n \"props\": {\n \"type\": \"object\",\n \"properties\": {\n \"commit\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"path\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"offset\": {\n \"type\": \"integer\",\n \"minimum\": 0\n },\n \"limit\": {\n \"type\": \"integer\",\n \"minimum\": 1\n }\n },\n \"required\": [\n \"commit\",\n \"path\"\n ],\n \"additionalProperties\": false\n },\n \"captures\": [],\n \"returnMode\": \"value\",\n \"returns\": {\n \"type\": \"object\",\n \"properties\": {\n \"commit\": {\n \"type\": \"string\"\n },\n \"path\": {\n \"type\": \"string\"\n },\n \"text\": {\n \"type\": \"string\"\n },\n \"offset\": {\n \"type\": \"integer\",\n \"minimum\": 0\n },\n \"length\": {\n \"type\": \"integer\",\n \"minimum\": 0\n },\n \"next\": {\n \"type\": [\n \"object\",\n \"null\"\n ],\n \"properties\": {\n \"commit\": {\n \"type\": \"string\"\n },\n \"path\": {\n \"type\": \"string\"\n },\n \"offset\": {\n \"type\": \"integer\",\n \"minimum\": 0\n },\n \"limit\": {\n \"type\": \"integer\",\n \"minimum\": 1\n }\n },\n \"required\": [\n \"commit\",\n \"path\",\n \"offset\",\n \"limit\"\n ],\n \"additionalProperties\": false\n }\n },\n \"required\": [\n \"commit\",\n \"path\",\n \"text\",\n \"offset\",\n \"length\",\n \"next\"\n ],\n \"additionalProperties\": false\n },\n \"description\": \"Read a committed file. `` reads the text that commit holds, not the working copy.\",\n \"as\": \"Required. The resolved commit, the path, the text window, its offset, the whole length, and the next page or null.\"\n },\n {\n \"kind\": \"component\",\n \"name\": \"Git.Files\",\n \"origin\": {\n \"kind\": \"registered\",\n \"origin\": \"@executablemd/workflow/composition\",\n \"reserved\": false\n },\n \"sourceKind\": \"registered\",\n \"inspectability\": \"complete\",\n \"forms\": [\n \"self-closing\",\n \"paired\"\n ],\n \"props\": {\n \"type\": \"object\",\n \"properties\": {\n \"prefix\": {\n \"type\": \"string\"\n },\n \"limit\": {\n \"type\": \"integer\",\n \"minimum\": 1\n },\n \"cursor\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n },\n \"required\": [],\n \"additionalProperties\": false\n },\n \"captures\": [],\n \"returnMode\": \"value\",\n \"returns\": {\n \"type\": \"object\",\n \"properties\": {\n \"paths\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n },\n \"next\": {\n \"type\": [\n \"object\",\n \"null\"\n ],\n \"properties\": {\n \"prefix\": {\n \"type\": \"string\"\n },\n \"limit\": {\n \"type\": \"integer\",\n \"minimum\": 1\n },\n \"cursor\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n },\n \"required\": [\n \"limit\",\n \"cursor\"\n ],\n \"additionalProperties\": false\n }\n },\n \"required\": [\n \"paths\",\n \"next\"\n ],\n \"additionalProperties\": false\n },\n \"description\": \"List tracked files. `` lists the selected repository's tracked paths, bounded and continuable.\",\n \"as\": \"Required. The tracked paths, and the arguments of the next page or null.\"\n },\n {\n \"kind\": \"component\",\n \"name\": \"Git.Push\",\n \"origin\": {\n \"kind\": \"registered\",\n \"origin\": \"@executablemd/workflow/composition\",\n \"reserved\": false\n },\n \"sourceKind\": \"registered\",\n \"inspectability\": \"complete\",\n \"forms\": [\n \"self-closing\"\n ],\n \"props\": {\n \"type\": \"object\",\n \"properties\": {},\n \"additionalProperties\": false\n },\n \"captures\": [],\n \"returnMode\": \"text\",\n \"returns\": {\n \"type\": \"string\"\n },\n \"description\": \"Publish the current branch. `` pushes its current commit to the same branch on `origin` without forcing.\"\n },\n {\n \"kind\": \"component\",\n \"name\": \"Git.Switch\",\n \"origin\": {\n \"kind\": \"registered\",\n \"origin\": \"@executablemd/workflow/composition\",\n \"reserved\": false\n },\n \"sourceKind\": \"registered\",\n \"inspectability\": \"complete\",\n \"forms\": [\n \"self-closing\",\n \"paired\"\n ],\n \"props\": {\n \"type\": \"object\",\n \"properties\": {\n \"branch\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"base\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n },\n \"required\": [\n \"branch\"\n ],\n \"additionalProperties\": false\n },\n \"captures\": [],\n \"returnMode\": \"text\",\n \"returns\": {\n \"type\": \"string\"\n },\n \"description\": \"Switch or create a branch. `` starts a missing branch at the specified base.\"\n },\n {\n \"kind\": \"component\",\n \"name\": \"Glob\",\n \"origin\": {\n \"kind\": \"registered\",\n \"origin\": \"@executablemd/core\",\n \"reserved\": false\n },\n \"sourceKind\": \"registered\",\n \"inspectability\": \"complete\",\n \"forms\": [\n \"self-closing\",\n \"paired\"\n ],\n \"props\": {\n \"type\": \"object\",\n \"properties\": {\n \"include\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n },\n \"minItems\": 1\n },\n \"exclude\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n },\n \"default\": []\n }\n },\n \"required\": [\n \"include\"\n ],\n \"additionalProperties\": false\n },\n \"captures\": [],\n \"returnMode\": \"value\",\n \"returns\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n },\n \"description\": \"List files by pattern. `` matches paths relative to the working directory. The list is sorted. Directories and symbolic links are never results.\",\n \"as\": \"Required. The matched paths, as a string array.\"\n },\n {\n \"kind\": \"component\",\n \"name\": \"Issue\",\n \"origin\": {\n \"kind\": \"registered\",\n \"origin\": \"@executablemd/workflow/composition\",\n \"reserved\": false\n },\n \"sourceKind\": \"registered\",\n \"inspectability\": \"complete\",\n \"forms\": [\n \"self-closing\",\n \"paired\"\n ],\n \"props\": {\n \"type\": \"object\",\n \"properties\": {\n \"url\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"title\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"tags\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n },\n \"assignee\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"provider\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n },\n \"captures\": [],\n \"returnMode\": \"value\",\n \"returns\": {\n \"oneOf\": [\n {\n \"type\": \"object\",\n \"properties\": {\n \"url\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n },\n \"required\": [\n \"url\"\n ],\n \"additionalProperties\": false\n },\n {\n \"type\": \"object\",\n \"properties\": {\n \"url\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"title\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"description\": {\n \"type\": \"string\"\n },\n \"tags\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n },\n \"assignee\": {\n \"type\": [\n \"string\",\n \"null\"\n ]\n }\n },\n \"required\": [\n \"url\",\n \"title\",\n \"description\",\n \"tags\",\n \"assignee\"\n ],\n \"additionalProperties\": false\n }\n ]\n },\n \"description\": \"Read or file an issue. `` reads one. `…` files its content in the issue tracker in scope.\",\n \"as\": \"Required for a read, which binds url, title, description, tags and assignee. A file binds the url alone.\",\n \"context\": \"The issue's description, for the form that files one.\"\n },\n {\n \"kind\": \"component\",\n \"name\": \"IssueTracker\",\n \"origin\": {\n \"kind\": \"registered\",\n \"origin\": \"@executablemd/workflow/composition\",\n \"reserved\": false\n },\n \"sourceKind\": \"registered\",\n \"inspectability\": \"complete\",\n \"forms\": [\n \"self-closing\",\n \"paired\"\n ],\n \"props\": {\n \"type\": \"object\",\n \"properties\": {\n \"url\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"provider\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"url\"\n ],\n \"additionalProperties\": false\n },\n \"captures\": [],\n \"returnMode\": \"text\",\n \"returns\": {\n \"type\": \"string\"\n },\n \"description\": \"Select an issue tracker. `…` expands its content with the specified tracker in scope.\",\n \"context\": \"The Markdown whose issues are filed there.\"\n },\n {\n \"kind\": \"component\",\n \"name\": \"Json\",\n \"origin\": {\n \"kind\": \"registered\",\n \"origin\": \"@executablemd/core\",\n \"reserved\": false\n },\n \"sourceKind\": \"registered\",\n \"inspectability\": \"complete\",\n \"forms\": [\n \"self-closing\"\n ],\n \"props\": {\n \"type\": \"object\",\n \"properties\": {},\n \"additionalProperties\": false\n },\n \"captures\": [\n \"value\"\n ],\n \"returnMode\": \"text\",\n \"returns\": {\n \"type\": \"string\"\n },\n \"description\": \"Render a value as JSON text. `` writes the JSON where you put it.\",\n \"as\": \"Optional. Captures the JSON text instead of emitting it.\"\n },\n {\n \"kind\": \"component\",\n \"name\": \"Parse\",\n \"origin\": {\n \"kind\": \"registered\",\n \"origin\": \"@executablemd/core\",\n \"reserved\": false\n },\n \"sourceKind\": \"registered\",\n \"inspectability\": \"complete\",\n \"forms\": [\n \"self-closing\",\n \"paired\"\n ],\n \"props\": {\n \"type\": \"object\",\n \"properties\": {\n \"schema\": {}\n },\n \"required\": [\n \"schema\"\n ],\n \"additionalProperties\": false\n },\n \"captures\": [],\n \"returnMode\": \"value\",\n \"returns\": {\n \"$schema\": \"http://json-schema.org/draft-07/schema#\"\n },\n \"description\": \"Parse a value using a JSON schema. `…` parses its content. Errors on invalid content.\",\n \"as\": \"Required. The validated value.\",\n \"context\": \"The JSON text to parse.\"\n },\n {\n \"kind\": \"component\",\n \"name\": \"Plan\",\n \"origin\": {\n \"kind\": \"declared-markdown\",\n \"origin\": \"@executablemd/cli/Plan.md\",\n \"digest\": \"d97953c7f65cde0a2858761245d94e06cd31aaba6feb15622256d4dddcaafec2\"\n },\n \"sourceKind\": \"declared-markdown\",\n \"inspectability\": \"complete\",\n \"forms\": [\n \"paired\"\n ],\n \"props\": {\n \"type\": \"object\",\n \"properties\": {\n \"session\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n },\n \"additionalProperties\": false\n },\n \"captures\": [],\n \"returnMode\": \"text\",\n \"returns\": {\n \"type\": \"string\"\n },\n \"description\": \"Generate program text from a prompt. `Ask for the user's age.` emits the approved program text; `` runs it.\",\n \"as\": \"Binds the exact approved program source and emits nothing. Omitted, that source is emitted where the component is written.\",\n \"context\": \"The complete prompt, expanded once before authorship.\"\n },\n {\n \"kind\": \"component\",\n \"name\": \"Prompt\",\n \"origin\": {\n \"kind\": \"registered\",\n \"origin\": \"@executablemd/core\",\n \"reserved\": false\n },\n \"sourceKind\": \"registered\",\n \"inspectability\": \"complete\",\n \"forms\": [\n \"self-closing\",\n \"paired\"\n ],\n \"props\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\"\n },\n \"agent\": {\n \"type\": \"string\"\n },\n \"session\": {\n \"type\": \"string\"\n },\n \"timeout\": {\n \"type\": \"string\"\n },\n \"throwOnError\": {\n \"type\": \"boolean\"\n }\n },\n \"additionalProperties\": false\n },\n \"captures\": [],\n \"returnMode\": \"text\",\n \"returns\": {\n \"type\": \"string\"\n },\n \"description\": \"Send a prompt and render the reply. `…` sends its content; `` sends the prop. `agent`, `session` and `timeout` override the surrounding scope. A failed prompt renders what it got and the document continues — `throwOnError` stops it instead.\",\n \"as\": \"Optional. Captures the reply instead of emitting it.\",\n \"context\": \"The prompt text, in the paired form.\"\n },\n {\n \"kind\": \"component\",\n \"name\": \"PullRequest\",\n \"origin\": {\n \"kind\": \"registered\",\n \"origin\": \"@executablemd/workflow/composition\",\n \"reserved\": false\n },\n \"sourceKind\": \"registered\",\n \"inspectability\": \"complete\",\n \"forms\": [\n \"self-closing\",\n \"paired\"\n ],\n \"props\": {\n \"type\": \"object\",\n \"properties\": {\n \"number\": {\n \"type\": \"integer\",\n \"minimum\": 1\n },\n \"title\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"base\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"draft\": {\n \"type\": \"boolean\",\n \"default\": false\n }\n },\n \"required\": [\n \"title\"\n ],\n \"additionalProperties\": false\n },\n \"captures\": [],\n \"returnMode\": \"value\",\n \"returns\": {\n \"type\": \"object\",\n \"properties\": {\n \"repository\": {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"locatorFingerprint\": {\n \"type\": \"string\",\n \"pattern\": \"^[0-9a-f]{64}$\"\n },\n \"requestedBase\": {\n \"type\": [\n \"string\",\n \"null\"\n ]\n },\n \"creationCommit\": {\n \"type\": \"string\",\n \"pattern\": \"^([0-9a-f]{40}|[0-9a-f]{64})$\"\n },\n \"primaryBranch\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"objectFormat\": {\n \"enum\": [\n \"sha1\",\n \"sha256\"\n ]\n }\n },\n \"required\": [\n \"name\",\n \"locatorFingerprint\",\n \"requestedBase\",\n \"creationCommit\",\n \"primaryBranch\",\n \"objectFormat\"\n ],\n \"additionalProperties\": false\n },\n \"providerId\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"number\": {\n \"type\": \"integer\",\n \"minimum\": 1\n },\n \"url\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"state\": {\n \"const\": \"open\"\n },\n \"headSha\": {\n \"type\": \"string\",\n \"pattern\": \"^([0-9a-f]{40}|[0-9a-f]{64})$\"\n },\n \"baseSha\": {\n \"type\": \"string\",\n \"pattern\": \"^([0-9a-f]{40}|[0-9a-f]{64})$\"\n }\n },\n \"required\": [\n \"repository\",\n \"providerId\",\n \"number\",\n \"url\",\n \"state\",\n \"headSha\",\n \"baseSha\"\n ],\n \"additionalProperties\": false\n },\n \"description\": \"Open or update a pull request. `…` uses its content as the body after ``.\",\n \"as\": \"Optional. The pull request's repository, number, url, state and head and base commits.\",\n \"context\": \"The pull request's body.\"\n },\n {\n \"kind\": \"component\",\n \"name\": \"PullRequest.Checks\",\n \"origin\": {\n \"kind\": \"registered\",\n \"origin\": \"@executablemd/workflow/composition\",\n \"reserved\": false\n },\n \"sourceKind\": \"registered\",\n \"inspectability\": \"complete\",\n \"forms\": [\n \"self-closing\"\n ],\n \"props\": {\n \"type\": \"object\",\n \"properties\": {\n \"url\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"provider\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n },\n \"required\": [\n \"url\"\n ],\n \"additionalProperties\": false\n },\n \"captures\": [],\n \"returnMode\": \"value\",\n \"returns\": {\n \"type\": \"array\",\n \"items\": {\n \"oneOf\": [\n {\n \"type\": \"object\",\n \"properties\": {\n \"kind\": {\n \"const\": \"check-run\"\n },\n \"id\": {\n \"type\": \"string\"\n },\n \"headSha\": {\n \"type\": \"string\"\n },\n \"name\": {\n \"type\": \"string\"\n },\n \"status\": {\n \"enum\": [\n \"queued\",\n \"in_progress\",\n \"completed\",\n \"waiting\",\n \"requested\",\n \"pending\"\n ]\n },\n \"conclusion\": {\n \"enum\": [\n \"success\",\n \"failure\",\n \"neutral\",\n \"cancelled\",\n \"skipped\",\n \"timed_out\",\n \"action_required\",\n null\n ]\n },\n \"url\": {\n \"type\": [\n \"string\",\n \"null\"\n ]\n },\n \"startedAt\": {\n \"type\": [\n \"string\",\n \"null\"\n ]\n },\n \"completedAt\": {\n \"type\": [\n \"string\",\n \"null\"\n ]\n },\n \"title\": {\n \"type\": [\n \"string\",\n \"null\"\n ]\n },\n \"summary\": {\n \"type\": [\n \"string\",\n \"null\"\n ]\n },\n \"text\": {\n \"type\": [\n \"string\",\n \"null\"\n ]\n }\n },\n \"required\": [\n \"kind\",\n \"id\",\n \"headSha\",\n \"name\",\n \"status\",\n \"conclusion\",\n \"url\",\n \"startedAt\",\n \"completedAt\",\n \"title\",\n \"summary\",\n \"text\"\n ],\n \"additionalProperties\": false\n },\n {\n \"type\": \"object\",\n \"properties\": {\n \"kind\": {\n \"const\": \"commit-status\"\n },\n \"id\": {\n \"type\": \"string\"\n },\n \"headSha\": {\n \"type\": \"string\"\n },\n \"name\": {\n \"type\": \"string\"\n },\n \"state\": {\n \"enum\": [\n \"error\",\n \"failure\",\n \"pending\",\n \"success\"\n ]\n },\n \"description\": {\n \"type\": [\n \"string\",\n \"null\"\n ]\n },\n \"url\": {\n \"type\": [\n \"string\",\n \"null\"\n ]\n },\n \"createdAt\": {\n \"type\": \"string\"\n },\n \"updatedAt\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"kind\",\n \"id\",\n \"headSha\",\n \"name\",\n \"state\",\n \"description\",\n \"url\",\n \"createdAt\",\n \"updatedAt\"\n ],\n \"additionalProperties\": false\n }\n ]\n }\n },\n \"description\": \"Read pull request checks. `` reads check runs and commit statuses for its head.\",\n \"as\": \"Required. Each check's kind, name, head commit and outcome.\"\n },\n {\n \"kind\": \"component\",\n \"name\": \"PullRequest.Comments\",\n \"origin\": {\n \"kind\": \"registered\",\n \"origin\": \"@executablemd/workflow/composition\",\n \"reserved\": false\n },\n \"sourceKind\": \"registered\",\n \"inspectability\": \"complete\",\n \"forms\": [\n \"self-closing\"\n ],\n \"props\": {\n \"type\": \"object\",\n \"properties\": {\n \"url\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"provider\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n },\n \"required\": [\n \"url\"\n ],\n \"additionalProperties\": false\n },\n \"captures\": [],\n \"returnMode\": \"value\",\n \"returns\": {\n \"type\": \"array\",\n \"items\": {\n \"oneOf\": [\n {\n \"type\": \"object\",\n \"properties\": {\n \"kind\": {\n \"const\": \"conversation\"\n },\n \"id\": {\n \"type\": \"string\"\n },\n \"author\": {\n \"type\": [\n \"string\",\n \"null\"\n ]\n },\n \"body\": {\n \"type\": \"string\"\n },\n \"createdAt\": {\n \"type\": \"string\"\n },\n \"updatedAt\": {\n \"type\": \"string\"\n },\n \"url\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"kind\",\n \"id\",\n \"author\",\n \"body\",\n \"createdAt\",\n \"updatedAt\",\n \"url\"\n ],\n \"additionalProperties\": false\n },\n {\n \"type\": \"object\",\n \"properties\": {\n \"kind\": {\n \"const\": \"review\"\n },\n \"id\": {\n \"type\": \"string\"\n },\n \"reviewId\": {\n \"type\": [\n \"string\",\n \"null\"\n ]\n },\n \"author\": {\n \"type\": [\n \"string\",\n \"null\"\n ]\n },\n \"body\": {\n \"type\": \"string\"\n },\n \"createdAt\": {\n \"type\": \"string\"\n },\n \"updatedAt\": {\n \"type\": \"string\"\n },\n \"url\": {\n \"type\": \"string\"\n },\n \"path\": {\n \"type\": \"string\"\n },\n \"diffHunk\": {\n \"type\": \"string\"\n },\n \"commitSha\": {\n \"type\": \"string\"\n },\n \"originalCommitSha\": {\n \"type\": \"string\"\n },\n \"line\": {\n \"type\": [\n \"integer\",\n \"null\"\n ]\n },\n \"side\": {\n \"enum\": [\n \"left\",\n \"right\",\n null\n ]\n },\n \"startLine\": {\n \"type\": [\n \"integer\",\n \"null\"\n ]\n },\n \"startSide\": {\n \"enum\": [\n \"left\",\n \"right\",\n null\n ]\n },\n \"inReplyToId\": {\n \"type\": [\n \"string\",\n \"null\"\n ]\n }\n },\n \"required\": [\n \"kind\",\n \"id\",\n \"reviewId\",\n \"author\",\n \"body\",\n \"createdAt\",\n \"updatedAt\",\n \"url\",\n \"path\",\n \"diffHunk\",\n \"commitSha\",\n \"originalCommitSha\",\n \"line\",\n \"side\",\n \"startLine\",\n \"startSide\",\n \"inReplyToId\"\n ],\n \"additionalProperties\": false\n }\n ]\n }\n },\n \"description\": \"Read pull request comments. `` reads both conversation and review comments.\",\n \"as\": \"Required. Each comment's kind, author, body, timestamps and url, and a review comment's file, hunk and line.\"\n },\n {\n \"kind\": \"component\",\n \"name\": \"PullRequest.Reviews\",\n \"origin\": {\n \"kind\": \"registered\",\n \"origin\": \"@executablemd/workflow/composition\",\n \"reserved\": false\n },\n \"sourceKind\": \"registered\",\n \"inspectability\": \"complete\",\n \"forms\": [\n \"self-closing\"\n ],\n \"props\": {\n \"type\": \"object\",\n \"properties\": {\n \"url\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"provider\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n },\n \"required\": [\n \"url\"\n ],\n \"additionalProperties\": false\n },\n \"captures\": [],\n \"returnMode\": \"value\",\n \"returns\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\"\n },\n \"author\": {\n \"type\": [\n \"string\",\n \"null\"\n ]\n },\n \"state\": {\n \"enum\": [\n \"approved\",\n \"changes-requested\",\n \"commented\",\n \"dismissed\",\n \"pending\"\n ]\n },\n \"body\": {\n \"type\": \"string\"\n },\n \"submittedAt\": {\n \"type\": [\n \"string\",\n \"null\"\n ]\n },\n \"commitSha\": {\n \"type\": [\n \"string\",\n \"null\"\n ]\n },\n \"url\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"id\",\n \"author\",\n \"state\",\n \"body\",\n \"submittedAt\",\n \"commitSha\",\n \"url\"\n ],\n \"additionalProperties\": false\n }\n },\n \"description\": \"Read pull request reviews. `` reads reviews from the specified pull request.\",\n \"as\": \"Required. Each review's author, state, body, submission time, commit and url.\"\n },\n {\n \"kind\": \"component\",\n \"name\": \"Query\",\n \"origin\": {\n \"kind\": \"registered\",\n \"origin\": \"@executablemd/core\",\n \"reserved\": false\n },\n \"sourceKind\": \"registered\",\n \"inspectability\": \"complete\",\n \"forms\": [\n \"self-closing\"\n ],\n \"props\": {\n \"type\": \"object\",\n \"properties\": {\n \"value\": {},\n \"yq\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n },\n \"required\": [\n \"value\",\n \"yq\"\n ],\n \"additionalProperties\": false\n },\n \"captures\": [],\n \"returnMode\": \"text\",\n \"returns\": {\n \"type\": \"string\"\n },\n \"description\": \"Select part of a value with a yq expression. `` binds the scripts object; the same element without `as` writes the selected value as JSON. Text is decoded only where the expression says `from_json` or `from_yaml`, and an expression that selects nothing or several values says to collect them with `[ … ]`.\",\n \"as\": \"Optional. Binds the selected value as data instead of writing it as JSON.\"\n },\n {\n \"kind\": \"component\",\n \"name\": \"Repository\",\n \"origin\": {\n \"kind\": \"registered\",\n \"origin\": \"@executablemd/workflow/composition\",\n \"reserved\": false\n },\n \"sourceKind\": \"registered\",\n \"inspectability\": \"complete\",\n \"forms\": [\n \"self-closing\",\n \"paired\"\n ],\n \"props\": {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"url\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"base\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n },\n \"required\": [\n \"name\",\n \"url\"\n ],\n \"additionalProperties\": false\n },\n \"captures\": [],\n \"returnMode\": \"text\",\n \"returns\": {\n \"type\": \"string\"\n },\n \"description\": \"Clone or use a repository. `…` expands its content in the specified checkout.\",\n \"as\": \"Optional. The path of the selected checkout.\",\n \"context\": \"The Markdown expanded in that checkout.\"\n },\n {\n \"kind\": \"component\",\n \"name\": \"SafeParse\",\n \"origin\": {\n \"kind\": \"registered\",\n \"origin\": \"@executablemd/core\",\n \"reserved\": false\n },\n \"sourceKind\": \"registered\",\n \"inspectability\": \"complete\",\n \"forms\": [\n \"self-closing\",\n \"paired\"\n ],\n \"props\": {\n \"type\": \"object\",\n \"properties\": {\n \"schema\": {}\n },\n \"required\": [\n \"schema\"\n ],\n \"additionalProperties\": false\n },\n \"captures\": [],\n \"returnMode\": \"value\",\n \"returns\": {\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"oneOf\": [\n {\n \"type\": \"object\",\n \"properties\": {\n \"ok\": {\n \"const\": true\n },\n \"value\": {}\n },\n \"required\": [\n \"ok\",\n \"value\"\n ],\n \"additionalProperties\": false\n },\n {\n \"type\": \"object\",\n \"properties\": {\n \"ok\": {\n \"const\": false\n },\n \"input\": {\n \"type\": \"string\"\n },\n \"errors\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"instancePath\": {\n \"type\": \"string\"\n },\n \"schemaPath\": {\n \"type\": \"string\"\n },\n \"keyword\": {\n \"type\": \"string\"\n },\n \"params\": {},\n \"message\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"instancePath\",\n \"schemaPath\",\n \"keyword\",\n \"params\",\n \"message\"\n ],\n \"additionalProperties\": false\n }\n }\n },\n \"required\": [\n \"ok\",\n \"input\",\n \"errors\"\n ],\n \"additionalProperties\": false\n }\n ]\n },\n \"description\": \"Parse a value using a JSON schema. `…` parses its content. Binds a result object instead of erroring.\",\n \"as\": \"Required. The result: either the validated value or the issues that rejected it.\",\n \"context\": \"The JSON text to parse.\"\n },\n {\n \"kind\": \"component\",\n \"name\": \"Session\",\n \"origin\": {\n \"kind\": \"registered\",\n \"origin\": \"@executablemd/core\",\n \"reserved\": false\n },\n \"sourceKind\": \"registered\",\n \"inspectability\": \"complete\",\n \"forms\": [\n \"self-closing\",\n \"paired\"\n ],\n \"props\": {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\"\n },\n \"model\": {\n \"type\": \"string\"\n },\n \"effort\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n },\n \"captures\": [],\n \"returnMode\": \"text\",\n \"returns\": {\n \"type\": \"string\"\n },\n \"description\": \"Configure one Agent conversation for its content. `…` uses that exact session and configuration for prompts and native launches from nested components. A self-closing Session places or validates the conversation without sending a prompt.\",\n \"context\": \"Markdown whose prompts and launches run in this session.\"\n },\n {\n \"kind\": \"component\",\n \"name\": \"Session.Launch\",\n \"origin\": {\n \"kind\": \"registered\",\n \"origin\": \"@executablemd/core\",\n \"reserved\": false\n },\n \"sourceKind\": \"registered\",\n \"inspectability\": \"complete\",\n \"forms\": [\n \"self-closing\",\n \"paired\"\n ],\n \"props\": {\n \"type\": \"object\",\n \"properties\": {\n \"agent\": {\n \"type\": \"string\"\n },\n \"session\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n },\n \"captures\": [],\n \"returnMode\": \"text\",\n \"returns\": {\n \"type\": \"string\"\n },\n \"description\": \"Launch a coding agent with prepared context. `…` makes its content the agent's starting context, hands the agent's own interface the terminal, and continues when you exit it.\",\n \"context\": \"The instructions the native session starts from.\"\n },\n {\n \"kind\": \"component\",\n \"name\": \"Slice\",\n \"origin\": {\n \"kind\": \"registered\",\n \"origin\": \"@executablemd/core\",\n \"reserved\": false\n },\n \"sourceKind\": \"registered\",\n \"inspectability\": \"complete\",\n \"forms\": [\n \"self-closing\",\n \"paired\"\n ],\n \"props\": {\n \"type\": \"object\",\n \"properties\": {\n \"offset\": {\n \"type\": \"integer\",\n \"default\": 0\n },\n \"length\": {\n \"type\": \"integer\",\n \"minimum\": 1,\n \"default\": 4096\n }\n },\n \"additionalProperties\": false\n },\n \"captures\": [],\n \"returnMode\": \"text\",\n \"returns\": {\n \"type\": \"string\"\n },\n \"description\": \"Show a window of rendered text. `…` counts Unicode code points and labels partial excerpts.\",\n \"as\": \"Optional. Captures the resulting text, including any range note, instead of emitting it.\",\n \"context\": \"The content whose completed rendering the window is taken from.\"\n },\n {\n \"kind\": \"component\",\n \"name\": \"Syntax\",\n \"origin\": {\n \"kind\": \"protected\",\n \"origin\": \"@executablemd/core\"\n },\n \"sourceKind\": \"protected\",\n \"inspectability\": \"complete\",\n \"forms\": [\n \"self-closing\"\n ],\n \"props\": {\n \"type\": \"object\",\n \"properties\": {\n \"names\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n },\n \"minItems\": 1,\n \"uniqueItems\": true,\n \"description\": \"Optional. Render complete references for these structural or component names instead of the list of available symbols. Entries render once each, in symbol order.\"\n }\n },\n \"additionalProperties\": false\n },\n \"captures\": [],\n \"returnMode\": \"text\",\n \"returns\": {\n \"type\": \"string\"\n },\n \"description\": \"Inspect available components and control-flow constructs. `` lists the symbols available here; `` renders selected documentation.\",\n \"as\": \"Optional. Captures the rendered text instead of emitting it.\"\n },\n {\n \"kind\": \"component\",\n \"name\": \"TempDir\",\n \"origin\": {\n \"kind\": \"registered\",\n \"origin\": \"@executablemd/core\",\n \"reserved\": false\n },\n \"sourceKind\": \"registered\",\n \"inspectability\": \"complete\",\n \"forms\": [\n \"self-closing\",\n \"paired\"\n ],\n \"props\": {\n \"type\": \"object\",\n \"properties\": {},\n \"additionalProperties\": false\n },\n \"captures\": [],\n \"returnMode\": \"text\",\n \"returns\": {\n \"type\": \"string\"\n },\n \"description\": \"Run work in a temporary working directory. `…` expands its content with the temporary directory as the working directory, so `` and commands inside write there rather than in the current one. `` renders the path instead.\",\n \"as\": \"Optional. Captures the rendered directory path instead of emitting it.\",\n \"context\": \"Markdown expanded with the temporary directory as its working directory.\"\n },\n {\n \"kind\": \"component\",\n \"name\": \"Test\",\n \"origin\": {\n \"kind\": \"registered\",\n \"origin\": \"@executablemd/core\",\n \"reserved\": false\n },\n \"sourceKind\": \"registered\",\n \"inspectability\": \"complete\",\n \"forms\": [\n \"self-closing\",\n \"paired\"\n ],\n \"props\": {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\"\n },\n \"timeout\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n },\n \"captures\": [],\n \"returnMode\": \"text\",\n \"returns\": {\n \"type\": \"string\"\n },\n \"description\": \"Define a test. `…` runs under `xmd test`, or inside a `` region; elsewhere it is skipped. A failing command or assertion inside fails the test rather than the document.\",\n \"context\": \"The body of the test: its assertions and the work they judge.\"\n },\n {\n \"kind\": \"component\",\n \"name\": \"Testing\",\n \"origin\": {\n \"kind\": \"registered\",\n \"origin\": \"@executablemd/testing\",\n \"reserved\": false\n },\n \"sourceKind\": \"registered\",\n \"inspectability\": \"complete\",\n \"forms\": [\n \"self-closing\",\n \"paired\"\n ],\n \"props\": {\n \"type\": \"object\",\n \"properties\": {},\n \"additionalProperties\": false\n },\n \"captures\": [],\n \"returnMode\": \"text\",\n \"returns\": {\n \"type\": \"string\"\n },\n \"description\": \"Turn on testing for its content. `…` runs the `` elements inside and reports them; a failing test fails the document, and so does finding no tests at all.\",\n \"context\": \"The Markdown expanded in testing mode.\"\n },\n {\n \"kind\": \"component\",\n \"name\": \"Verbose\",\n \"origin\": {\n \"kind\": \"registered\",\n \"origin\": \"@executablemd/cli\",\n \"reserved\": false\n },\n \"sourceKind\": \"registered\",\n \"inspectability\": \"complete\",\n \"forms\": [\n \"self-closing\",\n \"paired\"\n ],\n \"props\": {\n \"type\": \"object\",\n \"properties\": {},\n \"additionalProperties\": false\n },\n \"captures\": [],\n \"returnMode\": \"text\",\n \"returns\": {\n \"type\": \"string\"\n },\n \"description\": \"Expand content when run verbosity is enabled. `--verbose` enables it for the run; a component may override verbosity for its content.\",\n \"as\": \"Optional. Captures the rendered verbose text, or an empty string when verbosity is off.\"\n },\n {\n \"kind\": \"component\",\n \"name\": \"WebForm\",\n \"origin\": {\n \"kind\": \"registered\",\n \"origin\": \"@executablemd/web\",\n \"reserved\": false\n },\n \"sourceKind\": \"registered\",\n \"inspectability\": \"complete\",\n \"forms\": [\n \"self-closing\",\n \"paired\"\n ],\n \"props\": {\n \"type\": \"object\",\n \"properties\": {\n \"schema\": {},\n \"uiSchema\": {}\n },\n \"required\": [\n \"schema\"\n ],\n \"additionalProperties\": false\n },\n \"captures\": [],\n \"returnMode\": \"value\",\n \"returns\": {},\n \"description\": \"Ask a person a question in a browser form. `…` builds the form from the schema and shows its content above it. `uiSchema` sets presentation options. `` asks the same question without choosing the browser.\",\n \"as\": \"Required. The validated response.\",\n \"context\": \"The Markdown shown above the form.\"\n },\n {\n \"kind\": \"component\",\n \"name\": \"WorkflowRun\",\n \"origin\": {\n \"kind\": \"registered\",\n \"origin\": \"@executablemd/testing\",\n \"reserved\": false\n },\n \"sourceKind\": \"registered\",\n \"inspectability\": \"complete\",\n \"forms\": [\n \"self-closing\",\n \"paired\"\n ],\n \"props\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n },\n \"captures\": [],\n \"returnMode\": \"text\",\n \"returns\": {\n \"type\": \"string\"\n },\n \"description\": \"Scope a workflow-hosted execution. `…` holds `` children, and refuses unless the host supplies a workflow profile.\",\n \"context\": \"The workflow-hosted executions this scope owns.\"\n },\n {\n \"kind\": \"component\",\n \"name\": \"Worktree\",\n \"origin\": {\n \"kind\": \"registered\",\n \"origin\": \"@executablemd/workflow/composition\",\n \"reserved\": false\n },\n \"sourceKind\": \"registered\",\n \"inspectability\": \"complete\",\n \"forms\": [\n \"self-closing\",\n \"paired\"\n ],\n \"props\": {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"branch\": {\n \"type\": \"string\",\n \"minLength\": 1\n },\n \"base\": {\n \"type\": \"string\",\n \"minLength\": 1\n }\n },\n \"required\": [\n \"name\",\n \"branch\"\n ],\n \"additionalProperties\": false\n },\n \"captures\": [],\n \"returnMode\": \"text\",\n \"returns\": {\n \"type\": \"string\"\n },\n \"description\": \"Create or use a worktree. `…` expands its content in the worktree.\",\n \"as\": \"Optional. The path of the linked checkout.\",\n \"context\": \"The Markdown expanded in that checkout.\"\n },\n {\n \"kind\": \"component\",\n \"name\": \"Yaml\",\n \"origin\": {\n \"kind\": \"registered\",\n \"origin\": \"@executablemd/core\",\n \"reserved\": false\n },\n \"sourceKind\": \"registered\",\n \"inspectability\": \"complete\",\n \"forms\": [\n \"self-closing\"\n ],\n \"props\": {\n \"type\": \"object\",\n \"properties\": {},\n \"additionalProperties\": false\n },\n \"captures\": [\n \"value\"\n ],\n \"returnMode\": \"text\",\n \"returns\": {\n \"type\": \"string\"\n },\n \"description\": \"Render a value as YAML text. `` writes the YAML where you put it.\",\n \"as\": \"Optional. Captures the YAML text instead of emitting it.\"\n }\n ]\n },\n {\n \"kind\": \"user-provided\",\n \"entries\": []\n }\n ]\n}\n", + "cli-fragment-base.txt": "## Built-in structural syntax\n\nNo structural constructs are reserved.\n\n## Built-in components\n\nNo components are registered in this profile.\n\n## User-provided components\n\n### ``\n\nRender a value as JSON text. `` writes the JSON where you put it.\n\n**Forms:** ``\n\n#### Props\n\nThis component declares no individual props.\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {},\n \"additionalProperties\": false\n}\n```\n\n**Captures:** `value` — evaluated by the component itself, so these props are deliberately absent from the schema above.\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/core` (registered default)\n\n### ``\n\nRead the working directory. `` renders its path without adding a newline.\n\n**Forms:** ``\n\n#### Props\n\nThis component declares no individual props.\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {},\n \"additionalProperties\": false\n}\n```\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/core` (registered default)\n\n### ``\n\nRead or write a file. `` reads the content; `…` writes the content. The path is relative to the working directory.\n\n**Forms:** ``\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `path` | `string` | yes | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"path\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"path\"\n ],\n \"additionalProperties\": false\n}\n```\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/core` (protected component)\n\n### ``\n\nList files by pattern. `` matches paths relative to the working directory. The list is sorted. Directories and symbolic links are never results.\n\n**Forms:** ``\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `include` | `array` | yes | |\n| `exclude` | `array` | no | |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"include\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n },\n \"minItems\": 1\n },\n \"exclude\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n },\n \"default\": []\n }\n },\n \"required\": [\n \"include\"\n ],\n \"additionalProperties\": false\n}\n```\n\n**Returns:** a value — it renders nothing, and `as` binds what it returns.\n\n```json\n{\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n}\n```\n\n**Origin:** `@executablemd/core` (registered default)\n\n### ``\n\nInspect available components and control-flow constructs. `` lists the symbols available here; `` renders selected documentation.\n\n**Forms:** ``\n\n#### Props\n\n| Prop | Type | Required | Description |\n| --- | --- | --- | --- |\n| `names` | `array` | no | Optional. Render complete references for these structural or component names instead of the list of available symbols. Entries render once each, in symbol order. |\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"names\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n },\n \"minItems\": 1,\n \"uniqueItems\": true,\n \"description\": \"Optional. Render complete references for these structural or component names instead of the list of available symbols. Entries render once each, in symbol order.\"\n }\n },\n \"additionalProperties\": false\n}\n```\n\n**Returns:** text — the markdown this component renders.\n\n```json\n{\n \"type\": \"string\"\n}\n```\n\n**Origin:** `@executablemd/core` (protected component)\n" +} diff --git a/packages/core/tests/generated-xmd-root.test.ts b/packages/core/tests/generated-xmd-root.test.ts index a4f87c89a..d39c15f21 100644 --- a/packages/core/tests/generated-xmd-root.test.ts +++ b/packages/core/tests/generated-xmd-root.test.ts @@ -40,6 +40,8 @@ import type { DurableEvent } from "@executablemd/durable-streams"; import { Component, content } from "../src/component-api.ts"; import { Elicitation } from "../src/elicitation-api.ts"; import type { ElicitationRequest } from "../src/elicitation-api.ts"; +import baseline1178 from "./fixtures/syntax-generated-base.json" with { type: "json" }; +import { expectAvailability, syntaxInstallation } from "./support/syntax-availability.ts"; import { pinnedJson } from "../src/generated-xmd.ts"; import { useSelection } from "./support/generated-selection.ts"; import { answerProvider } from "./support/answer-provider.ts"; @@ -1762,3 +1764,58 @@ describe("993 generated nested roots", () => { } }); }); + +describe("1178 generated root references and scope", () => { + beforeAll(() => useTempFileCompiler()); + it("keeps root engine availability local across sibling roots and restores enclosing installed syntax", function* () { + const calls: string[] = []; + const names = ["If", "Output", "Content", "Return", "Banner", "BannerLine"]; + const named = ``; + const candidate = request(`${named}1178-ROOT`); + const run = yield* withHeldHost( + { + installations: [candidate.installation, syntaxInstallation(calls)], + root: { path: HELD_ROOT_PATH, source: `${named}` }, + }, + function* (held) { + const first = yield* held.execution.evaluateGeneratedXmdRoot(candidate.root); + if (!first.ok) { + throw first.error; + } + expect(first.value.output).toContain("1178-ROOT"); + for (const name of ["If", "Output"]) { + expectAvailability(first.value.output, name, true); + } + for (const name of ["Content", "Return", "Banner", "BannerLine"]) { + expectAvailability(first.value.output, name, false); + } + const second = yield* held.execution.evaluateGeneratedXmdRoot({ + id: "turn-2", + source: `{before}1178-CUT{reference}1178-CUT{after}`, + }); + if (!second.ok) { + throw second.error; + } + const [before, reference, after] = second.value.output.split("1178-CUT"); + expect(before).toBe(baseline1178["root-base.txt"]); + expect(after).toBe(baseline1178["root-base.txt"]); + expectAvailability(reference, "If", true); + const third = yield* held.execution.evaluateGeneratedXmdRoot({ + id: "turn-3", + source: "", + }); + if (!third.ok) { + throw third.error; + } + expect(third.value.output).toBe(baseline1178["root-base.txt"]); + }, + ); + if (!run.completion.ok) { + throw run.completion.error; + } + for (const name of names) { + expectAvailability(String(run.completion.value), name, true); + } + expect(calls).toEqual([]); + }); +}); diff --git a/packages/core/tests/support/syntax-availability.ts b/packages/core/tests/support/syntax-availability.ts new file mode 100644 index 000000000..2c3857f8c --- /dev/null +++ b/packages/core/tests/support/syntax-availability.ts @@ -0,0 +1,43 @@ +import { expect } from "@executablemd/test-support/expect"; +import type { Operation } from "effection"; +import { Structural } from "../../host.ts"; +import type { ExecutionInstallation } from "../../host.ts"; + +/** Assert the label belongs to this reference, rather than another section. */ +export function expectAvailability(text: string, name: string, available: boolean): void { + const sections = text.split(`### \`<${name}>\``); + expect(sections).toHaveLength(2); + expect(sections[1].split("\n### ")[0]).toContain( + `**Available in this evaluation:** ${available ? "yes" : "no"}`, + ); +} + +/** Installed authoring syntax that generated expansion must never enter. */ +export function syntaxInstallation(calls: string[]): ExecutionInstallation { + const parent = Structural({ + name: "Banner", + origin: "test://1178", + forms: ["paired"], + props: { type: "object", properties: {}, additionalProperties: false }, + syntax: ["…"], + description: "Frame the lines written inside it.", + context: "The lines this banner frames.", + parent: null, + }); + return { + declarations: [ + parent, + Structural({ + ...parent, + name: "BannerLine", + parent: "Banner", + syntax: ["…"], + }), + ], + // deno-lint-ignore require-yield + *expand(): Operation { + calls.push("handler invoked"); + throw new Error("1178: inspection entered a structural handler"); + }, + }; +} diff --git a/packages/core/tests/syntax-api.test.ts b/packages/core/tests/syntax-api.test.ts index aa41a91f2..4693e5958 100644 --- a/packages/core/tests/syntax-api.test.ts +++ b/packages/core/tests/syntax-api.test.ts @@ -8,6 +8,10 @@ import { mkdtemp } from "node:fs/promises"; import { tmpdir } from "node:os"; import { join } from "node:path"; import { InMemoryStream } from "@executablemd/durable-streams"; +import baseline1178 from "./fixtures/syntax-generated-base.json" with { type: "json" }; +import { expectAvailability } from "./support/syntax-availability.ts"; +import { useNarrowedSyntax } from "../src/syntax-api.ts"; +import { engineSyntaxEntry } from "../src/structural.ts"; import { Syntax } from "../api.ts"; import type { SyntaxApi, SyntaxSymbols } from "../api.ts"; import { @@ -71,6 +75,69 @@ function* run(text: string, stream = new InMemoryStream()): Operation { ); } +describe("1178 reference specialization", () => { + it("snapshots engine entries, distinguishes omission from empty and retains middleware", function* () { + const authoring = yield* inspectSyntax({ includes: [] }); + expect(renderSyntaxMarkdown(authoring)).toBe(baseline1178["canonical-base.txt"]); + expect(JSON.stringify(authoring)).toBe(baseline1178["catalog-base.json"]); + const entry = { + ...engineSyntaxEntry("If"), + origin: { kind: "structural" as const, construct: "If" }, + syntax: ["…"], + }; + const entries = [entry]; + const root = syntaxReference(authoring); + const specialized = root.available(symbolsOf(), entries); + entry.syntax[0] = "MUTATED"; + entry.origin.construct = "MUTATED"; + entries.splice(0); + let reads = 0; + yield* scoped(function* () { + yield* useNarrowedSyntax(specialized); + yield* Syntax.around({ + *symbols(_args, next) { + reads++; + const effective = yield* next(); + expect(effective.categories[0].entries[0]).toEqual(engineSyntaxEntry("If")); + return effective; + }, + }); + const text = yield* root.documentation(["If"]); + expectAvailability(text, "If", true); + expect(text).not.toContain("MUTATED"); + }); + expect(reads).toBe(1); + yield* scoped(function* () { + yield* useNarrowedSyntax(specialized); + yield* Syntax.around({ + *symbols(_args, next) { + const effective = yield* next(); + return { + ...effective, + categories: [ + { kind: "structural", entries: [] }, + effective.categories[1], + effective.categories[2], + ], + } satisfies SyntaxSymbols; + }, + }); + expectAvailability(yield* root.documentation(["If"]), "If", false); + }); + expect((yield* specialized.symbols()).categories[0].entries).toEqual([]); + for (const [reference, available] of [ + [root.available(authoring), true], + [root.available(authoring, []), false], + [specialized.available(symbolsOf(), []), false], + ] as const) { + yield* scoped(function* () { + yield* Syntax.around({ symbols: () => reference.symbols() }); + expectAvailability(yield* root.documentation(["If"]), "If", available); + }); + } + }); +}); + describe("Tier SA — contextual Syntax", () => { it("SA: structural availability compares complete installed identity and keeps enclosing references", function* () { const declaration = Structural({ diff --git a/scripts/tests/plan-component-compiled.test.ts b/scripts/tests/plan-component-compiled.test.ts index 30146480a..0bb071cc4 100644 --- a/scripts/tests/plan-component-compiled.test.ts +++ b/scripts/tests/plan-component-compiled.test.ts @@ -17,6 +17,8 @@ * missing binary is reported as the setup it is rather than as a failed assertion. */ +import baseline1178 from "../../packages/core/tests/fixtures/syntax-generated-base.json" with { type: "json" }; +import { expectAvailability } from "../../packages/core/tests/support/syntax-availability.ts"; import { runCli } from "@executablemd/test-support/launch"; import { describe, it } from "@executablemd/test-support/bdd"; import { expect } from "@executablemd/test-support/expect"; @@ -511,3 +513,58 @@ describe( }); }, ); + +describe( + "1178 narrowed structural availability", + { sanitizeOps: false, sanitizeResources: false }, + () => { + it("matches source and rebuilt binary through real Evaluate outside the checkout", function* () { + const elsewhere = yield* until(mkdtemp(path.join(tmpdir(), "xmd-1178-availability-"))); + yield* ensure(() => rm(elsewhere, { recursive: true, force: true })); + const plugin = path.join( + ROOT, + "packages/cli/tests/fixtures/plugins/structural-reference.mjs", + ); + const names = ["If", "Syntax", "Content", "Return", "Output", "Banner", "BannerLine"]; + const fragment = `1178-CUT1178-DISTRIBUTED-IF`; + yield* writeTextFile( + path.join(elsewhere, "availability.md"), + ``, + ); + const args = ["run", `--plugin=${plugin}`, "--include", elsewhere, "availability.md"]; + const source = yield* runCli(args, { cwd: elsewhere }).expect(); + const compiled = yield* timebox(TIMEOUT, function* () { + return yield* exec(BINARY, { arguments: args, cwd: elsewhere }).join(); + }); + if (compiled.timeout) { + throw new Error("1178 compiled availability timed out"); + } + expect(compiled.value.code).toBe(0); + expect(compiled.value.stdout).toBe(source.stdout); + expect(compiled.value.stdout + compiled.value.stderr).not.toContain("handler invoked"); + const [captured, marker] = compiled.value.stdout.split("1178-CUT"); + const { before, reference, after } = JSON.parse(captured); + expect(before).toBe(baseline1178["cli-fragment-base.txt"]); + expect(after).toBe(baseline1178["cli-fragment-base.txt"]); + expect(marker).toContain("1178-DISTRIBUTED-IF"); + for (const name of ["If", "Syntax"]) { + expectAvailability(reference, name, true); + } + for (const name of ["Content", "Return", "Output", "Banner", "BannerLine"]) { + expectAvailability(reference, name, false); + } + // Empty includes keep these catalog fixtures independent of temporary paths. + const empty = path.join(elsewhere, "empty"); + yield* until(mkdir(empty)); + for (const [extra, expected] of [ + [[], baseline1178["cli-bare-base.txt"]], + [["--json"], baseline1178["cli-json-base.txt"]], + ] as const) { + const lookup = yield* runCli(["syntax", "--include", empty, ...extra], { + cwd: elsewhere, + }).expect(); + expect(lookup.stdout).toBe(expected); + } + }); + }, +); diff --git a/specs/executable-mdx-spec.md b/specs/executable-mdx-spec.md index 03149535e..3bffac0c5 100644 --- a/specs/executable-mdx-spec.md +++ b/specs/executable-mdx-spec.md @@ -3001,7 +3001,13 @@ schema or invented binding contract. Mixed structural/component requests render once each in symbol order and refuse whole if any name is unknown. Inspection invokes no structural expansion handler. Availability compares the full engine or installed origin identity against effective symbols and grants no execution -authority. Bare ``, bare `xmd syntax` and version-1 JSON retain their +authority. In generated evaluation, a named read includes the engine language +supported at a valid placement: fragments exclude Content, Return and Output; +roots additionally support Output. Installed constructs are unavailable because +generated expansion declares none. Parent and loop constraints still apply. +Bare generated reads retain their component-only presentation and empty +structural category; named language availability does not change admission. +Bare ``, bare `xmd syntax` and version-1 JSON retain their existing presentation. The documentation is read from the owning package through the direct filesystem, From cbe502182f696494a776cb6a225558f8109c4cde Mon Sep 17 00:00:00 2001 From: Taras Mankovski Date: Tue, 10 Nov 2026 12:13:15 -0500 Subject: [PATCH 4/4] Specify generated Syntax availability and REPL index purposes Address the maintainer review on #1229. Put generated placement in the composition contract. Separate bare presentation from named availability, including symbols middleware and fragment and root conformance. Specify index purpose derivation, fallback and bound, and link the shared named renderer. Evidence: syntax API, Syntax component, Evaluate, generated root, Sidekick controls and syntax CLI suites passed (50 tests, 320 steps). --- specs/executable-mdx-spec.md | 82 ++++++++++++++++++------------------ specs/repl-spec.md | 20 ++++++--- 2 files changed, 55 insertions(+), 47 deletions(-) diff --git a/specs/executable-mdx-spec.md b/specs/executable-mdx-spec.md index 3bffac0c5..5f2b5a616 100644 --- a/specs/executable-mdx-spec.md +++ b/specs/executable-mdx-spec.md @@ -2999,16 +2999,11 @@ parent relationship and body context. Their declaration metadata is their usage reference; they receive no component package-documentation fallback, return schema or invented binding contract. Mixed structural/component requests render once each in symbol order and refuse whole if any name is unknown. Inspection -invokes no structural expansion handler. Availability compares the full engine -or installed origin identity against effective symbols and grants no execution -authority. In generated evaluation, a named read includes the engine language -supported at a valid placement: fragments exclude Content, Return and Output; -roots additionally support Output. Installed constructs are unavailable because -generated expansion declares none. Parent and loop constraints still apply. -Bare generated reads retain their component-only presentation and empty -structural category; named language availability does not change admission. -Bare ``, bare `xmd syntax` and version-1 JSON retain their -existing presentation. +invokes no structural expansion handler. Named lookup compares the full engine +or installed origin identity against its effective availability symbols. In +generated evaluation the default availability reflects +[the generated composition rules](#533-ordinary-generated-composition). +Describing a construct grants no execution authority. The documentation is read from the owning package through the direct filesystem, not through `API.Fs` or the document-facing `Files` provider. Both of those are @@ -3085,19 +3080,20 @@ A host-maintained list of every package's documentation, kept beside a host-maintained list of every package's registrations, is two lists that drift; this is one. -**Reference and availability are separate.** The reference carries two inputs. -Default bare `` reports the effective contextual symbols at this -site. The named form selects from the **enclosing authoring symbols** and -states, per entry, -`**Available in this evaluation:** yes` or `no`. Uncustomized at a root the two -are one set of symbols and everything selected is available; a trusted -evaluation boundary that narrows execution keeps the enclosing reference, so a -nested author can be told how a component works where they may not run one — -and is told which it is. Descriptive middleware that filters the effective -symbols separates the two at a root as well, and the per-entry label is what -says so. -Neither input carries definitions, import witnesses, invocation capabilities, -providers, registrations or any other execution capability. +**Reference and availability are separate.** The named form selects from the +**enclosing authoring symbols**. It compares each selection with the effective +symbols for that lookup and reports `**Available in this evaluation:** yes` or +`no`. In an ordinary root with no customization these inputs are the same. +A narrowing boundary retains the enclosing reference so a nested author can +read about forms that are unavailable there. + +Default bare `` renders the effective symbols for bare presentation. +A generated boundary supplies its admitted components, with empty structural +and built-in categories. For named availability, its default symbols also +include the engine identities supported by +[generated composition](#533-ordinary-generated-composition). The difference is +local to the named read. Symbol data carries no definitions, registrations or +invocation capabilities. Availability compares each entry's **identity** rather than its spelling: one name may hold a different component on each side, and an author shown one of @@ -3164,15 +3160,16 @@ snapshots the documentation contributions already in its calling scope and installs its lazy symbols and documentation providers at minimum priority, without reading the source. -Default text renders the effective contextual symbols, and text middleware may -transform or replace that answer. Default named lookup retains its enclosing -catalog for metadata and long-form text and reads effective symbols once for -availability, so filtering symbols affects bare text and named availability -while an omitted enclosing component remains documentable; text-only -customization changes neither symbols nor named lookup, and a synthetic answer -that does not delegate skips the default work entirely. Generated producer and -body scopes narrow symbols only, retaining the enclosing named-documentation -owner, and their descriptive bindings end with those scopes. Standalone Plan +Default text renders the effective bare symbols. Default named lookup retains +its enclosing catalog for metadata and long-form text and reads contextual +symbols once for availability. Symbols middleware can filter or replace the +symbols returned for either read, including the generated engine entries +supplied for a named read. An entry filtered from availability remains +documentable from the enclosing catalog. Text middleware can transform or +replace bare text without changing symbols or named lookup. A synthetic answer +that does not delegate skips the corresponding default work. Generated producer +and body scopes keep the enclosing named-documentation owner and release their +descriptive bindings at scope exit. Standalone Plan and CLI inspection bind the target run's declarative profile through `useSyntax`; embedded Plan inherits its enclosing profile. CLI inspection starts no execution initialization or operational provider merely to print. @@ -4884,14 +4881,16 @@ binding (§4.5) — a consequence of which environment the write landed in, not channel of the fragment's own. A generated **root** is the separate case: it begins with an environment of its own, so its bindings stay in it. -**Every built-in structural construct is available, with its ordinary -semantics.** `Content`, `Output`, `Return`, `Let`, `Each`, `If`, `Else`, -`Switch`, `Case`, `Loop`, `Break`, `PrintErrors`, `Answers`, `Answer`, `Try`, `Catch` and `Finally` are -engine-owned language rather than component permission. A generated fragment -composes admitted reads with branching, binding and bounded iteration, and the -source rules deciding each construct are the same ones ordinary validation and -expansion read — one construct means one thing whether a person or an Agent -wrote it. +**Generated placement.** Engine constructs use their ordinary source rules, +including parent, loop and body constraints. Fragments support constructs such +as `If` and `Loop` where their placement is valid. Fragments have no independent +`Output` context. A generated root also supports `Output` under the +[ordinary declaration and selection rules](#generated-roots-and-preview). +Neither has the caller context for `Content` or the value-body context for +`Return`. Generated evaluation declares no installed structural constructs or +regions. These rules supply the default engine identities for +[named Syntax availability](#531-syntax--the-protected-symbols-component). +Every component reached through a construct still requires its own admission. Preflight dispatches a reserved structural name to those rules **before** it consults the admitted table, so a construct is never reported as a component the @@ -13645,7 +13644,8 @@ component that observes one at an authored site. | SYN11–SYN15 | The import chain | Middleware that answers, substitutes, mutates, redirects, delegates twice or reuses another import's definition cannot run a replacement; ordinary delegation reaches canonical ``; a deliberate middleware refusal stays a refusal; document-authored context and a look-alike reference change nothing | | SYN16–SYN18 | The site described | An ordinary run reports its own includes and registry; a workflow root reports its bundle without importing or running a member; a declared Markdown component's body reports the site it inherited | | SYN20–SYN22 | The record kept | Continuation restores the retained symbols after the environment moves and rediscovers nothing; missing, additional and wrong-typed payloads refuse before output or binding; a cancelled read completes teardown and commits nothing | -| SYN23, SYN25b | Never permission | Symbols naming a component neither register, resolve nor authorize it; a fixed narrower reference answers with exactly the symbols it was handed and adds nothing — the seam `` installs through | +| SYN23, SYN25b | Never permission | Symbols naming a component neither register, resolve nor authorize it. A fixed narrower reference without a generated availability input returns exactly its supplied symbols | +| SYN47 | Generated presentation and availability | Bare reads keep the admitted component listing and empty structural and built-in categories before and after a named read. A fragment reports named `If` and `Loop` available and `Output` unavailable. A root reports named `If` and `Output` available. Both report `Content`, `Return`, and enclosing installed constructs and their regions unavailable by default | | SYN24 | One description | Inspection and validation describe the component identically, from one declaration | | SYN26 | Another loaded copy | A protected implementation built by a second loaded copy answers for nothing in the active execution | | SYN27 | Protected provenance | The symbols report the component under the `protected` origin kind in both the structured entry and the rendered Markdown, and never as a reserved registration; `inspectComponent` agrees | diff --git a/specs/repl-spec.md b/specs/repl-spec.md index cbc25bcd9..614d5b3bd 100644 --- a/specs/repl-spec.md +++ b/specs/repl-spec.md @@ -3210,18 +3210,26 @@ layering those live values over retained head values. A reply's own vocabulary and an entry's are described separately, because they differ: a construct that is ordinary in an entry can be unavailable in a reply. What a reply may write is the compact surface derived from what is admitted; what -an entry may write is a read, using core's structured symbols and selection over the -ordinary entry's current registry, finalized includes and host declarations. +an entry may write is a read over the ordinary entry's current registry, +finalized includes and host declarations. The index uses core's structured +symbols. Named lookup uses core's +[full reference selection and renderer](executable-mdx-spec.md#531-syntax--the-protected-symbols-component). It carries the existing assertion defaults, including Assert, AssertEquals and AssertThrows, without entering the broader CLI run profile's testing, Verbose or web bootstrap. Each ask reads current session component files; Plugin selection is captured once per command, and another configured command describes its own selection. Earlier saved discovery stays historical feedback. -Bare `` returns a compact index: exact names in their existing -categories, one bounded short purpose per name and a copyable named lookup. -It projects the current structured symbols without prop tables, JSON or return -schemas, detailed usage or origin boilerplate. `` +Bare `` returns a compact index with exact names in symbol order +under their existing categories and a copyable named lookup. Each purpose uses +the symbol's trimmed description, collapses whitespace to single spaces and +takes the text through the first period, question mark or exclamation point +followed by a space, or keeps the whole description if none matches. A missing +or blank description points to the named reference. +An origin-only repository TypeScript component instead says its contract is +unavailable without importing it. A purpose longer than 160 UTF-16 code units +keeps the first 159 and an ellipsis. Markdown escaping follows truncation. +The index omits prop tables, schemas, detailed usage and origin boilerplate. `` returns complete selected references, including engine and installed structural forms, props and parent constraints. Canonical bare ``, CLI syntax and version-1 JSON keep their existing formats.