You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Revised after owner interview (2026-08-02): matcher-based <Answer> children replace the original ordered values array. The template engine is borrowed from TestAgent.
Motivation
A component that uses <Elicit> internally asks whoever the host's provider reaches. Sometimes the surrounding document already knows the answers: a workflow exercising a third-party component non-interactively, a demo, a region of a run that should not stop for a person. Today the only way to supply answers is scriptElicitations() in an eval block — TypeScript, sanctioned only for tests. Providing answers should be a document construct (Code Rule 11).
<Answers> is elicitation middleware as a component: it installs a scoped provider around its children's expansion. Its <Answer> children are matchers; every other child is the wrapped body, rendered transparently — the wrapper changes who answers, never what the body produces.
<Answer> matchers
template prop for a single-line template, or children for a multiline one — supplying both is a configuration error (the <WhenPrompt> convention).
Templates match the whole rendered message of an elicitation: literal text constrains, {?name} matches any text and binds nothing (wildcard only in this slice — capture-into-value is deferred until a use case demands it), {binding} interpolates an existing binding and requires it at that position.
An <Answer> with no template matches any message.
value (required) — the answer, as an expression or captured JSON text. Parsed at the wrapper, so a malformed value is reported where it was written, not disguised as a provider failure inside a child.
<Answer> is meaningful only as a direct child of <Answers>; anywhere else it is a positioned diagnostic, mirroring <Else> outside <If>.
An <Answers> with no body — self-closing, or nothing but <Answer> children — is a positioned configuration diagnostic: it can never answer anything, so writing it is a mistake worth catching (owner ruling, 2026-08-02, from PR ✨ Add <Answers>/<Answer>: supply elicitation responses as a document construct #269 review). How the wrapper receives its matchers (slots or expansion machinery) is the implementor's plan question, not contract.
Selection
The first declared matching<Answer> answers. Matchers are reusable: one answers every elicitation it matches for the wrapper's lifetime. Consequence, stated deliberately: declaration order is significant, and a broad template above a narrow one shadows it permanently — first-wins plus reusable is the whole selection rule.
An <Answer> that never fires is not an error.
Unmatched elicitations
delegate (optional boolean on <Answers>, default false):
false: an elicitation no matcher answers fails, with a diagnostic naming the actual message and the templates tried (the expected/actual style of PromptMismatchError).
true: the middleware calls next — the elicitation walks outward through enclosing <Answers> to the host's provider.
Nested <Answers>: installed at { at: "min" }, the nearest region answers first; with delegate the chain composes outward.
What core already guarantees (unchanged)
Every provided answer is judged by core against the asking component's schema before it binds — <Answers> performs no validation beyond JSON parsing.
Unmarked, fail-fast under 💥 Fail fast on function-component failures, collect explicitly #251's default. <Answers> and <Answer> are claimed structural names like <Test>/<WhenPrompt> — implemented as an expansion hook receiving raw children, and therefore not overridable by repository files (owner ruling, 2026-08-02, mechanism-plan review: a construct that needs raw children is structural, and a repository function component could not implement matcher semantics).
Borrowed machinery
The template engine is packages/test-agent/src/template.ts — pure, dependency-free parseTemplate/matchPrompt with whole-string anchoring, wildcard holes, binding interpolation, and expected/actual mismatch errors. Hoist it to core and have test-agent import it from there, following the schema-walk/canonicalize consolidation pattern from #264: dependency direction only works that way, and TestAgent's behavior and diagnostics must be provably unchanged (its suites are the evidence). <WhenPrompt>'s staged model — every prompt must match the active stage — is deliberately not borrowed: <Answers> is an unordered matcher set, per the middleware framing.
Acceptance criteria
The example above answers a nested component's elicitation with no host provider installed, choosing by template.
First-declared-wins proven with two overlapping templates; reusability proven with one matcher answering two elicitations.
delegate={false} fails an unmatched elicitation with the templates-tried diagnostic; delegate={true} reaches an observing outer provider; nested regions compose.
A provided answer failing the asking schema fails that elicitation with normal validation diagnostics.
A misplaced <Answer>, a bodyless <Answers>, a template parse error, both template forms at once, and a non-JSON value are each positioned configuration diagnostics.
Replay restores without matching.
TestAgent suites pass unchanged against the hoisted engine.
The {binding} asymmetry between the template= prop (engine resolves the binding) and the children form (markdown interpolation substitutes it first) is inherited from <WhenPrompt> and documented in the spec for both constructs — net matching constraint identical, diagnostics and absent-binding edges differ (owner ruling, 2026-08-02).
Spec section, site documentation, and colocated markdown coverage ship in the same PR.
Sequencing
Next up (owner decision, 2026-08-02) — proceeds in parallel with the #197 chain's PR 2; nothing on #76/#260 depends on it.
Motivation
A component that uses
<Elicit>internally asks whoever the host's provider reaches. Sometimes the surrounding document already knows the answers: a workflow exercising a third-party component non-interactively, a demo, a region of a run that should not stop for a person. Today the only way to supply answers isscriptElicitations()in an eval block — TypeScript, sanctioned only for tests. Providing answers should be a document construct (Code Rule 11).Contract
<Answers>is elicitation middleware as a component: it installs a scoped provider around its children's expansion. Its<Answer>children are matchers; every other child is the wrapped body, rendered transparently — the wrapper changes who answers, never what the body produces.<Answer>matcherstemplateprop for a single-line template, or children for a multiline one — supplying both is a configuration error (the<WhenPrompt>convention).{?name}matches any text and binds nothing (wildcard only in this slice — capture-into-value is deferred until a use case demands it),{binding}interpolates an existing binding and requires it at that position.<Answer>with no template matches any message.value(required) — the answer, as an expression or captured JSON text. Parsed at the wrapper, so a malformed value is reported where it was written, not disguised as a provider failure inside a child.<Answer>is meaningful only as a direct child of<Answers>; anywhere else it is a positioned diagnostic, mirroring<Else>outside<If>.<Answers>with no body — self-closing, or nothing but<Answer>children — is a positioned configuration diagnostic: it can never answer anything, so writing it is a mistake worth catching (owner ruling, 2026-08-02, from PR ✨ Add<Answers>/<Answer>: supply elicitation responses as a document construct #269 review). How the wrapper receives its matchers (slots or expansion machinery) is the implementor's plan question, not contract.Selection
<Answer>answers. Matchers are reusable: one answers every elicitation it matches for the wrapper's lifetime. Consequence, stated deliberately: declaration order is significant, and a broad template above a narrow one shadows it permanently — first-wins plus reusable is the whole selection rule.<Answer>that never fires is not an error.Unmatched elicitations
delegate(optional boolean on<Answers>, defaultfalse):false: an elicitation no matcher answers fails, with a diagnostic naming the actual message and the templates tried (theexpected/actualstyle ofPromptMismatchError).true: the middleware callsnext— the elicitation walks outward through enclosing<Answers>to the host's provider.<Answers>: installed at{ at: "min" }, the nearest region answers first; withdelegatethe chain composes outward.What core already guarantees (unchanged)
<Answers>performs no validation beyond JSON parsing.<Answers>and<Answer>are claimed structural names like<Test>/<WhenPrompt>— implemented as an expansion hook receiving raw children, and therefore not overridable by repository files (owner ruling, 2026-08-02, mechanism-plan review: a construct that needs raw children is structural, and a repository function component could not implement matcher semantics).Borrowed machinery
The template engine is
packages/test-agent/src/template.ts— pure, dependency-freeparseTemplate/matchPromptwith whole-string anchoring, wildcard holes, binding interpolation, and expected/actual mismatch errors. Hoist it to core and have test-agent import it from there, following theschema-walk/canonicalizeconsolidation pattern from #264: dependency direction only works that way, and TestAgent's behavior and diagnostics must be provably unchanged (its suites are the evidence).<WhenPrompt>'s staged model — every prompt must match the active stage — is deliberately not borrowed:<Answers>is an unordered matcher set, per the middleware framing.Acceptance criteria
<Answer>matches anything;{binding}interpolation constrains;{?name}binds nothing.delegate={false}fails an unmatched elicitation with the templates-tried diagnostic;delegate={true}reaches an observing outer provider; nested regions compose.<Answer>, a bodyless<Answers>, a template parse error, both template forms at once, and a non-JSONvalueare each positioned configuration diagnostics.{binding}asymmetry between thetemplate=prop (engine resolves the binding) and the children form (markdown interpolation substitutes it first) is inherited from<WhenPrompt>and documented in the spec for both constructs — net matching constraint identical, diagnostics and absent-binding edges differ (owner ruling, 2026-08-02).Sequencing
Next up (owner decision, 2026-08-02) — proceeds in parallel with the #197 chain's PR 2; nothing on #76/#260 depends on it.