Skip to content

Add provider-neutral Elicit through the core Context API #197

Description

@taras

Motivation

Executable Markdown workflows need a provider-neutral way to pause for
structured human input. The document should describe what it is asking and the
valid response shape without choosing whether the interaction occurs in a web
form, terminal UI, Effection Inspector, automated test, or another host.

<Elicit> is a core contextual capability. It does not select an interaction
mode. The current CLI configuration uses the WebForm provider tracked in #195.

Implementation coordination

<Elicit> is an ordinary core TypeScript function component registered as a non-reserved default through #202's registration surface. Core resolves and validates props, owns as, creates the invocation boundary, and applies the validated return binding. The component receives no raw ComponentElement, expression map, binding environment, or as value and is not implemented through Component.expand.

Implementation depends on:

  1. Register function components and migrate legacy component handlers #202 PR 1 for scope-local registration and ordinary function-component resolution; and
  2. Add a bundled local WebForm component for schema-backed user input #195's reviewed live-form provider operation/adapter contract for the CLI's initial provider.

It does not wait for #202's Agent, Testing, assertion, or TestAgent migrations, and it does not depend on WebForm's browser-CI, website, or publication cleanup once the provider contract is available.

The component compiles the response schema before calling content(). It then presents the rendered request through the contextual Elicitation provider and returns the provider result through a declared broad JSON return schema. No schema, content, provider, or transport behavior is implemented a second time in an expansion handler.

Authoring contract

<Elicit schema={responseSchema} as="response">
  Review the implementation plan and provide your decision.
</Elicit>
  • <Elicit> and the Elicitation Context API live in @executablemd/core.
  • schema and as are required.
  • schema accepts captured JSON text or an already structured draft-07 JSON
    Schema value.
  • Invocation content expands through content() into the request message presented by the configured provider.
  • A valid structured response binds directly to as.
  • The component emits nothing into the surrounding document.
  • The component exposes no mode, provider, WebForm, or RJSF-specific props.
  • Authors that intentionally require a browser form or RJSF uiSchema can use
    the public <WebForm> component from Add a bundled local WebForm component for schema-backed user input #195 directly.

Elicitation Context API

The contextual provider receives only the rendered request and compiled
response schema:

interface ElicitationRequest {
  message: string;
  schema: JsonSchema;
}

It returns an unknown structured value through an Effection operation.

Core owns:

  • schema parsing and compilation;
  • final response validation;
  • capture and source diagnostics;
  • durable response recording and replay; and
  • interruption through the surrounding Effection scope.

The provider owns only its live interaction and transport lifecycle. It does
not receive as, workflow run IDs, journal details, or component execution
identities.

The schema compiles before invocation content expands or the provider is contacted. An
invalid schema therefore produces no invocation-content effects and cannot open an
interaction.

When no provider is installed, <Elicit> fails immediately with a clear
no elicitation provider configured diagnostic.

Provider configuration

Provider selection happens only through the Context API.

  • The normal CLI composes the WebForm implementation from Add a bundled local WebForm component for schema-backed user input #195 as its current
    provider.
  • Applications embedding core explicitly install an elicitation provider.
  • Automated tests install scripted middleware through the same API.
  • Future terminal and Effection Inspector integrations replace the provider
    without changing executable Markdown.

Core has no dependency on React, RJSF, HTTP serving, browser launching, terminal
UI, or Inspector packages.

Response and lifecycle behavior

  • Core validates every provider result against the compiled schema before it
    binds or journals the value.
  • A schema-invalid provider result fails once with normalized validation
    diagnostics. Core does not silently invoke the provider again.
  • Interactive correction belongs inside a provider such as WebForm. Workflow
    retry belongs in visible bounded Markdown control flow.
  • Provider failures propagate with <Elicit> source context.
  • Halting the execution halts the provider operation and its owned resources.
  • <Elicit> has no protocol-defined approve, decline, cancel, or other
    outcomes. The schema defines every response option available to the user.
  • Cancellation of execution remains an Effection lifecycle event unless the
    document explicitly models cancellation as schema data.

Durability

Only the final validated response is journaled.

On replay, core restores the response and binding without expanding the request
content or invoking the configured provider. Provider choice and transport
details do not affect a completed replay.

Testing

Add a colocated Elicit.test.md document. It uses an eval block to apply
scripted Elicitation Context middleware within each <Test> scope, invokes
<Elicit> normally, and asserts the captured response.

Core exposes a test helper for constructing the scripted middleware. The eval
block supplies an ordered response queue rather than reimplementing a provider.
The helper:

  • consumes one response per live elicitation;
  • fails when an elicitation has no scripted response;
  • fails at test teardown when scripted responses remain unused; and
  • is removed automatically with the enclosing test scope.

No testing-only prop or special Markdown component is added. This eval use is
an explicitly approved exception for installing Context API middleware.

The Markdown tests cover:

  • schemas supplied as captured JSON and structured values;
  • invocation content becoming the provider request;
  • structured capture with no surrounding output;
  • multiple elicitations consuming scripted responses in order;
  • missing scripted responses; and
  • unused scripted responses.

Add lower-level automated tests for:

  • required props and capture name;
  • malformed and invalid draft-07 schemas;
  • schema compilation before invocation-content expansion;
  • no provider being configured;
  • the provider receiving only the rendered message and compiled schema;
  • provider results being validated again by core;
  • normalized diagnostics for invalid provider results;
  • invocation-content and provider failures propagating with source context;
  • interruption halting an active provider;
  • contextual provider override and restoration;
  • durable response recording;
  • full replay without invocation-content expansion or provider invocation; and
  • parity across Deno, Node, and Bun.

Documentation

  • Specify the component props, schema forms, output, validation, and lifecycle
    behavior in the core component reference.
  • Document the Elicitation Context API and show how hosts install providers.
  • Add a website example using <Elicit> for a human review decision.
  • Explain why provider selection is contextual rather than an author-facing
    mode.
  • Link the current WebForm provider in Add a bundled local WebForm component for schema-backed user input #195 while keeping browser-specific
    details out of the core contract.

Acceptance criteria

  • <Elicit> expresses a provider-neutral, schema-constrained request.
  • The provider is selected exclusively through the Context API.
  • Core validates both the schema and the provider response.
  • Invalid schemas cause no invocation-content or provider effects.
  • Missing providers and invalid responses produce actionable diagnostics.
  • Response options come only from the document's schema.
  • Interruption remains a lifecycle event.
  • Replay restores the response without repeating invocation-content or provider work.
  • Markdown tests configure scripted responses through eval-installed
    middleware with exact queue consumption.
  • Specification and website documentation ship in the same PR.

Not included

  • A mode prop or provider selection in Markdown.
  • RJSF uiSchema or other provider-specific presentation options.
  • Built-in approve, decline, or cancel actions.
  • Hidden retry or response repair.
  • The WebForm implementation and bundled assets tracked in Add a bundled local WebForm component for schema-backed user input #195.
  • Terminal UI and Effection Inspector providers.

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