Add xmd syntax for discoverable component documentation #632

Description

@taras

Motivation

Agents and people need an effect-free way to discover the complete syntax
available to an executable.md run. A consumer must not need prior knowledge of
the language's structural constructs in order to ask what it can write.

This is also the prerequisite vocabulary source for xmd prompt (#260): prompt
generation consumes the same structural descriptions that the CLI exposes,
rather than maintaining a second handwritten catalog.

Command

xmd syntaxxmd syntax --jsonxmd syntax --include ./components --include ./more-components
  • xmd syntax writes human-readable Markdown by default.
  • xmd syntax --json writes the same information as deterministic structured
    JSON for external tools and agents.
  • The command accepts the ordered, repeatable --include configuration used by
    xmd run. Explicit includes replace the defaults; without one it uses
    ["components", "."].
  • Discovery describes the run host profile under the contextual cwd.
  • The command performs inspection only. It does not expand a component body,
    execute eval or shell blocks, import a repository TypeScript module, launch an
    agent, mint execution or invocation authority, or create a journal.

Catalog categories

The result always contains these categories in this order:

  1. Built-in structural syntax — the constructs canonical core recognizes
    before component resolution, such as <If>, <Each>, <Output> and
    <Content>.
  2. Built-in components — the selected registered defaults in the run host
    profile, including core, Agent, testing and web components. Components the
    host declares to an execution, such as <Session>, are described from plain
    profile declarations without instantiating their authority-bearing factory.
  3. User-provided components — the selected repository Markdown and
    TypeScript components found through the configured includes.

A name appears only as the implementation execution would select. A repository
component that overrides an ordinary built-in default therefore appears once,
under user-provided components, with the repository origin. Structural syntax
remains structural because a repository or registration cannot claim it.

Component discovery

Core enumerates candidate names from the effective run-profile declarations and
from repository paths that invert the existing dotted-name mapping:

  • Name.md and Name.ts describe Name;
  • Name/index.md and Name/index.ts describe Name;
  • nested paths describe dotted names, so Ns/Name.md and
    Ns/Name/index.md describe Ns.Name.

Only paths that describe a name the component grammar accepts are candidates.
Candidate names are de-duplicated, then each is passed through the same
selectComponent() decision execution uses. The existing include order,
.md/.ts candidate order, reserved/default tiers, and repository override
precedence therefore remain authoritative.

A missing include contributes no names, as it does during execution. An include
root that exists but cannot be inspected fails the request rather than making a
partial catalog look complete. Each configured include root is resolved as the
directory the caller named; a symbolic-link root is refused.

Architecture amendment — selection-relevant symlinks. Traversal never follows
a symbolic link to a directory. It classifies a reported link only when the
link's complete logical path could participate in component selection: the path
is itself one of the candidate file spellings, or every path segment is a valid
component-name segment and could therefore be an ancestor of one. A relevant
link to a file is selected through its ordinary repository path; a relevant link
to a directory, to nothing, or to an unclassifiable target fails the whole
include. The diagnostic names the configured include and logical entry, not its
resolved host target.

A link behind a lower-case, dotted, hidden, or otherwise invalid logical prefix
is ignored. No valid component name can make probeComponentPath() probe
through that prefix, so ignoring the link cannot hide an implementation
execution could select. This replaces blanket refusal of every directory link:
with the default ["components", "."], blanket refusal made bare
xmd syntax fail in ordinary package repositories solely because
node_modules contains directory links.

Entries within each category are ordered by component name in Unicode code-point
order. Props, captures and syntax forms retain their declaration order.

Component documentation

Markdown components may declare these optional string metadata fields directly
in frontmatter:

---description: Creates a temporary directory and expands its body inside it.as: The absolute path of the temporary directory.context: Commands and file operations in the body use the temporary directory.props:
prefix:
type: stringdescription: Prefix for the generated directory name---

The fields mean:

  • description: what the component does.
  • as: what as="name" binds.
  • context: what is applied while expanding the component body.

They remain ordinary Markdown metadata. They are not reserved and have no
execution semantics. Inspection recognizes resolved string values under these
names; another value remains ordinary metadata and contributes no documentation
field.

Registered and execution-declared TypeScript components can declare the
equivalent fields directly with their structural registration metadata. The
existing props and returns schemas remain the machine-readable validated input
and result contracts; JSON Schema description continues to document
individual props.

Documentation is optional for repository-authored components so existing
components remain valid. Every first-party structural construct and component
exposed by the run host profile provides a description, plus as and
context whenever those explanations apply.

Inspection contract

Core provides one effect-free structural result. The CLI Markdown renderer, CLI
JSON renderer and xmd prompt consume this value directly; neither invokes nor
parses another one's output.

The JSON projection has this versioned shape, reusing the existing
ComponentOrigin, PropsSchema, and ReturnsSchema contracts:

interfaceSyntaxCatalog{readonlyversion: 1;readonlycategories: readonly[{readonlykind: "structural";readonlyentries: readonlyStructuralSyntaxEntry[]},{readonlykind: "built-in";readonlyentries: readonlyCompleteComponentSyntaxEntry[]},{readonlykind: "user-provided";readonlyentries: readonly(|CompleteComponentSyntaxEntry|OriginOnlyComponentSyntaxEntry)[];},];}interfaceStructuralSyntaxEntry{readonlykind: "structural";readonlyname: string;readonlyorigin: Extract<ComponentOrigin,{kind: "structural"}>;readonlysyntax: readonlystring[];readonlydescription: string;readonlyas?: string;readonlycontext?: string;}interfaceCompleteComponentSyntaxEntry{readonlykind: "component";readonlyname: string;readonlyorigin: Exclude<ComponentOrigin,{kind: "structural"}>;readonlysourceKind: "registered"|"markdown";readonlyinspectability: "complete";readonlyforms: readonly("self-closing"|"paired")[];readonlyprops: PropsSchema;readonlycaptures: readonlystring[];readonlyreturnMode: "text"|"value";readonlyreturns: ReturnsSchema;readonlydescription?: string;readonlyas?: string;readonlycontext?: string;}interfaceOriginOnlyComponentSyntaxEntry{readonlykind: "component";readonlyname: string;readonlyorigin: Extract<ComponentOrigin,{kind: "repository"}>;readonlysourceKind: "typescript";readonlyinspectability: "origin-only";}

Every structural entry contains its name and structural origin, one or more
exact authored syntax forms, a description, and as or context prose when
those concepts apply.

Every fully inspectable component entry contains:

  • name, category, selected origin and source kind;
  • inspectability: "complete";
  • accepted invocation forms (self-closing, paired, or both), in that
    canonical order;
  • the canonical draft-07 props schema;
  • captured prop names, separately from the schema that deliberately excludes
    them;
  • returnMode: "text" | "value" and the effective returns schema ({ type: "string" } in text mode);
  • optional description, as, and context.

The return mode stays explicit because a text component and a value component
declaring returns: { type: string } have the same schema and different
invocation contracts. Captures stay explicit because they are caller-visible
props that intentionally do not cross the JSON props boundary.

Repository TypeScript files are available but not safely inspectable in full:
their schemas and documentation live on module exports, and loading the module
would execute top-level code. They therefore appear with name, category,
repository origin, source kind and inspectability: "origin-only"; props,
captures, returns, forms and prose fields are absent. A future static manifest
can enrich them without weakening this command's no-import guarantee.

Repository Markdown is parsed without expanding its body. A component whose
prose fields are absent still appears with every structural field inspection can
safely provide.

Markdown output

The default output renders the three categories as separate top-level sections.
It is useful both as reference documentation and as agent prompt material.
Each structural construct shows its authored forms and purpose. Each fully
inspectable component shows invocation forms, purpose, props, captures, as
meaning, body context, return mode and origin when available. An origin-only
TypeScript component is identified as such and never presented as accepting no
props.

For example:

## Built-in components### `<TempDir>`
Creates a temporary directory and expands its body inside it.
#### Props| Prop | Type | Required | Description || --- | --- | --- | --- ||`prefix`| string | no | Prefix for the generated directory name |**`as`:** The absolute path of the temporary directory.
**Body context:** Commands and file operations in the body use the temporary
directory.

Acceptance criteria

  • xmd syntax emits Markdown and xmd syntax --json emits the corresponding
    version-1 structured representation.
  • Both outputs and xmd prompt are produced from the same internal inspection
    result.
  • The result contains built-in structural syntax, selected built-in components,
    and selected user-provided components as separate ordered categories.
  • Candidate enumeration and final selection agree with ordinary execution's
    includes, name mapping and resolution precedence.
  • Traversal never follows a directory link. Candidate-relevant directory and
    dangling links fail the whole request; links behind a logical prefix component
    resolution cannot probe through are ignored.
  • Bare xmd syntax remains usable with its default includes in an ordinary
    package repository whose node_modules contains directory links.
  • Repeated --include values preserve caller order and replace the defaults.
  • Markdown frontmatter description, as, and context string values appear
    in both output forms; non-string values remain ordinary metadata and are not
    documentation.
  • Registered and execution-declared component documentation appears through the
    same fields without minting execution authority.
  • Props and returns retain their canonical draft-07 schemas; captures,
    invocation forms and text/value return mode remain explicit.
  • Undocumented repository Markdown components remain discoverable.
  • Repository TypeScript components appear as origin-only and are never imported.
  • Inspection performs none of the component's effects and creates no journal.
  • Every first-party structural construct and component in the run host profile
    has complete applicable prose documentation.
  • Category and entry ordering is deterministic.
  • JSON and Markdown never describe an opaque TypeScript component as though it
    accepted no props.

Evidence

Use Markdown tests as the primary end-to-end evidence:

  • all three categories render in their fixed order;
  • a Markdown component declares description, as, context, and described
    props;
  • xmd syntax discovers it and renders those declarations;
  • xmd syntax --json reports the equivalent structure;
  • an undocumented Markdown component remains discoverable;
  • a repository TypeScript module that throws at top level is listed origin-only
    and is not imported;
  • a component body containing an observable effect is not expanded during
    discovery;
  • repository Markdown/TypeScript and index paths map to dotted names;
  • a candidate file link is selected; a candidate-relevant directory or dangling
    link fails; a link behind a lower-case or dotted prefix is ignored;
  • bare xmd syntax succeeds in a representative package tree containing
    node_modules directory links;
  • duplicate names and component-directory precedence match execution;
  • repeated --include values replace the defaults in caller order;
  • a repository component overriding a built-in appears once in the
    user-provided category;
  • <Session> is present even though inspection creates no execution claimant;
  • captures and self-closing/paired forms are visible; and
  • Markdown and JSON preserve the same names, categories, origins and structural
    fields.

Add focused core tests for metadata extraction, catalog enumeration, deterministic
ordering, registration and execution-declaration metadata, origin-only
TypeScript inspection, structural descriptions, captures/forms, and the
structured result. Avoid one snapshot of the entire catalog; assert meaningful
entries and category boundaries so routine description edits do not rewrite
unrelated evidence.

Out of scope

  • Implementing xmd prompt itself.
  • Executing components to infer documentation.
  • Importing repository TypeScript components during inspection.
  • A static documentation manifest for repository TypeScript components.
  • Requiring documentation from repository-authored components.
  • A structured ontology for contextual APIs or bindings; context is concise
    prose in this slice.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all \u003cpre\u003e\u003ccode\u003e blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks"); } } catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); } })(); (function(){ try { var __m = "github.com"; var __re = new RegExp('^' + "github\\.com" + '
      Skip to content

      Add xmd syntax for discoverable component documentation #632

      Description

      @taras

      Motivation

      Agents and people need an effect-free way to discover the complete syntax
      available to an executable.md run. A consumer must not need prior knowledge of
      the language's structural constructs in order to ask what it can write.

      This is also the prerequisite vocabulary source for xmd prompt (#260): prompt
      generation consumes the same structural descriptions that the CLI exposes,
      rather than maintaining a second handwritten catalog.

      Command

      xmd syntaxxmd syntax --jsonxmd syntax --include ./components --include ./more-components
      • xmd syntax writes human-readable Markdown by default.
      • xmd syntax --json writes the same information as deterministic structured
        JSON for external tools and agents.
      • The command accepts the ordered, repeatable --include configuration used by
        xmd run. Explicit includes replace the defaults; without one it uses
        ["components", "."].
      • Discovery describes the run host profile under the contextual cwd.
      • The command performs inspection only. It does not expand a component body,
        execute eval or shell blocks, import a repository TypeScript module, launch an
        agent, mint execution or invocation authority, or create a journal.

      Catalog categories

      The result always contains these categories in this order:

      1. Built-in structural syntax — the constructs canonical core recognizes
        before component resolution, such as <If>, <Each>, <Output> and
        <Content>.
      2. Built-in components — the selected registered defaults in the run host
        profile, including core, Agent, testing and web components. Components the
        host declares to an execution, such as <Session>, are described from plain
        profile declarations without instantiating their authority-bearing factory.
      3. User-provided components — the selected repository Markdown and
        TypeScript components found through the configured includes.

      A name appears only as the implementation execution would select. A repository
      component that overrides an ordinary built-in default therefore appears once,
      under user-provided components, with the repository origin. Structural syntax
      remains structural because a repository or registration cannot claim it.

      Component discovery

      Core enumerates candidate names from the effective run-profile declarations and
      from repository paths that invert the existing dotted-name mapping:

      • Name.md and Name.ts describe Name;
      • Name/index.md and Name/index.ts describe Name;
      • nested paths describe dotted names, so Ns/Name.md and
        Ns/Name/index.md describe Ns.Name.

      Only paths that describe a name the component grammar accepts are candidates.
      Candidate names are de-duplicated, then each is passed through the same
      selectComponent() decision execution uses. The existing include order,
      .md/.ts candidate order, reserved/default tiers, and repository override
      precedence therefore remain authoritative.

      A missing include contributes no names, as it does during execution. An include
      root that exists but cannot be inspected fails the request rather than making a
      partial catalog look complete. Each configured include root is resolved as the
      directory the caller named; a symbolic-link root is refused.

      Architecture amendment — selection-relevant symlinks. Traversal never follows
      a symbolic link to a directory. It classifies a reported link only when the
      link's complete logical path could participate in component selection: the path
      is itself one of the candidate file spellings, or every path segment is a valid
      component-name segment and could therefore be an ancestor of one. A relevant
      link to a file is selected through its ordinary repository path; a relevant link
      to a directory, to nothing, or to an unclassifiable target fails the whole
      include. The diagnostic names the configured include and logical entry, not its
      resolved host target.

      A link behind a lower-case, dotted, hidden, or otherwise invalid logical prefix
      is ignored. No valid component name can make probeComponentPath() probe
      through that prefix, so ignoring the link cannot hide an implementation
      execution could select. This replaces blanket refusal of every directory link:
      with the default ["components", "."], blanket refusal made bare
      xmd syntax fail in ordinary package repositories solely because
      node_modules contains directory links.

      Entries within each category are ordered by component name in Unicode code-point
      order. Props, captures and syntax forms retain their declaration order.

      Component documentation

      Markdown components may declare these optional string metadata fields directly
      in frontmatter:

      ---description: Creates a temporary directory and expands its body inside it.as: The absolute path of the temporary directory.context: Commands and file operations in the body use the temporary directory.props:
      prefix:
      type: stringdescription: Prefix for the generated directory name---

      The fields mean:

      • description: what the component does.
      • as: what as="name" binds.
      • context: what is applied while expanding the component body.

      They remain ordinary Markdown metadata. They are not reserved and have no
      execution semantics. Inspection recognizes resolved string values under these
      names; another value remains ordinary metadata and contributes no documentation
      field.

      Registered and execution-declared TypeScript components can declare the
      equivalent fields directly with their structural registration metadata. The
      existing props and returns schemas remain the machine-readable validated input
      and result contracts; JSON Schema description continues to document
      individual props.

      Documentation is optional for repository-authored components so existing
      components remain valid. Every first-party structural construct and component
      exposed by the run host profile provides a description, plus as and
      context whenever those explanations apply.

      Inspection contract

      Core provides one effect-free structural result. The CLI Markdown renderer, CLI
      JSON renderer and xmd prompt consume this value directly; neither invokes nor
      parses another one's output.

      The JSON projection has this versioned shape, reusing the existing
      ComponentOrigin, PropsSchema, and ReturnsSchema contracts:

      interfaceSyntaxCatalog{readonlyversion: 1;readonlycategories: readonly[{readonlykind: "structural";readonlyentries: readonlyStructuralSyntaxEntry[]},{readonlykind: "built-in";readonlyentries: readonlyCompleteComponentSyntaxEntry[]},{readonlykind: "user-provided";readonlyentries: readonly(|CompleteComponentSyntaxEntry|OriginOnlyComponentSyntaxEntry)[];},];}interfaceStructuralSyntaxEntry{readonlykind: "structural";readonlyname: string;readonlyorigin: Extract<ComponentOrigin,{kind: "structural"}>;readonlysyntax: readonlystring[];readonlydescription: string;readonlyas?: string;readonlycontext?: string;}interfaceCompleteComponentSyntaxEntry{readonlykind: "component";readonlyname: string;readonlyorigin: Exclude<ComponentOrigin,{kind: "structural"}>;readonlysourceKind: "registered"|"markdown";readonlyinspectability: "complete";readonlyforms: readonly("self-closing"|"paired")[];readonlyprops: PropsSchema;readonlycaptures: readonlystring[];readonlyreturnMode: "text"|"value";readonlyreturns: ReturnsSchema;readonlydescription?: string;readonlyas?: string;readonlycontext?: string;}interfaceOriginOnlyComponentSyntaxEntry{readonlykind: "component";readonlyname: string;readonlyorigin: Extract<ComponentOrigin,{kind: "repository"}>;readonlysourceKind: "typescript";readonlyinspectability: "origin-only";}

      Every structural entry contains its name and structural origin, one or more
      exact authored syntax forms, a description, and as or context prose when
      those concepts apply.

      Every fully inspectable component entry contains:

      • name, category, selected origin and source kind;
      • inspectability: "complete";
      • accepted invocation forms (self-closing, paired, or both), in that
        canonical order;
      • the canonical draft-07 props schema;
      • captured prop names, separately from the schema that deliberately excludes
        them;
      • returnMode: "text" | "value" and the effective returns schema ({ type: "string" } in text mode);
      • optional description, as, and context.

      The return mode stays explicit because a text component and a value component
      declaring returns: { type: string } have the same schema and different
      invocation contracts. Captures stay explicit because they are caller-visible
      props that intentionally do not cross the JSON props boundary.

      Repository TypeScript files are available but not safely inspectable in full:
      their schemas and documentation live on module exports, and loading the module
      would execute top-level code. They therefore appear with name, category,
      repository origin, source kind and inspectability: "origin-only"; props,
      captures, returns, forms and prose fields are absent. A future static manifest
      can enrich them without weakening this command's no-import guarantee.

      Repository Markdown is parsed without expanding its body. A component whose
      prose fields are absent still appears with every structural field inspection can
      safely provide.

      Markdown output

      The default output renders the three categories as separate top-level sections.
      It is useful both as reference documentation and as agent prompt material.
      Each structural construct shows its authored forms and purpose. Each fully
      inspectable component shows invocation forms, purpose, props, captures, as
      meaning, body context, return mode and origin when available. An origin-only
      TypeScript component is identified as such and never presented as accepting no
      props.

      For example:

      ## Built-in components### `<TempDir>`
      Creates a temporary directory and expands its body inside it.
      #### Props| Prop | Type | Required | Description || --- | --- | --- | --- ||`prefix`| string | no | Prefix for the generated directory name |**`as`:** The absolute path of the temporary directory.
      **Body context:** Commands and file operations in the body use the temporary
      directory.

      Acceptance criteria

      • xmd syntax emits Markdown and xmd syntax --json emits the corresponding
        version-1 structured representation.
      • Both outputs and xmd prompt are produced from the same internal inspection
        result.
      • The result contains built-in structural syntax, selected built-in components,
        and selected user-provided components as separate ordered categories.
      • Candidate enumeration and final selection agree with ordinary execution's
        includes, name mapping and resolution precedence.
      • Traversal never follows a directory link. Candidate-relevant directory and
        dangling links fail the whole request; links behind a logical prefix component
        resolution cannot probe through are ignored.
      • Bare xmd syntax remains usable with its default includes in an ordinary
        package repository whose node_modules contains directory links.
      • Repeated --include values preserve caller order and replace the defaults.
      • Markdown frontmatter description, as, and context string values appear
        in both output forms; non-string values remain ordinary metadata and are not
        documentation.
      • Registered and execution-declared component documentation appears through the
        same fields without minting execution authority.
      • Props and returns retain their canonical draft-07 schemas; captures,
        invocation forms and text/value return mode remain explicit.
      • Undocumented repository Markdown components remain discoverable.
      • Repository TypeScript components appear as origin-only and are never imported.
      • Inspection performs none of the component's effects and creates no journal.
      • Every first-party structural construct and component in the run host profile
        has complete applicable prose documentation.
      • Category and entry ordering is deterministic.
      • JSON and Markdown never describe an opaque TypeScript component as though it
        accepted no props.

      Evidence

      Use Markdown tests as the primary end-to-end evidence:

      • all three categories render in their fixed order;
      • a Markdown component declares description, as, context, and described
        props;
      • xmd syntax discovers it and renders those declarations;
      • xmd syntax --json reports the equivalent structure;
      • an undocumented Markdown component remains discoverable;
      • a repository TypeScript module that throws at top level is listed origin-only
        and is not imported;
      • a component body containing an observable effect is not expanded during
        discovery;
      • repository Markdown/TypeScript and index paths map to dotted names;
      • a candidate file link is selected; a candidate-relevant directory or dangling
        link fails; a link behind a lower-case or dotted prefix is ignored;
      • bare xmd syntax succeeds in a representative package tree containing
        node_modules directory links;
      • duplicate names and component-directory precedence match execution;
      • repeated --include values replace the defaults in caller order;
      • a repository component overriding a built-in appears once in the
        user-provided category;
      • <Session> is present even though inspection creates no execution claimant;
      • captures and self-closing/paired forms are visible; and
      • Markdown and JSON preserve the same names, categories, origins and structural
        fields.

      Add focused core tests for metadata extraction, catalog enumeration, deterministic
      ordering, registration and execution-declaration metadata, origin-only
      TypeScript inspection, structural descriptions, captures/forms, and the
      structured result. Avoid one snapshot of the entire catalog; assert meaningful
      entries and category boundaries so routine description edits do not rewrite
      unrelated evidence.

      Out of scope

      • Implementing xmd prompt itself.
      • Executing components to infer documentation.
      • Importing repository TypeScript components during inspection.
      • A static documentation manifest for repository TypeScript components.
      • Requiring documentation from repository-authored components.
      • A structured ontology for contextual APIs or bindings; context is concise
        prose in this slice.

      Activity

      Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

      Metadata

      Metadata

      Assignees

      No one assigned

        Labels

        No labels
        No labels

        Projects

        No projects

          Milestone

          No milestone

          Relationships

          None yet

          Development

          No branches or pull requests

          Issue actions

          , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
          Skip to content

          Add xmd syntax for discoverable component documentation #632

          Description

          @taras

          Motivation

          Agents and people need an effect-free way to discover the complete syntax
          available to an executable.md run. A consumer must not need prior knowledge of
          the language's structural constructs in order to ask what it can write.

          This is also the prerequisite vocabulary source for xmd prompt (#260): prompt
          generation consumes the same structural descriptions that the CLI exposes,
          rather than maintaining a second handwritten catalog.

          Command

          xmd syntaxxmd syntax --jsonxmd syntax --include ./components --include ./more-components
          • xmd syntax writes human-readable Markdown by default.
          • xmd syntax --json writes the same information as deterministic structured
            JSON for external tools and agents.
          • The command accepts the ordered, repeatable --include configuration used by
            xmd run. Explicit includes replace the defaults; without one it uses
            ["components", "."].
          • Discovery describes the run host profile under the contextual cwd.
          • The command performs inspection only. It does not expand a component body,
            execute eval or shell blocks, import a repository TypeScript module, launch an
            agent, mint execution or invocation authority, or create a journal.

          Catalog categories

          The result always contains these categories in this order:

          1. Built-in structural syntax — the constructs canonical core recognizes
            before component resolution, such as <If>, <Each>, <Output> and
            <Content>.
          2. Built-in components — the selected registered defaults in the run host
            profile, including core, Agent, testing and web components. Components the
            host declares to an execution, such as <Session>, are described from plain
            profile declarations without instantiating their authority-bearing factory.
          3. User-provided components — the selected repository Markdown and
            TypeScript components found through the configured includes.

          A name appears only as the implementation execution would select. A repository
          component that overrides an ordinary built-in default therefore appears once,
          under user-provided components, with the repository origin. Structural syntax
          remains structural because a repository or registration cannot claim it.

          Component discovery

          Core enumerates candidate names from the effective run-profile declarations and
          from repository paths that invert the existing dotted-name mapping:

          • Name.md and Name.ts describe Name;
          • Name/index.md and Name/index.ts describe Name;
          • nested paths describe dotted names, so Ns/Name.md and
            Ns/Name/index.md describe Ns.Name.

          Only paths that describe a name the component grammar accepts are candidates.
          Candidate names are de-duplicated, then each is passed through the same
          selectComponent() decision execution uses. The existing include order,
          .md/.ts candidate order, reserved/default tiers, and repository override
          precedence therefore remain authoritative.

          A missing include contributes no names, as it does during execution. An include
          root that exists but cannot be inspected fails the request rather than making a
          partial catalog look complete. Each configured include root is resolved as the
          directory the caller named; a symbolic-link root is refused.

          Architecture amendment — selection-relevant symlinks. Traversal never follows
          a symbolic link to a directory. It classifies a reported link only when the
          link's complete logical path could participate in component selection: the path
          is itself one of the candidate file spellings, or every path segment is a valid
          component-name segment and could therefore be an ancestor of one. A relevant
          link to a file is selected through its ordinary repository path; a relevant link
          to a directory, to nothing, or to an unclassifiable target fails the whole
          include. The diagnostic names the configured include and logical entry, not its
          resolved host target.

          A link behind a lower-case, dotted, hidden, or otherwise invalid logical prefix
          is ignored. No valid component name can make probeComponentPath() probe
          through that prefix, so ignoring the link cannot hide an implementation
          execution could select. This replaces blanket refusal of every directory link:
          with the default ["components", "."], blanket refusal made bare
          xmd syntax fail in ordinary package repositories solely because
          node_modules contains directory links.

          Entries within each category are ordered by component name in Unicode code-point
          order. Props, captures and syntax forms retain their declaration order.

          Component documentation

          Markdown components may declare these optional string metadata fields directly
          in frontmatter:

          ---description: Creates a temporary directory and expands its body inside it.as: The absolute path of the temporary directory.context: Commands and file operations in the body use the temporary directory.props:
          prefix:
          type: stringdescription: Prefix for the generated directory name---

          The fields mean:

          • description: what the component does.
          • as: what as="name" binds.
          • context: what is applied while expanding the component body.

          They remain ordinary Markdown metadata. They are not reserved and have no
          execution semantics. Inspection recognizes resolved string values under these
          names; another value remains ordinary metadata and contributes no documentation
          field.

          Registered and execution-declared TypeScript components can declare the
          equivalent fields directly with their structural registration metadata. The
          existing props and returns schemas remain the machine-readable validated input
          and result contracts; JSON Schema description continues to document
          individual props.

          Documentation is optional for repository-authored components so existing
          components remain valid. Every first-party structural construct and component
          exposed by the run host profile provides a description, plus as and
          context whenever those explanations apply.

          Inspection contract

          Core provides one effect-free structural result. The CLI Markdown renderer, CLI
          JSON renderer and xmd prompt consume this value directly; neither invokes nor
          parses another one's output.

          The JSON projection has this versioned shape, reusing the existing
          ComponentOrigin, PropsSchema, and ReturnsSchema contracts:

          interfaceSyntaxCatalog{readonlyversion: 1;readonlycategories: readonly[{readonlykind: "structural";readonlyentries: readonlyStructuralSyntaxEntry[]},{readonlykind: "built-in";readonlyentries: readonlyCompleteComponentSyntaxEntry[]},{readonlykind: "user-provided";readonlyentries: readonly(|CompleteComponentSyntaxEntry|OriginOnlyComponentSyntaxEntry)[];},];}interfaceStructuralSyntaxEntry{readonlykind: "structural";readonlyname: string;readonlyorigin: Extract<ComponentOrigin,{kind: "structural"}>;readonlysyntax: readonlystring[];readonlydescription: string;readonlyas?: string;readonlycontext?: string;}interfaceCompleteComponentSyntaxEntry{readonlykind: "component";readonlyname: string;readonlyorigin: Exclude<ComponentOrigin,{kind: "structural"}>;readonlysourceKind: "registered"|"markdown";readonlyinspectability: "complete";readonlyforms: readonly("self-closing"|"paired")[];readonlyprops: PropsSchema;readonlycaptures: readonlystring[];readonlyreturnMode: "text"|"value";readonlyreturns: ReturnsSchema;readonlydescription?: string;readonlyas?: string;readonlycontext?: string;}interfaceOriginOnlyComponentSyntaxEntry{readonlykind: "component";readonlyname: string;readonlyorigin: Extract<ComponentOrigin,{kind: "repository"}>;readonlysourceKind: "typescript";readonlyinspectability: "origin-only";}

          Every structural entry contains its name and structural origin, one or more
          exact authored syntax forms, a description, and as or context prose when
          those concepts apply.

          Every fully inspectable component entry contains:

          • name, category, selected origin and source kind;
          • inspectability: "complete";
          • accepted invocation forms (self-closing, paired, or both), in that
            canonical order;
          • the canonical draft-07 props schema;
          • captured prop names, separately from the schema that deliberately excludes
            them;
          • returnMode: "text" | "value" and the effective returns schema ({ type: "string" } in text mode);
          • optional description, as, and context.

          The return mode stays explicit because a text component and a value component
          declaring returns: { type: string } have the same schema and different
          invocation contracts. Captures stay explicit because they are caller-visible
          props that intentionally do not cross the JSON props boundary.

          Repository TypeScript files are available but not safely inspectable in full:
          their schemas and documentation live on module exports, and loading the module
          would execute top-level code. They therefore appear with name, category,
          repository origin, source kind and inspectability: "origin-only"; props,
          captures, returns, forms and prose fields are absent. A future static manifest
          can enrich them without weakening this command's no-import guarantee.

          Repository Markdown is parsed without expanding its body. A component whose
          prose fields are absent still appears with every structural field inspection can
          safely provide.

          Markdown output

          The default output renders the three categories as separate top-level sections.
          It is useful both as reference documentation and as agent prompt material.
          Each structural construct shows its authored forms and purpose. Each fully
          inspectable component shows invocation forms, purpose, props, captures, as
          meaning, body context, return mode and origin when available. An origin-only
          TypeScript component is identified as such and never presented as accepting no
          props.

          For example:

          ## Built-in components### `<TempDir>`
          Creates a temporary directory and expands its body inside it.
          #### Props| Prop | Type | Required | Description || --- | --- | --- | --- ||`prefix`| string | no | Prefix for the generated directory name |**`as`:** The absolute path of the temporary directory.
          **Body context:** Commands and file operations in the body use the temporary
          directory.

          Acceptance criteria

          • xmd syntax emits Markdown and xmd syntax --json emits the corresponding
            version-1 structured representation.
          • Both outputs and xmd prompt are produced from the same internal inspection
            result.
          • The result contains built-in structural syntax, selected built-in components,
            and selected user-provided components as separate ordered categories.
          • Candidate enumeration and final selection agree with ordinary execution's
            includes, name mapping and resolution precedence.
          • Traversal never follows a directory link. Candidate-relevant directory and
            dangling links fail the whole request; links behind a logical prefix component
            resolution cannot probe through are ignored.
          • Bare xmd syntax remains usable with its default includes in an ordinary
            package repository whose node_modules contains directory links.
          • Repeated --include values preserve caller order and replace the defaults.
          • Markdown frontmatter description, as, and context string values appear
            in both output forms; non-string values remain ordinary metadata and are not
            documentation.
          • Registered and execution-declared component documentation appears through the
            same fields without minting execution authority.
          • Props and returns retain their canonical draft-07 schemas; captures,
            invocation forms and text/value return mode remain explicit.
          • Undocumented repository Markdown components remain discoverable.
          • Repository TypeScript components appear as origin-only and are never imported.
          • Inspection performs none of the component's effects and creates no journal.
          • Every first-party structural construct and component in the run host profile
            has complete applicable prose documentation.
          • Category and entry ordering is deterministic.
          • JSON and Markdown never describe an opaque TypeScript component as though it
            accepted no props.

          Evidence

          Use Markdown tests as the primary end-to-end evidence:

          • all three categories render in their fixed order;
          • a Markdown component declares description, as, context, and described
            props;
          • xmd syntax discovers it and renders those declarations;
          • xmd syntax --json reports the equivalent structure;
          • an undocumented Markdown component remains discoverable;
          • a repository TypeScript module that throws at top level is listed origin-only
            and is not imported;
          • a component body containing an observable effect is not expanded during
            discovery;
          • repository Markdown/TypeScript and index paths map to dotted names;
          • a candidate file link is selected; a candidate-relevant directory or dangling
            link fails; a link behind a lower-case or dotted prefix is ignored;
          • bare xmd syntax succeeds in a representative package tree containing
            node_modules directory links;
          • duplicate names and component-directory precedence match execution;
          • repeated --include values replace the defaults in caller order;
          • a repository component overriding a built-in appears once in the
            user-provided category;
          • <Session> is present even though inspection creates no execution claimant;
          • captures and self-closing/paired forms are visible; and
          • Markdown and JSON preserve the same names, categories, origins and structural
            fields.

          Add focused core tests for metadata extraction, catalog enumeration, deterministic
          ordering, registration and execution-declaration metadata, origin-only
          TypeScript inspection, structural descriptions, captures/forms, and the
          structured result. Avoid one snapshot of the entire catalog; assert meaningful
          entries and category boundaries so routine description edits do not rewrite
          unrelated evidence.

          Out of scope

          • Implementing xmd prompt itself.
          • Executing components to infer documentation.
          • Importing repository TypeScript components during inspection.
          • A static documentation manifest for repository TypeScript components.
          • Requiring documentation from repository-authored components.
          • A structured ontology for contextual APIs or bindings; context is concise
            prose in this slice.

          Activity

          Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

          Metadata

          Metadata

          Assignees

          No one assigned

            Labels

            No labels
            No labels

            Projects

            No projects

              Milestone

              No milestone

              Relationships

              None yet

              Development

              No branches or pull requests

              Issue actions

              , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length \u003e 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
              Skip to content

              Add xmd syntax for discoverable component documentation #632

              Description

              @taras

              Motivation

              Agents and people need an effect-free way to discover the complete syntax
              available to an executable.md run. A consumer must not need prior knowledge of
              the language's structural constructs in order to ask what it can write.

              This is also the prerequisite vocabulary source for xmd prompt (#260): prompt
              generation consumes the same structural descriptions that the CLI exposes,
              rather than maintaining a second handwritten catalog.

              Command

              xmd syntaxxmd syntax --jsonxmd syntax --include ./components --include ./more-components
              • xmd syntax writes human-readable Markdown by default.
              • xmd syntax --json writes the same information as deterministic structured
                JSON for external tools and agents.
              • The command accepts the ordered, repeatable --include configuration used by
                xmd run. Explicit includes replace the defaults; without one it uses
                ["components", "."].
              • Discovery describes the run host profile under the contextual cwd.
              • The command performs inspection only. It does not expand a component body,
                execute eval or shell blocks, import a repository TypeScript module, launch an
                agent, mint execution or invocation authority, or create a journal.

              Catalog categories

              The result always contains these categories in this order:

              1. Built-in structural syntax — the constructs canonical core recognizes
                before component resolution, such as <If>, <Each>, <Output> and
                <Content>.
              2. Built-in components — the selected registered defaults in the run host
                profile, including core, Agent, testing and web components. Components the
                host declares to an execution, such as <Session>, are described from plain
                profile declarations without instantiating their authority-bearing factory.
              3. User-provided components — the selected repository Markdown and
                TypeScript components found through the configured includes.

              A name appears only as the implementation execution would select. A repository
              component that overrides an ordinary built-in default therefore appears once,
              under user-provided components, with the repository origin. Structural syntax
              remains structural because a repository or registration cannot claim it.

              Component discovery

              Core enumerates candidate names from the effective run-profile declarations and
              from repository paths that invert the existing dotted-name mapping:

              • Name.md and Name.ts describe Name;
              • Name/index.md and Name/index.ts describe Name;
              • nested paths describe dotted names, so Ns/Name.md and
                Ns/Name/index.md describe Ns.Name.

              Only paths that describe a name the component grammar accepts are candidates.
              Candidate names are de-duplicated, then each is passed through the same
              selectComponent() decision execution uses. The existing include order,
              .md/.ts candidate order, reserved/default tiers, and repository override
              precedence therefore remain authoritative.

              A missing include contributes no names, as it does during execution. An include
              root that exists but cannot be inspected fails the request rather than making a
              partial catalog look complete. Each configured include root is resolved as the
              directory the caller named; a symbolic-link root is refused.

              Architecture amendment — selection-relevant symlinks. Traversal never follows
              a symbolic link to a directory. It classifies a reported link only when the
              link's complete logical path could participate in component selection: the path
              is itself one of the candidate file spellings, or every path segment is a valid
              component-name segment and could therefore be an ancestor of one. A relevant
              link to a file is selected through its ordinary repository path; a relevant link
              to a directory, to nothing, or to an unclassifiable target fails the whole
              include. The diagnostic names the configured include and logical entry, not its
              resolved host target.

              A link behind a lower-case, dotted, hidden, or otherwise invalid logical prefix
              is ignored. No valid component name can make probeComponentPath() probe
              through that prefix, so ignoring the link cannot hide an implementation
              execution could select. This replaces blanket refusal of every directory link:
              with the default ["components", "."], blanket refusal made bare
              xmd syntax fail in ordinary package repositories solely because
              node_modules contains directory links.

              Entries within each category are ordered by component name in Unicode code-point
              order. Props, captures and syntax forms retain their declaration order.

              Component documentation

              Markdown components may declare these optional string metadata fields directly
              in frontmatter:

              ---description: Creates a temporary directory and expands its body inside it.as: The absolute path of the temporary directory.context: Commands and file operations in the body use the temporary directory.props:
              prefix:
              type: stringdescription: Prefix for the generated directory name---

              The fields mean:

              • description: what the component does.
              • as: what as="name" binds.
              • context: what is applied while expanding the component body.

              They remain ordinary Markdown metadata. They are not reserved and have no
              execution semantics. Inspection recognizes resolved string values under these
              names; another value remains ordinary metadata and contributes no documentation
              field.

              Registered and execution-declared TypeScript components can declare the
              equivalent fields directly with their structural registration metadata. The
              existing props and returns schemas remain the machine-readable validated input
              and result contracts; JSON Schema description continues to document
              individual props.

              Documentation is optional for repository-authored components so existing
              components remain valid. Every first-party structural construct and component
              exposed by the run host profile provides a description, plus as and
              context whenever those explanations apply.

              Inspection contract

              Core provides one effect-free structural result. The CLI Markdown renderer, CLI
              JSON renderer and xmd prompt consume this value directly; neither invokes nor
              parses another one's output.

              The JSON projection has this versioned shape, reusing the existing
              ComponentOrigin, PropsSchema, and ReturnsSchema contracts:

              interfaceSyntaxCatalog{readonlyversion: 1;readonlycategories: readonly[{readonlykind: "structural";readonlyentries: readonlyStructuralSyntaxEntry[]},{readonlykind: "built-in";readonlyentries: readonlyCompleteComponentSyntaxEntry[]},{readonlykind: "user-provided";readonlyentries: readonly(|CompleteComponentSyntaxEntry|OriginOnlyComponentSyntaxEntry)[];},];}interfaceStructuralSyntaxEntry{readonlykind: "structural";readonlyname: string;readonlyorigin: Extract<ComponentOrigin,{kind: "structural"}>;readonlysyntax: readonlystring[];readonlydescription: string;readonlyas?: string;readonlycontext?: string;}interfaceCompleteComponentSyntaxEntry{readonlykind: "component";readonlyname: string;readonlyorigin: Exclude<ComponentOrigin,{kind: "structural"}>;readonlysourceKind: "registered"|"markdown";readonlyinspectability: "complete";readonlyforms: readonly("self-closing"|"paired")[];readonlyprops: PropsSchema;readonlycaptures: readonlystring[];readonlyreturnMode: "text"|"value";readonlyreturns: ReturnsSchema;readonlydescription?: string;readonlyas?: string;readonlycontext?: string;}interfaceOriginOnlyComponentSyntaxEntry{readonlykind: "component";readonlyname: string;readonlyorigin: Extract<ComponentOrigin,{kind: "repository"}>;readonlysourceKind: "typescript";readonlyinspectability: "origin-only";}

              Every structural entry contains its name and structural origin, one or more
              exact authored syntax forms, a description, and as or context prose when
              those concepts apply.

              Every fully inspectable component entry contains:

              • name, category, selected origin and source kind;
              • inspectability: "complete";
              • accepted invocation forms (self-closing, paired, or both), in that
                canonical order;
              • the canonical draft-07 props schema;
              • captured prop names, separately from the schema that deliberately excludes
                them;
              • returnMode: "text" | "value" and the effective returns schema ({ type: "string" } in text mode);
              • optional description, as, and context.

              The return mode stays explicit because a text component and a value component
              declaring returns: { type: string } have the same schema and different
              invocation contracts. Captures stay explicit because they are caller-visible
              props that intentionally do not cross the JSON props boundary.

              Repository TypeScript files are available but not safely inspectable in full:
              their schemas and documentation live on module exports, and loading the module
              would execute top-level code. They therefore appear with name, category,
              repository origin, source kind and inspectability: "origin-only"; props,
              captures, returns, forms and prose fields are absent. A future static manifest
              can enrich them without weakening this command's no-import guarantee.

              Repository Markdown is parsed without expanding its body. A component whose
              prose fields are absent still appears with every structural field inspection can
              safely provide.

              Markdown output

              The default output renders the three categories as separate top-level sections.
              It is useful both as reference documentation and as agent prompt material.
              Each structural construct shows its authored forms and purpose. Each fully
              inspectable component shows invocation forms, purpose, props, captures, as
              meaning, body context, return mode and origin when available. An origin-only
              TypeScript component is identified as such and never presented as accepting no
              props.

              For example:

              ## Built-in components### `<TempDir>`
              Creates a temporary directory and expands its body inside it.
              #### Props| Prop | Type | Required | Description || --- | --- | --- | --- ||`prefix`| string | no | Prefix for the generated directory name |**`as`:** The absolute path of the temporary directory.
              **Body context:** Commands and file operations in the body use the temporary
              directory.

              Acceptance criteria

              • xmd syntax emits Markdown and xmd syntax --json emits the corresponding
                version-1 structured representation.
              • Both outputs and xmd prompt are produced from the same internal inspection
                result.
              • The result contains built-in structural syntax, selected built-in components,
                and selected user-provided components as separate ordered categories.
              • Candidate enumeration and final selection agree with ordinary execution's
                includes, name mapping and resolution precedence.
              • Traversal never follows a directory link. Candidate-relevant directory and
                dangling links fail the whole request; links behind a logical prefix component
                resolution cannot probe through are ignored.
              • Bare xmd syntax remains usable with its default includes in an ordinary
                package repository whose node_modules contains directory links.
              • Repeated --include values preserve caller order and replace the defaults.
              • Markdown frontmatter description, as, and context string values appear
                in both output forms; non-string values remain ordinary metadata and are not
                documentation.
              • Registered and execution-declared component documentation appears through the
                same fields without minting execution authority.
              • Props and returns retain their canonical draft-07 schemas; captures,
                invocation forms and text/value return mode remain explicit.
              • Undocumented repository Markdown components remain discoverable.
              • Repository TypeScript components appear as origin-only and are never imported.
              • Inspection performs none of the component's effects and creates no journal.
              • Every first-party structural construct and component in the run host profile
                has complete applicable prose documentation.
              • Category and entry ordering is deterministic.
              • JSON and Markdown never describe an opaque TypeScript component as though it
                accepted no props.

              Evidence

              Use Markdown tests as the primary end-to-end evidence:

              • all three categories render in their fixed order;
              • a Markdown component declares description, as, context, and described
                props;
              • xmd syntax discovers it and renders those declarations;
              • xmd syntax --json reports the equivalent structure;
              • an undocumented Markdown component remains discoverable;
              • a repository TypeScript module that throws at top level is listed origin-only
                and is not imported;
              • a component body containing an observable effect is not expanded during
                discovery;
              • repository Markdown/TypeScript and index paths map to dotted names;
              • a candidate file link is selected; a candidate-relevant directory or dangling
                link fails; a link behind a lower-case or dotted prefix is ignored;
              • bare xmd syntax succeeds in a representative package tree containing
                node_modules directory links;
              • duplicate names and component-directory precedence match execution;
              • repeated --include values replace the defaults in caller order;
              • a repository component overriding a built-in appears once in the
                user-provided category;
              • <Session> is present even though inspection creates no execution claimant;
              • captures and self-closing/paired forms are visible; and
              • Markdown and JSON preserve the same names, categories, origins and structural
                fields.

              Add focused core tests for metadata extraction, catalog enumeration, deterministic
              ordering, registration and execution-declaration metadata, origin-only
              TypeScript inspection, structural descriptions, captures/forms, and the
              structured result. Avoid one snapshot of the entire catalog; assert meaningful
              entries and category boundaries so routine description edits do not rewrite
              unrelated evidence.

              Out of scope

              • Implementing xmd prompt itself.
              • Executing components to infer documentation.
              • Importing repository TypeScript components during inspection.
              • A static documentation manifest for repository TypeScript components.
              • Requiring documentation from repository-authored components.
              • A structured ontology for contextual APIs or bindings; context is concise
                prose in this slice.

              Activity

              Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

              Metadata

              Metadata

              Assignees

              No one assigned

                Labels

                No labels
                No labels

                Projects

                No projects

                  Milestone

                  No milestone

                  Relationships

                  None yet

                  Development

                  No branches or pull requests

                  Issue actions

                  , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
                  Skip to content

                  Add xmd syntax for discoverable component documentation #632

                  Description

                  @taras

                  Motivation

                  Agents and people need an effect-free way to discover the complete syntax
                  available to an executable.md run. A consumer must not need prior knowledge of
                  the language's structural constructs in order to ask what it can write.

                  This is also the prerequisite vocabulary source for xmd prompt (#260): prompt
                  generation consumes the same structural descriptions that the CLI exposes,
                  rather than maintaining a second handwritten catalog.

                  Command

                  xmd syntaxxmd syntax --jsonxmd syntax --include ./components --include ./more-components
                  • xmd syntax writes human-readable Markdown by default.
                  • xmd syntax --json writes the same information as deterministic structured
                    JSON for external tools and agents.
                  • The command accepts the ordered, repeatable --include configuration used by
                    xmd run. Explicit includes replace the defaults; without one it uses
                    ["components", "."].
                  • Discovery describes the run host profile under the contextual cwd.
                  • The command performs inspection only. It does not expand a component body,
                    execute eval or shell blocks, import a repository TypeScript module, launch an
                    agent, mint execution or invocation authority, or create a journal.

                  Catalog categories

                  The result always contains these categories in this order:

                  1. Built-in structural syntax — the constructs canonical core recognizes
                    before component resolution, such as <If>, <Each>, <Output> and
                    <Content>.
                  2. Built-in components — the selected registered defaults in the run host
                    profile, including core, Agent, testing and web components. Components the
                    host declares to an execution, such as <Session>, are described from plain
                    profile declarations without instantiating their authority-bearing factory.
                  3. User-provided components — the selected repository Markdown and
                    TypeScript components found through the configured includes.

                  A name appears only as the implementation execution would select. A repository
                  component that overrides an ordinary built-in default therefore appears once,
                  under user-provided components, with the repository origin. Structural syntax
                  remains structural because a repository or registration cannot claim it.

                  Component discovery

                  Core enumerates candidate names from the effective run-profile declarations and
                  from repository paths that invert the existing dotted-name mapping:

                  • Name.md and Name.ts describe Name;
                  • Name/index.md and Name/index.ts describe Name;
                  • nested paths describe dotted names, so Ns/Name.md and
                    Ns/Name/index.md describe Ns.Name.

                  Only paths that describe a name the component grammar accepts are candidates.
                  Candidate names are de-duplicated, then each is passed through the same
                  selectComponent() decision execution uses. The existing include order,
                  .md/.ts candidate order, reserved/default tiers, and repository override
                  precedence therefore remain authoritative.

                  A missing include contributes no names, as it does during execution. An include
                  root that exists but cannot be inspected fails the request rather than making a
                  partial catalog look complete. Each configured include root is resolved as the
                  directory the caller named; a symbolic-link root is refused.

                  Architecture amendment — selection-relevant symlinks. Traversal never follows
                  a symbolic link to a directory. It classifies a reported link only when the
                  link's complete logical path could participate in component selection: the path
                  is itself one of the candidate file spellings, or every path segment is a valid
                  component-name segment and could therefore be an ancestor of one. A relevant
                  link to a file is selected through its ordinary repository path; a relevant link
                  to a directory, to nothing, or to an unclassifiable target fails the whole
                  include. The diagnostic names the configured include and logical entry, not its
                  resolved host target.

                  A link behind a lower-case, dotted, hidden, or otherwise invalid logical prefix
                  is ignored. No valid component name can make probeComponentPath() probe
                  through that prefix, so ignoring the link cannot hide an implementation
                  execution could select. This replaces blanket refusal of every directory link:
                  with the default ["components", "."], blanket refusal made bare
                  xmd syntax fail in ordinary package repositories solely because
                  node_modules contains directory links.

                  Entries within each category are ordered by component name in Unicode code-point
                  order. Props, captures and syntax forms retain their declaration order.

                  Component documentation

                  Markdown components may declare these optional string metadata fields directly
                  in frontmatter:

                  ---description: Creates a temporary directory and expands its body inside it.as: The absolute path of the temporary directory.context: Commands and file operations in the body use the temporary directory.props:
                  prefix:
                  type: stringdescription: Prefix for the generated directory name---

                  The fields mean:

                  • description: what the component does.
                  • as: what as="name" binds.
                  • context: what is applied while expanding the component body.

                  They remain ordinary Markdown metadata. They are not reserved and have no
                  execution semantics. Inspection recognizes resolved string values under these
                  names; another value remains ordinary metadata and contributes no documentation
                  field.

                  Registered and execution-declared TypeScript components can declare the
                  equivalent fields directly with their structural registration metadata. The
                  existing props and returns schemas remain the machine-readable validated input
                  and result contracts; JSON Schema description continues to document
                  individual props.

                  Documentation is optional for repository-authored components so existing
                  components remain valid. Every first-party structural construct and component
                  exposed by the run host profile provides a description, plus as and
                  context whenever those explanations apply.

                  Inspection contract

                  Core provides one effect-free structural result. The CLI Markdown renderer, CLI
                  JSON renderer and xmd prompt consume this value directly; neither invokes nor
                  parses another one's output.

                  The JSON projection has this versioned shape, reusing the existing
                  ComponentOrigin, PropsSchema, and ReturnsSchema contracts:

                  interfaceSyntaxCatalog{readonlyversion: 1;readonlycategories: readonly[{readonlykind: "structural";readonlyentries: readonlyStructuralSyntaxEntry[]},{readonlykind: "built-in";readonlyentries: readonlyCompleteComponentSyntaxEntry[]},{readonlykind: "user-provided";readonlyentries: readonly(|CompleteComponentSyntaxEntry|OriginOnlyComponentSyntaxEntry)[];},];}interfaceStructuralSyntaxEntry{readonlykind: "structural";readonlyname: string;readonlyorigin: Extract<ComponentOrigin,{kind: "structural"}>;readonlysyntax: readonlystring[];readonlydescription: string;readonlyas?: string;readonlycontext?: string;}interfaceCompleteComponentSyntaxEntry{readonlykind: "component";readonlyname: string;readonlyorigin: Exclude<ComponentOrigin,{kind: "structural"}>;readonlysourceKind: "registered"|"markdown";readonlyinspectability: "complete";readonlyforms: readonly("self-closing"|"paired")[];readonlyprops: PropsSchema;readonlycaptures: readonlystring[];readonlyreturnMode: "text"|"value";readonlyreturns: ReturnsSchema;readonlydescription?: string;readonlyas?: string;readonlycontext?: string;}interfaceOriginOnlyComponentSyntaxEntry{readonlykind: "component";readonlyname: string;readonlyorigin: Extract<ComponentOrigin,{kind: "repository"}>;readonlysourceKind: "typescript";readonlyinspectability: "origin-only";}

                  Every structural entry contains its name and structural origin, one or more
                  exact authored syntax forms, a description, and as or context prose when
                  those concepts apply.

                  Every fully inspectable component entry contains:

                  • name, category, selected origin and source kind;
                  • inspectability: "complete";
                  • accepted invocation forms (self-closing, paired, or both), in that
                    canonical order;
                  • the canonical draft-07 props schema;
                  • captured prop names, separately from the schema that deliberately excludes
                    them;
                  • returnMode: "text" | "value" and the effective returns schema ({ type: "string" } in text mode);
                  • optional description, as, and context.

                  The return mode stays explicit because a text component and a value component
                  declaring returns: { type: string } have the same schema and different
                  invocation contracts. Captures stay explicit because they are caller-visible
                  props that intentionally do not cross the JSON props boundary.

                  Repository TypeScript files are available but not safely inspectable in full:
                  their schemas and documentation live on module exports, and loading the module
                  would execute top-level code. They therefore appear with name, category,
                  repository origin, source kind and inspectability: "origin-only"; props,
                  captures, returns, forms and prose fields are absent. A future static manifest
                  can enrich them without weakening this command's no-import guarantee.

                  Repository Markdown is parsed without expanding its body. A component whose
                  prose fields are absent still appears with every structural field inspection can
                  safely provide.

                  Markdown output

                  The default output renders the three categories as separate top-level sections.
                  It is useful both as reference documentation and as agent prompt material.
                  Each structural construct shows its authored forms and purpose. Each fully
                  inspectable component shows invocation forms, purpose, props, captures, as
                  meaning, body context, return mode and origin when available. An origin-only
                  TypeScript component is identified as such and never presented as accepting no
                  props.

                  For example:

                  ## Built-in components### `<TempDir>`
                  Creates a temporary directory and expands its body inside it.
                  #### Props| Prop | Type | Required | Description || --- | --- | --- | --- ||`prefix`| string | no | Prefix for the generated directory name |**`as`:** The absolute path of the temporary directory.
                  **Body context:** Commands and file operations in the body use the temporary
                  directory.

                  Acceptance criteria

                  • xmd syntax emits Markdown and xmd syntax --json emits the corresponding
                    version-1 structured representation.
                  • Both outputs and xmd prompt are produced from the same internal inspection
                    result.
                  • The result contains built-in structural syntax, selected built-in components,
                    and selected user-provided components as separate ordered categories.
                  • Candidate enumeration and final selection agree with ordinary execution's
                    includes, name mapping and resolution precedence.
                  • Traversal never follows a directory link. Candidate-relevant directory and
                    dangling links fail the whole request; links behind a logical prefix component
                    resolution cannot probe through are ignored.
                  • Bare xmd syntax remains usable with its default includes in an ordinary
                    package repository whose node_modules contains directory links.
                  • Repeated --include values preserve caller order and replace the defaults.
                  • Markdown frontmatter description, as, and context string values appear
                    in both output forms; non-string values remain ordinary metadata and are not
                    documentation.
                  • Registered and execution-declared component documentation appears through the
                    same fields without minting execution authority.
                  • Props and returns retain their canonical draft-07 schemas; captures,
                    invocation forms and text/value return mode remain explicit.
                  • Undocumented repository Markdown components remain discoverable.
                  • Repository TypeScript components appear as origin-only and are never imported.
                  • Inspection performs none of the component's effects and creates no journal.
                  • Every first-party structural construct and component in the run host profile
                    has complete applicable prose documentation.
                  • Category and entry ordering is deterministic.
                  • JSON and Markdown never describe an opaque TypeScript component as though it
                    accepted no props.

                  Evidence

                  Use Markdown tests as the primary end-to-end evidence:

                  • all three categories render in their fixed order;
                  • a Markdown component declares description, as, context, and described
                    props;
                  • xmd syntax discovers it and renders those declarations;
                  • xmd syntax --json reports the equivalent structure;
                  • an undocumented Markdown component remains discoverable;
                  • a repository TypeScript module that throws at top level is listed origin-only
                    and is not imported;
                  • a component body containing an observable effect is not expanded during
                    discovery;
                  • repository Markdown/TypeScript and index paths map to dotted names;
                  • a candidate file link is selected; a candidate-relevant directory or dangling
                    link fails; a link behind a lower-case or dotted prefix is ignored;
                  • bare xmd syntax succeeds in a representative package tree containing
                    node_modules directory links;
                  • duplicate names and component-directory precedence match execution;
                  • repeated --include values replace the defaults in caller order;
                  • a repository component overriding a built-in appears once in the
                    user-provided category;
                  • <Session> is present even though inspection creates no execution claimant;
                  • captures and self-closing/paired forms are visible; and
                  • Markdown and JSON preserve the same names, categories, origins and structural
                    fields.

                  Add focused core tests for metadata extraction, catalog enumeration, deterministic
                  ordering, registration and execution-declaration metadata, origin-only
                  TypeScript inspection, structural descriptions, captures/forms, and the
                  structured result. Avoid one snapshot of the entire catalog; assert meaningful
                  entries and category boundaries so routine description edits do not rewrite
                  unrelated evidence.

                  Out of scope

                  • Implementing xmd prompt itself.
                  • Executing components to infer documentation.
                  • Importing repository TypeScript components during inspection.
                  • A static documentation manifest for repository TypeScript components.
                  • Requiring documentation from repository-authored components.
                  • A structured ontology for contextual APIs or bindings; context is concise
                    prose in this slice.

                  Activity

                  Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

                  Metadata

                  Metadata

                  Assignees

                  No one assigned

                    Labels

                    No labels
                    No labels

                    Projects

                    No projects

                      Milestone

                      No milestone

                      Relationships

                      None yet

                      Development

                      No branches or pull requests

                      Issue actions

                      , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
                      Skip to content

                      Add xmd syntax for discoverable component documentation #632

                      Description

                      @taras

                      Motivation

                      Agents and people need an effect-free way to discover the complete syntax
                      available to an executable.md run. A consumer must not need prior knowledge of
                      the language's structural constructs in order to ask what it can write.

                      This is also the prerequisite vocabulary source for xmd prompt (#260): prompt
                      generation consumes the same structural descriptions that the CLI exposes,
                      rather than maintaining a second handwritten catalog.

                      Command

                      xmd syntaxxmd syntax --jsonxmd syntax --include ./components --include ./more-components
                      • xmd syntax writes human-readable Markdown by default.
                      • xmd syntax --json writes the same information as deterministic structured
                        JSON for external tools and agents.
                      • The command accepts the ordered, repeatable --include configuration used by
                        xmd run. Explicit includes replace the defaults; without one it uses
                        ["components", "."].
                      • Discovery describes the run host profile under the contextual cwd.
                      • The command performs inspection only. It does not expand a component body,
                        execute eval or shell blocks, import a repository TypeScript module, launch an
                        agent, mint execution or invocation authority, or create a journal.

                      Catalog categories

                      The result always contains these categories in this order:

                      1. Built-in structural syntax — the constructs canonical core recognizes
                        before component resolution, such as <If>, <Each>, <Output> and
                        <Content>.
                      2. Built-in components — the selected registered defaults in the run host
                        profile, including core, Agent, testing and web components. Components the
                        host declares to an execution, such as <Session>, are described from plain
                        profile declarations without instantiating their authority-bearing factory.
                      3. User-provided components — the selected repository Markdown and
                        TypeScript components found through the configured includes.

                      A name appears only as the implementation execution would select. A repository
                      component that overrides an ordinary built-in default therefore appears once,
                      under user-provided components, with the repository origin. Structural syntax
                      remains structural because a repository or registration cannot claim it.

                      Component discovery

                      Core enumerates candidate names from the effective run-profile declarations and
                      from repository paths that invert the existing dotted-name mapping:

                      • Name.md and Name.ts describe Name;
                      • Name/index.md and Name/index.ts describe Name;
                      • nested paths describe dotted names, so Ns/Name.md and
                        Ns/Name/index.md describe Ns.Name.

                      Only paths that describe a name the component grammar accepts are candidates.
                      Candidate names are de-duplicated, then each is passed through the same
                      selectComponent() decision execution uses. The existing include order,
                      .md/.ts candidate order, reserved/default tiers, and repository override
                      precedence therefore remain authoritative.

                      A missing include contributes no names, as it does during execution. An include
                      root that exists but cannot be inspected fails the request rather than making a
                      partial catalog look complete. Each configured include root is resolved as the
                      directory the caller named; a symbolic-link root is refused.

                      Architecture amendment — selection-relevant symlinks. Traversal never follows
                      a symbolic link to a directory. It classifies a reported link only when the
                      link's complete logical path could participate in component selection: the path
                      is itself one of the candidate file spellings, or every path segment is a valid
                      component-name segment and could therefore be an ancestor of one. A relevant
                      link to a file is selected through its ordinary repository path; a relevant link
                      to a directory, to nothing, or to an unclassifiable target fails the whole
                      include. The diagnostic names the configured include and logical entry, not its
                      resolved host target.

                      A link behind a lower-case, dotted, hidden, or otherwise invalid logical prefix
                      is ignored. No valid component name can make probeComponentPath() probe
                      through that prefix, so ignoring the link cannot hide an implementation
                      execution could select. This replaces blanket refusal of every directory link:
                      with the default ["components", "."], blanket refusal made bare
                      xmd syntax fail in ordinary package repositories solely because
                      node_modules contains directory links.

                      Entries within each category are ordered by component name in Unicode code-point
                      order. Props, captures and syntax forms retain their declaration order.

                      Component documentation

                      Markdown components may declare these optional string metadata fields directly
                      in frontmatter:

                      ---description: Creates a temporary directory and expands its body inside it.as: The absolute path of the temporary directory.context: Commands and file operations in the body use the temporary directory.props:
                      prefix:
                      type: stringdescription: Prefix for the generated directory name---

                      The fields mean:

                      • description: what the component does.
                      • as: what as="name" binds.
                      • context: what is applied while expanding the component body.

                      They remain ordinary Markdown metadata. They are not reserved and have no
                      execution semantics. Inspection recognizes resolved string values under these
                      names; another value remains ordinary metadata and contributes no documentation
                      field.

                      Registered and execution-declared TypeScript components can declare the
                      equivalent fields directly with their structural registration metadata. The
                      existing props and returns schemas remain the machine-readable validated input
                      and result contracts; JSON Schema description continues to document
                      individual props.

                      Documentation is optional for repository-authored components so existing
                      components remain valid. Every first-party structural construct and component
                      exposed by the run host profile provides a description, plus as and
                      context whenever those explanations apply.

                      Inspection contract

                      Core provides one effect-free structural result. The CLI Markdown renderer, CLI
                      JSON renderer and xmd prompt consume this value directly; neither invokes nor
                      parses another one's output.

                      The JSON projection has this versioned shape, reusing the existing
                      ComponentOrigin, PropsSchema, and ReturnsSchema contracts:

                      interfaceSyntaxCatalog{readonlyversion: 1;readonlycategories: readonly[{readonlykind: "structural";readonlyentries: readonlyStructuralSyntaxEntry[]},{readonlykind: "built-in";readonlyentries: readonlyCompleteComponentSyntaxEntry[]},{readonlykind: "user-provided";readonlyentries: readonly(|CompleteComponentSyntaxEntry|OriginOnlyComponentSyntaxEntry)[];},];}interfaceStructuralSyntaxEntry{readonlykind: "structural";readonlyname: string;readonlyorigin: Extract<ComponentOrigin,{kind: "structural"}>;readonlysyntax: readonlystring[];readonlydescription: string;readonlyas?: string;readonlycontext?: string;}interfaceCompleteComponentSyntaxEntry{readonlykind: "component";readonlyname: string;readonlyorigin: Exclude<ComponentOrigin,{kind: "structural"}>;readonlysourceKind: "registered"|"markdown";readonlyinspectability: "complete";readonlyforms: readonly("self-closing"|"paired")[];readonlyprops: PropsSchema;readonlycaptures: readonlystring[];readonlyreturnMode: "text"|"value";readonlyreturns: ReturnsSchema;readonlydescription?: string;readonlyas?: string;readonlycontext?: string;}interfaceOriginOnlyComponentSyntaxEntry{readonlykind: "component";readonlyname: string;readonlyorigin: Extract<ComponentOrigin,{kind: "repository"}>;readonlysourceKind: "typescript";readonlyinspectability: "origin-only";}

                      Every structural entry contains its name and structural origin, one or more
                      exact authored syntax forms, a description, and as or context prose when
                      those concepts apply.

                      Every fully inspectable component entry contains:

                      • name, category, selected origin and source kind;
                      • inspectability: "complete";
                      • accepted invocation forms (self-closing, paired, or both), in that
                        canonical order;
                      • the canonical draft-07 props schema;
                      • captured prop names, separately from the schema that deliberately excludes
                        them;
                      • returnMode: "text" | "value" and the effective returns schema ({ type: "string" } in text mode);
                      • optional description, as, and context.

                      The return mode stays explicit because a text component and a value component
                      declaring returns: { type: string } have the same schema and different
                      invocation contracts. Captures stay explicit because they are caller-visible
                      props that intentionally do not cross the JSON props boundary.

                      Repository TypeScript files are available but not safely inspectable in full:
                      their schemas and documentation live on module exports, and loading the module
                      would execute top-level code. They therefore appear with name, category,
                      repository origin, source kind and inspectability: "origin-only"; props,
                      captures, returns, forms and prose fields are absent. A future static manifest
                      can enrich them without weakening this command's no-import guarantee.

                      Repository Markdown is parsed without expanding its body. A component whose
                      prose fields are absent still appears with every structural field inspection can
                      safely provide.

                      Markdown output

                      The default output renders the three categories as separate top-level sections.
                      It is useful both as reference documentation and as agent prompt material.
                      Each structural construct shows its authored forms and purpose. Each fully
                      inspectable component shows invocation forms, purpose, props, captures, as
                      meaning, body context, return mode and origin when available. An origin-only
                      TypeScript component is identified as such and never presented as accepting no
                      props.

                      For example:

                      ## Built-in components### `<TempDir>`
                      Creates a temporary directory and expands its body inside it.
                      #### Props| Prop | Type | Required | Description || --- | --- | --- | --- ||`prefix`| string | no | Prefix for the generated directory name |**`as`:** The absolute path of the temporary directory.
                      **Body context:** Commands and file operations in the body use the temporary
                      directory.

                      Acceptance criteria

                      • xmd syntax emits Markdown and xmd syntax --json emits the corresponding
                        version-1 structured representation.
                      • Both outputs and xmd prompt are produced from the same internal inspection
                        result.
                      • The result contains built-in structural syntax, selected built-in components,
                        and selected user-provided components as separate ordered categories.
                      • Candidate enumeration and final selection agree with ordinary execution's
                        includes, name mapping and resolution precedence.
                      • Traversal never follows a directory link. Candidate-relevant directory and
                        dangling links fail the whole request; links behind a logical prefix component
                        resolution cannot probe through are ignored.
                      • Bare xmd syntax remains usable with its default includes in an ordinary
                        package repository whose node_modules contains directory links.
                      • Repeated --include values preserve caller order and replace the defaults.
                      • Markdown frontmatter description, as, and context string values appear
                        in both output forms; non-string values remain ordinary metadata and are not
                        documentation.
                      • Registered and execution-declared component documentation appears through the
                        same fields without minting execution authority.
                      • Props and returns retain their canonical draft-07 schemas; captures,
                        invocation forms and text/value return mode remain explicit.
                      • Undocumented repository Markdown components remain discoverable.
                      • Repository TypeScript components appear as origin-only and are never imported.
                      • Inspection performs none of the component's effects and creates no journal.
                      • Every first-party structural construct and component in the run host profile
                        has complete applicable prose documentation.
                      • Category and entry ordering is deterministic.
                      • JSON and Markdown never describe an opaque TypeScript component as though it
                        accepted no props.

                      Evidence

                      Use Markdown tests as the primary end-to-end evidence:

                      • all three categories render in their fixed order;
                      • a Markdown component declares description, as, context, and described
                        props;
                      • xmd syntax discovers it and renders those declarations;
                      • xmd syntax --json reports the equivalent structure;
                      • an undocumented Markdown component remains discoverable;
                      • a repository TypeScript module that throws at top level is listed origin-only
                        and is not imported;
                      • a component body containing an observable effect is not expanded during
                        discovery;
                      • repository Markdown/TypeScript and index paths map to dotted names;
                      • a candidate file link is selected; a candidate-relevant directory or dangling
                        link fails; a link behind a lower-case or dotted prefix is ignored;
                      • bare xmd syntax succeeds in a representative package tree containing
                        node_modules directory links;
                      • duplicate names and component-directory precedence match execution;
                      • repeated --include values replace the defaults in caller order;
                      • a repository component overriding a built-in appears once in the
                        user-provided category;
                      • <Session> is present even though inspection creates no execution claimant;
                      • captures and self-closing/paired forms are visible; and
                      • Markdown and JSON preserve the same names, categories, origins and structural
                        fields.

                      Add focused core tests for metadata extraction, catalog enumeration, deterministic
                      ordering, registration and execution-declaration metadata, origin-only
                      TypeScript inspection, structural descriptions, captures/forms, and the
                      structured result. Avoid one snapshot of the entire catalog; assert meaningful
                      entries and category boundaries so routine description edits do not rewrite
                      unrelated evidence.

                      Out of scope

                      • Implementing xmd prompt itself.
                      • Executing components to infer documentation.
                      • Importing repository TypeScript components during inspection.
                      • A static documentation manifest for repository TypeScript components.
                      • Requiring documentation from repository-authored components.
                      • A structured ontology for contextual APIs or bindings; context is concise
                        prose in this slice.

                      Activity

                      Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

                      Metadata

                      Metadata

                      Assignees

                      No one assigned

                        Labels

                        No labels
                        No labels

                        Projects

                        No projects

                          Milestone

                          No milestone

                          Relationships

                          None yet

                          Development

                          No branches or pull requests

                          Issue actions

                          , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
                          Skip to content

                          Add xmd syntax for discoverable component documentation #632

                          Description

                          @taras

                          Motivation

                          Agents and people need an effect-free way to discover the complete syntax
                          available to an executable.md run. A consumer must not need prior knowledge of
                          the language's structural constructs in order to ask what it can write.

                          This is also the prerequisite vocabulary source for xmd prompt (#260): prompt
                          generation consumes the same structural descriptions that the CLI exposes,
                          rather than maintaining a second handwritten catalog.

                          Command

                          xmd syntaxxmd syntax --jsonxmd syntax --include ./components --include ./more-components
                          • xmd syntax writes human-readable Markdown by default.
                          • xmd syntax --json writes the same information as deterministic structured
                            JSON for external tools and agents.
                          • The command accepts the ordered, repeatable --include configuration used by
                            xmd run. Explicit includes replace the defaults; without one it uses
                            ["components", "."].
                          • Discovery describes the run host profile under the contextual cwd.
                          • The command performs inspection only. It does not expand a component body,
                            execute eval or shell blocks, import a repository TypeScript module, launch an
                            agent, mint execution or invocation authority, or create a journal.

                          Catalog categories

                          The result always contains these categories in this order:

                          1. Built-in structural syntax — the constructs canonical core recognizes
                            before component resolution, such as <If>, <Each>, <Output> and
                            <Content>.
                          2. Built-in components — the selected registered defaults in the run host
                            profile, including core, Agent, testing and web components. Components the
                            host declares to an execution, such as <Session>, are described from plain
                            profile declarations without instantiating their authority-bearing factory.
                          3. User-provided components — the selected repository Markdown and
                            TypeScript components found through the configured includes.

                          A name appears only as the implementation execution would select. A repository
                          component that overrides an ordinary built-in default therefore appears once,
                          under user-provided components, with the repository origin. Structural syntax
                          remains structural because a repository or registration cannot claim it.

                          Component discovery

                          Core enumerates candidate names from the effective run-profile declarations and
                          from repository paths that invert the existing dotted-name mapping:

                          • Name.md and Name.ts describe Name;
                          • Name/index.md and Name/index.ts describe Name;
                          • nested paths describe dotted names, so Ns/Name.md and
                            Ns/Name/index.md describe Ns.Name.

                          Only paths that describe a name the component grammar accepts are candidates.
                          Candidate names are de-duplicated, then each is passed through the same
                          selectComponent() decision execution uses. The existing include order,
                          .md/.ts candidate order, reserved/default tiers, and repository override
                          precedence therefore remain authoritative.

                          A missing include contributes no names, as it does during execution. An include
                          root that exists but cannot be inspected fails the request rather than making a
                          partial catalog look complete. Each configured include root is resolved as the
                          directory the caller named; a symbolic-link root is refused.

                          Architecture amendment — selection-relevant symlinks. Traversal never follows
                          a symbolic link to a directory. It classifies a reported link only when the
                          link's complete logical path could participate in component selection: the path
                          is itself one of the candidate file spellings, or every path segment is a valid
                          component-name segment and could therefore be an ancestor of one. A relevant
                          link to a file is selected through its ordinary repository path; a relevant link
                          to a directory, to nothing, or to an unclassifiable target fails the whole
                          include. The diagnostic names the configured include and logical entry, not its
                          resolved host target.

                          A link behind a lower-case, dotted, hidden, or otherwise invalid logical prefix
                          is ignored. No valid component name can make probeComponentPath() probe
                          through that prefix, so ignoring the link cannot hide an implementation
                          execution could select. This replaces blanket refusal of every directory link:
                          with the default ["components", "."], blanket refusal made bare
                          xmd syntax fail in ordinary package repositories solely because
                          node_modules contains directory links.

                          Entries within each category are ordered by component name in Unicode code-point
                          order. Props, captures and syntax forms retain their declaration order.

                          Component documentation

                          Markdown components may declare these optional string metadata fields directly
                          in frontmatter:

                          ---description: Creates a temporary directory and expands its body inside it.as: The absolute path of the temporary directory.context: Commands and file operations in the body use the temporary directory.props:
                          prefix:
                          type: stringdescription: Prefix for the generated directory name---

                          The fields mean:

                          • description: what the component does.
                          • as: what as="name" binds.
                          • context: what is applied while expanding the component body.

                          They remain ordinary Markdown metadata. They are not reserved and have no
                          execution semantics. Inspection recognizes resolved string values under these
                          names; another value remains ordinary metadata and contributes no documentation
                          field.

                          Registered and execution-declared TypeScript components can declare the
                          equivalent fields directly with their structural registration metadata. The
                          existing props and returns schemas remain the machine-readable validated input
                          and result contracts; JSON Schema description continues to document
                          individual props.

                          Documentation is optional for repository-authored components so existing
                          components remain valid. Every first-party structural construct and component
                          exposed by the run host profile provides a description, plus as and
                          context whenever those explanations apply.

                          Inspection contract

                          Core provides one effect-free structural result. The CLI Markdown renderer, CLI
                          JSON renderer and xmd prompt consume this value directly; neither invokes nor
                          parses another one's output.

                          The JSON projection has this versioned shape, reusing the existing
                          ComponentOrigin, PropsSchema, and ReturnsSchema contracts:

                          interfaceSyntaxCatalog{readonlyversion: 1;readonlycategories: readonly[{readonlykind: "structural";readonlyentries: readonlyStructuralSyntaxEntry[]},{readonlykind: "built-in";readonlyentries: readonlyCompleteComponentSyntaxEntry[]},{readonlykind: "user-provided";readonlyentries: readonly(|CompleteComponentSyntaxEntry|OriginOnlyComponentSyntaxEntry)[];},];}interfaceStructuralSyntaxEntry{readonlykind: "structural";readonlyname: string;readonlyorigin: Extract<ComponentOrigin,{kind: "structural"}>;readonlysyntax: readonlystring[];readonlydescription: string;readonlyas?: string;readonlycontext?: string;}interfaceCompleteComponentSyntaxEntry{readonlykind: "component";readonlyname: string;readonlyorigin: Exclude<ComponentOrigin,{kind: "structural"}>;readonlysourceKind: "registered"|"markdown";readonlyinspectability: "complete";readonlyforms: readonly("self-closing"|"paired")[];readonlyprops: PropsSchema;readonlycaptures: readonlystring[];readonlyreturnMode: "text"|"value";readonlyreturns: ReturnsSchema;readonlydescription?: string;readonlyas?: string;readonlycontext?: string;}interfaceOriginOnlyComponentSyntaxEntry{readonlykind: "component";readonlyname: string;readonlyorigin: Extract<ComponentOrigin,{kind: "repository"}>;readonlysourceKind: "typescript";readonlyinspectability: "origin-only";}

                          Every structural entry contains its name and structural origin, one or more
                          exact authored syntax forms, a description, and as or context prose when
                          those concepts apply.

                          Every fully inspectable component entry contains:

                          • name, category, selected origin and source kind;
                          • inspectability: "complete";
                          • accepted invocation forms (self-closing, paired, or both), in that
                            canonical order;
                          • the canonical draft-07 props schema;
                          • captured prop names, separately from the schema that deliberately excludes
                            them;
                          • returnMode: "text" | "value" and the effective returns schema ({ type: "string" } in text mode);
                          • optional description, as, and context.

                          The return mode stays explicit because a text component and a value component
                          declaring returns: { type: string } have the same schema and different
                          invocation contracts. Captures stay explicit because they are caller-visible
                          props that intentionally do not cross the JSON props boundary.

                          Repository TypeScript files are available but not safely inspectable in full:
                          their schemas and documentation live on module exports, and loading the module
                          would execute top-level code. They therefore appear with name, category,
                          repository origin, source kind and inspectability: "origin-only"; props,
                          captures, returns, forms and prose fields are absent. A future static manifest
                          can enrich them without weakening this command's no-import guarantee.

                          Repository Markdown is parsed without expanding its body. A component whose
                          prose fields are absent still appears with every structural field inspection can
                          safely provide.

                          Markdown output

                          The default output renders the three categories as separate top-level sections.
                          It is useful both as reference documentation and as agent prompt material.
                          Each structural construct shows its authored forms and purpose. Each fully
                          inspectable component shows invocation forms, purpose, props, captures, as
                          meaning, body context, return mode and origin when available. An origin-only
                          TypeScript component is identified as such and never presented as accepting no
                          props.

                          For example:

                          ## Built-in components### `<TempDir>`
                          Creates a temporary directory and expands its body inside it.
                          #### Props| Prop | Type | Required | Description || --- | --- | --- | --- ||`prefix`| string | no | Prefix for the generated directory name |**`as`:** The absolute path of the temporary directory.
                          **Body context:** Commands and file operations in the body use the temporary
                          directory.

                          Acceptance criteria

                          • xmd syntax emits Markdown and xmd syntax --json emits the corresponding
                            version-1 structured representation.
                          • Both outputs and xmd prompt are produced from the same internal inspection
                            result.
                          • The result contains built-in structural syntax, selected built-in components,
                            and selected user-provided components as separate ordered categories.
                          • Candidate enumeration and final selection agree with ordinary execution's
                            includes, name mapping and resolution precedence.
                          • Traversal never follows a directory link. Candidate-relevant directory and
                            dangling links fail the whole request; links behind a logical prefix component
                            resolution cannot probe through are ignored.
                          • Bare xmd syntax remains usable with its default includes in an ordinary
                            package repository whose node_modules contains directory links.
                          • Repeated --include values preserve caller order and replace the defaults.
                          • Markdown frontmatter description, as, and context string values appear
                            in both output forms; non-string values remain ordinary metadata and are not
                            documentation.
                          • Registered and execution-declared component documentation appears through the
                            same fields without minting execution authority.
                          • Props and returns retain their canonical draft-07 schemas; captures,
                            invocation forms and text/value return mode remain explicit.
                          • Undocumented repository Markdown components remain discoverable.
                          • Repository TypeScript components appear as origin-only and are never imported.
                          • Inspection performs none of the component's effects and creates no journal.
                          • Every first-party structural construct and component in the run host profile
                            has complete applicable prose documentation.
                          • Category and entry ordering is deterministic.
                          • JSON and Markdown never describe an opaque TypeScript component as though it
                            accepted no props.

                          Evidence

                          Use Markdown tests as the primary end-to-end evidence:

                          • all three categories render in their fixed order;
                          • a Markdown component declares description, as, context, and described
                            props;
                          • xmd syntax discovers it and renders those declarations;
                          • xmd syntax --json reports the equivalent structure;
                          • an undocumented Markdown component remains discoverable;
                          • a repository TypeScript module that throws at top level is listed origin-only
                            and is not imported;
                          • a component body containing an observable effect is not expanded during
                            discovery;
                          • repository Markdown/TypeScript and index paths map to dotted names;
                          • a candidate file link is selected; a candidate-relevant directory or dangling
                            link fails; a link behind a lower-case or dotted prefix is ignored;
                          • bare xmd syntax succeeds in a representative package tree containing
                            node_modules directory links;
                          • duplicate names and component-directory precedence match execution;
                          • repeated --include values replace the defaults in caller order;
                          • a repository component overriding a built-in appears once in the
                            user-provided category;
                          • <Session> is present even though inspection creates no execution claimant;
                          • captures and self-closing/paired forms are visible; and
                          • Markdown and JSON preserve the same names, categories, origins and structural
                            fields.

                          Add focused core tests for metadata extraction, catalog enumeration, deterministic
                          ordering, registration and execution-declaration metadata, origin-only
                          TypeScript inspection, structural descriptions, captures/forms, and the
                          structured result. Avoid one snapshot of the entire catalog; assert meaningful
                          entries and category boundaries so routine description edits do not rewrite
                          unrelated evidence.

                          Out of scope

                          • Implementing xmd prompt itself.
                          • Executing components to infer documentation.
                          • Importing repository TypeScript components during inspection.
                          • A static documentation manifest for repository TypeScript components.
                          • Requiring documentation from repository-authored components.
                          • A structured ontology for contextual APIs or bindings; context is concise
                            prose in this slice.

                          Activity

                          Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

                          Metadata

                          Metadata

                          Assignees

                          No one assigned

                            Labels

                            No labels
                            No labels

                            Projects

                            No projects

                              Milestone

                              No milestone

                              Relationships

                              None yet

                              Development

                              No branches or pull requests

                              Issue actions

                              , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
                              Skip to content

                              Add xmd syntax for discoverable component documentation #632

                              Description

                              @taras

                              Motivation

                              Agents and people need an effect-free way to discover the complete syntax
                              available to an executable.md run. A consumer must not need prior knowledge of
                              the language's structural constructs in order to ask what it can write.

                              This is also the prerequisite vocabulary source for xmd prompt (#260): prompt
                              generation consumes the same structural descriptions that the CLI exposes,
                              rather than maintaining a second handwritten catalog.

                              Command

                              xmd syntaxxmd syntax --jsonxmd syntax --include ./components --include ./more-components
                              • xmd syntax writes human-readable Markdown by default.
                              • xmd syntax --json writes the same information as deterministic structured
                                JSON for external tools and agents.
                              • The command accepts the ordered, repeatable --include configuration used by
                                xmd run. Explicit includes replace the defaults; without one it uses
                                ["components", "."].
                              • Discovery describes the run host profile under the contextual cwd.
                              • The command performs inspection only. It does not expand a component body,
                                execute eval or shell blocks, import a repository TypeScript module, launch an
                                agent, mint execution or invocation authority, or create a journal.

                              Catalog categories

                              The result always contains these categories in this order:

                              1. Built-in structural syntax — the constructs canonical core recognizes
                                before component resolution, such as <If>, <Each>, <Output> and
                                <Content>.
                              2. Built-in components — the selected registered defaults in the run host
                                profile, including core, Agent, testing and web components. Components the
                                host declares to an execution, such as <Session>, are described from plain
                                profile declarations without instantiating their authority-bearing factory.
                              3. User-provided components — the selected repository Markdown and
                                TypeScript components found through the configured includes.

                              A name appears only as the implementation execution would select. A repository
                              component that overrides an ordinary built-in default therefore appears once,
                              under user-provided components, with the repository origin. Structural syntax
                              remains structural because a repository or registration cannot claim it.

                              Component discovery

                              Core enumerates candidate names from the effective run-profile declarations and
                              from repository paths that invert the existing dotted-name mapping:

                              • Name.md and Name.ts describe Name;
                              • Name/index.md and Name/index.ts describe Name;
                              • nested paths describe dotted names, so Ns/Name.md and
                                Ns/Name/index.md describe Ns.Name.

                              Only paths that describe a name the component grammar accepts are candidates.
                              Candidate names are de-duplicated, then each is passed through the same
                              selectComponent() decision execution uses. The existing include order,
                              .md/.ts candidate order, reserved/default tiers, and repository override
                              precedence therefore remain authoritative.

                              A missing include contributes no names, as it does during execution. An include
                              root that exists but cannot be inspected fails the request rather than making a
                              partial catalog look complete. Each configured include root is resolved as the
                              directory the caller named; a symbolic-link root is refused.

                              Architecture amendment — selection-relevant symlinks. Traversal never follows
                              a symbolic link to a directory. It classifies a reported link only when the
                              link's complete logical path could participate in component selection: the path
                              is itself one of the candidate file spellings, or every path segment is a valid
                              component-name segment and could therefore be an ancestor of one. A relevant
                              link to a file is selected through its ordinary repository path; a relevant link
                              to a directory, to nothing, or to an unclassifiable target fails the whole
                              include. The diagnostic names the configured include and logical entry, not its
                              resolved host target.

                              A link behind a lower-case, dotted, hidden, or otherwise invalid logical prefix
                              is ignored. No valid component name can make probeComponentPath() probe
                              through that prefix, so ignoring the link cannot hide an implementation
                              execution could select. This replaces blanket refusal of every directory link:
                              with the default ["components", "."], blanket refusal made bare
                              xmd syntax fail in ordinary package repositories solely because
                              node_modules contains directory links.

                              Entries within each category are ordered by component name in Unicode code-point
                              order. Props, captures and syntax forms retain their declaration order.

                              Component documentation

                              Markdown components may declare these optional string metadata fields directly
                              in frontmatter:

                              ---description: Creates a temporary directory and expands its body inside it.as: The absolute path of the temporary directory.context: Commands and file operations in the body use the temporary directory.props:
                              prefix:
                              type: stringdescription: Prefix for the generated directory name---

                              The fields mean:

                              • description: what the component does.
                              • as: what as="name" binds.
                              • context: what is applied while expanding the component body.

                              They remain ordinary Markdown metadata. They are not reserved and have no
                              execution semantics. Inspection recognizes resolved string values under these
                              names; another value remains ordinary metadata and contributes no documentation
                              field.

                              Registered and execution-declared TypeScript components can declare the
                              equivalent fields directly with their structural registration metadata. The
                              existing props and returns schemas remain the machine-readable validated input
                              and result contracts; JSON Schema description continues to document
                              individual props.

                              Documentation is optional for repository-authored components so existing
                              components remain valid. Every first-party structural construct and component
                              exposed by the run host profile provides a description, plus as and
                              context whenever those explanations apply.

                              Inspection contract

                              Core provides one effect-free structural result. The CLI Markdown renderer, CLI
                              JSON renderer and xmd prompt consume this value directly; neither invokes nor
                              parses another one's output.

                              The JSON projection has this versioned shape, reusing the existing
                              ComponentOrigin, PropsSchema, and ReturnsSchema contracts:

                              interfaceSyntaxCatalog{readonlyversion: 1;readonlycategories: readonly[{readonlykind: "structural";readonlyentries: readonlyStructuralSyntaxEntry[]},{readonlykind: "built-in";readonlyentries: readonlyCompleteComponentSyntaxEntry[]},{readonlykind: "user-provided";readonlyentries: readonly(|CompleteComponentSyntaxEntry|OriginOnlyComponentSyntaxEntry)[];},];}interfaceStructuralSyntaxEntry{readonlykind: "structural";readonlyname: string;readonlyorigin: Extract<ComponentOrigin,{kind: "structural"}>;readonlysyntax: readonlystring[];readonlydescription: string;readonlyas?: string;readonlycontext?: string;}interfaceCompleteComponentSyntaxEntry{readonlykind: "component";readonlyname: string;readonlyorigin: Exclude<ComponentOrigin,{kind: "structural"}>;readonlysourceKind: "registered"|"markdown";readonlyinspectability: "complete";readonlyforms: readonly("self-closing"|"paired")[];readonlyprops: PropsSchema;readonlycaptures: readonlystring[];readonlyreturnMode: "text"|"value";readonlyreturns: ReturnsSchema;readonlydescription?: string;readonlyas?: string;readonlycontext?: string;}interfaceOriginOnlyComponentSyntaxEntry{readonlykind: "component";readonlyname: string;readonlyorigin: Extract<ComponentOrigin,{kind: "repository"}>;readonlysourceKind: "typescript";readonlyinspectability: "origin-only";}

                              Every structural entry contains its name and structural origin, one or more
                              exact authored syntax forms, a description, and as or context prose when
                              those concepts apply.

                              Every fully inspectable component entry contains:

                              • name, category, selected origin and source kind;
                              • inspectability: "complete";
                              • accepted invocation forms (self-closing, paired, or both), in that
                                canonical order;
                              • the canonical draft-07 props schema;
                              • captured prop names, separately from the schema that deliberately excludes
                                them;
                              • returnMode: "text" | "value" and the effective returns schema ({ type: "string" } in text mode);
                              • optional description, as, and context.

                              The return mode stays explicit because a text component and a value component
                              declaring returns: { type: string } have the same schema and different
                              invocation contracts. Captures stay explicit because they are caller-visible
                              props that intentionally do not cross the JSON props boundary.

                              Repository TypeScript files are available but not safely inspectable in full:
                              their schemas and documentation live on module exports, and loading the module
                              would execute top-level code. They therefore appear with name, category,
                              repository origin, source kind and inspectability: "origin-only"; props,
                              captures, returns, forms and prose fields are absent. A future static manifest
                              can enrich them without weakening this command's no-import guarantee.

                              Repository Markdown is parsed without expanding its body. A component whose
                              prose fields are absent still appears with every structural field inspection can
                              safely provide.

                              Markdown output

                              The default output renders the three categories as separate top-level sections.
                              It is useful both as reference documentation and as agent prompt material.
                              Each structural construct shows its authored forms and purpose. Each fully
                              inspectable component shows invocation forms, purpose, props, captures, as
                              meaning, body context, return mode and origin when available. An origin-only
                              TypeScript component is identified as such and never presented as accepting no
                              props.

                              For example:

                              ## Built-in components### `<TempDir>`
                              Creates a temporary directory and expands its body inside it.
                              #### Props| Prop | Type | Required | Description || --- | --- | --- | --- ||`prefix`| string | no | Prefix for the generated directory name |**`as`:** The absolute path of the temporary directory.
                              **Body context:** Commands and file operations in the body use the temporary
                              directory.

                              Acceptance criteria

                              • xmd syntax emits Markdown and xmd syntax --json emits the corresponding
                                version-1 structured representation.
                              • Both outputs and xmd prompt are produced from the same internal inspection
                                result.
                              • The result contains built-in structural syntax, selected built-in components,
                                and selected user-provided components as separate ordered categories.
                              • Candidate enumeration and final selection agree with ordinary execution's
                                includes, name mapping and resolution precedence.
                              • Traversal never follows a directory link. Candidate-relevant directory and
                                dangling links fail the whole request; links behind a logical prefix component
                                resolution cannot probe through are ignored.
                              • Bare xmd syntax remains usable with its default includes in an ordinary
                                package repository whose node_modules contains directory links.
                              • Repeated --include values preserve caller order and replace the defaults.
                              • Markdown frontmatter description, as, and context string values appear
                                in both output forms; non-string values remain ordinary metadata and are not
                                documentation.
                              • Registered and execution-declared component documentation appears through the
                                same fields without minting execution authority.
                              • Props and returns retain their canonical draft-07 schemas; captures,
                                invocation forms and text/value return mode remain explicit.
                              • Undocumented repository Markdown components remain discoverable.
                              • Repository TypeScript components appear as origin-only and are never imported.
                              • Inspection performs none of the component's effects and creates no journal.
                              • Every first-party structural construct and component in the run host profile
                                has complete applicable prose documentation.
                              • Category and entry ordering is deterministic.
                              • JSON and Markdown never describe an opaque TypeScript component as though it
                                accepted no props.

                              Evidence

                              Use Markdown tests as the primary end-to-end evidence:

                              • all three categories render in their fixed order;
                              • a Markdown component declares description, as, context, and described
                                props;
                              • xmd syntax discovers it and renders those declarations;
                              • xmd syntax --json reports the equivalent structure;
                              • an undocumented Markdown component remains discoverable;
                              • a repository TypeScript module that throws at top level is listed origin-only
                                and is not imported;
                              • a component body containing an observable effect is not expanded during
                                discovery;
                              • repository Markdown/TypeScript and index paths map to dotted names;
                              • a candidate file link is selected; a candidate-relevant directory or dangling
                                link fails; a link behind a lower-case or dotted prefix is ignored;
                              • bare xmd syntax succeeds in a representative package tree containing
                                node_modules directory links;
                              • duplicate names and component-directory precedence match execution;
                              • repeated --include values replace the defaults in caller order;
                              • a repository component overriding a built-in appears once in the
                                user-provided category;
                              • <Session> is present even though inspection creates no execution claimant;
                              • captures and self-closing/paired forms are visible; and
                              • Markdown and JSON preserve the same names, categories, origins and structural
                                fields.

                              Add focused core tests for metadata extraction, catalog enumeration, deterministic
                              ordering, registration and execution-declaration metadata, origin-only
                              TypeScript inspection, structural descriptions, captures/forms, and the
                              structured result. Avoid one snapshot of the entire catalog; assert meaningful
                              entries and category boundaries so routine description edits do not rewrite
                              unrelated evidence.

                              Out of scope

                              • Implementing xmd prompt itself.
                              • Executing components to infer documentation.
                              • Importing repository TypeScript components during inspection.
                              • A static documentation manifest for repository TypeScript components.
                              • Requiring documentation from repository-authored components.
                              • A structured ontology for contextual APIs or bindings; context is concise
                                prose in this slice.

                              Activity

                              Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

                              Metadata

                              Metadata

                              Assignees

                              No one assigned

                                Labels

                                No labels
                                No labels

                                Projects

                                No projects

                                  Milestone

                                  No milestone

                                  Relationships

                                  None yet

                                  Development

                                  No branches or pull requests

                                  Issue actions