What's New in the Component System¶
A summary of changes for template and component authors already familiar with
{{ insert() }} and component.yml.
Parameter names: _alias and _ask¶
The alias and ask parameters on insert() have been renamed to _alias
and _ask:
{# Before #}
{{ insert('nda', alias='confidentiality', ask="Include NDA?") }}
{# After #}
{{ insert('nda', _alias='confidentiality', _ask="Include NDA?") }}
Why: The old names were reserved — you couldn't have a component input
called alias or ask. The _ prefix creates a clear namespace for VIBE
directives, freeing all unprefixed names for your component's inputs.
The old names are no longer accepted; VIBE will report a validation error if you use them.
Positioning questions with _after¶
Instead of adding _insert_questions_ markers to your config.yml, you can
now position component questions directly from insert():
This places the component's interview questions immediately after
contract_value — no config marker needed.
When combined with _ask, the gate question also appears at the _after
position:
The _insert_questions_ markers in config.yml still work; _after is an
alternative that keeps positioning closer to the insert() call.
Followup questions with _follows¶
Use _follows to make component questions appear as visual follow-ups nested
under a host question:
When the user answers client_city, the component's questions (postal code,
country) appear as sub-questions visually attached to it.
_after and _follows are mutually exclusive — _after positions questions
in the main interview list, _follows nests them under a parent.
collection.yml replaces defaults.yml¶
The configuration file for component collections has been renamed from
defaults.yml to collection.yml:
components/
└── legal_clauses/
├── collection.yml ← preferred name
├── force_majeure.md
└── governing_law.md
Both names are still recognized, but collection.yml is preferred. No action
required — existing defaults.yml files continue to work.
Collection questions¶
Collections can now have their own interview questions, declared in
collection.yml alongside inputs:
# collection.yml
inputs:
PartyA:
type: text
PartyB:
type: text
questions:
ArbitrationPreferred:
label: Do the parties prefer arbitration?
type: bool
How they differ from inputs:
| Inputs | Collection questions | |
|---|---|---|
| Who provides the value | The host, via insert() or component_defaults |
The user, during the interview |
| Asked how many times | N/A (not asked) | Once per collection, regardless of how many components you insert |
| Use case | Data the host knows (party names, dates) | Details internal to the collection (clause variants, preferences) |
Component templates reference collection questions as regular variables:
{% if ArbitrationPreferred %}
Any disputes shall be resolved by arbitration...
{% else %}
Any disputes shall be resolved by the courts of {{ Jurisdiction }}...
{% endif %}
Values passed via insert() take precedence over collection question answers,
so hosts can override when needed:
When to use inputs vs. questions: If the host template naturally knows the value (party names, governing law, language), make it an input. If the value is a detail of how the collection's templates work internally (clause variants, formatting preferences), make it a question.
Grouped gates with _multichoice¶
When several optional components should be presented as a single multichoice
(checkbox) question instead of separate Yes/No gates, use _multichoice:
{{ insert("clauses.ai", _ask="Artificial Intelligence", _multichoice="Commitments") }}
{{ insert("clauses.bench", _ask="Benchmarking", _multichoice="Commitments") }}
{{ insert("clauses.sla", _ask="Service Levels", _multichoice="Commitments") }}
All insert() calls that share the same _multichoice label are combined into
one multichoice question. Each component's _ask label becomes a checkbox
option. Checking an option opens that component's gate; unchecking it closes it.
Constraints:
_multichoicerequires_ask(the option label)._multichoicecannot be combined with_follows.- All members of a group that use
_aftermust target the same question.
Placement uses the same mechanisms as standalone gates — _after, or a
config marker named after the generated question ID. The ID is _mc_ followed
by a slug of the label (e.g., _multichoice="Commitments" → _mc_commitments).
You can reserve its position in config.yml:
questions:
title:
type: text
_mc_commitments: true # marker — multichoice question appears here
author:
type: text
Automatic followup nesting for collection questions¶
When a component collection is gated by a _multichoice question, collection-
level questions are now automatically nested as followups of the relevant
checkbox option — provided the question is referenced by exactly one component
template in the collection.
Questions referenced by two or more components (or by none) remain standalone, since there is no single obvious parent to attach them to.
This means the interview only shows a collection question when the user has selected the component that actually needs it, rather than displaying it unconditionally.
Input scoping¶
When you insert a template from a collection, VIBE now only validates the inputs that template actually uses — not every input the collection declares.
# collection.yml — declares three inputs
inputs:
PartyA:
type: text
PartyB:
type: text
Jurisdiction:
type: text
If force_majeure.md only references PartyA, then inserting it without
providing PartyB or Jurisdiction is valid:
{{ insert('legal_clauses.force_majeure', PartyA=client_name) }}
{# No error — force_majeure.md doesn't use PartyB or Jurisdiction #}
This makes large collections practical. A clause library can declare dozens of inputs without every template needing all of them.
Summary of insert() parameters¶
All VIBE directive parameters use the _ prefix. Component input names are
always unprefixed.
| Parameter | Purpose | Example |
|---|---|---|
_alias |
Unique instance name (required for multiple insertions of same component) | _alias='party_a_sig' |
_ask |
Gate question — user decides whether to include | _ask="Include NDA?" or _ask=True |
_after |
Position questions after a named host question | _after='contract_value' |
_follows |
Nest questions as follow-ups of a host question | _follows='client_city' |
_multichoice |
Group multiple components into one checkbox question | _multichoice="Commitments" |
| (any other) | Component input value | PartyA=client_name |