Core VIBE Engine Architecture¶
Architectural reference for the core VIBE document assembly engine. Optimized for LLM consumption.
See also:
components.md- Component system detailsassistant.md- AI-assisted interview systemfrontend.md- Frontend UI patterns (htmx, Alpine.js)llm-providers.md- LLM provider abstractionreview.md- Document compliance reviewauthor.md- Template authoring workspace
1. SYSTEM OVERVIEW¶
VIBE is a Flask-based document assembly system that generates documents through dynamic interviews. Core innovation: probing mechanism determines question relevance by executing templates with placeholder values rather than static analysis.
Core Philosophy: Template-as-Truth
- Templates control question relevance (not configuration)
- Execution-based discovery (not prediction)
- Server-driven UI with minimal client logic
Application Core: VibeFlask (subclass of Flask in vibe/core.py) adds type-hinted attributes for template_provider, LLM_ENDPOINTS, etc. Infrastructure uses DataDirectoryManager (vibe/infrastructure/data_directory.py) for all data path resolution (sessions, logs, caches). Config path is resolved from VIBE_CONFIG_PATH env var (default: config.yml), overridable via vibe run --config path/to/config.yml.
2. PROBING MECHANISM (CORE INNOVATION)¶
2.1 Central Architecture¶
The probing system determines question relevance by executing the template with current state and tracking variable access via custom Jinja Undefined handler.
Key Files:
vibe/probing/orchestrator.py- Core probing logic and TrackingUndefinedvibe/web/core/state_tracker.py- Flask wrapper and relevance determinationvibe/probing/exceptions.py- ProbeMissingPathError, ProbeNeedsError
2.2 Core Function: run_probe¶
Location: vibe/probing/orchestrator.py::run_probe (delegates to ProbeOrchestrator). Accepts optional alias parameter for component probing.
Algorithm (via ProbeOrchestrator):
- Configure TrackingUndefined as Jinja undefined handler
- Initialize
probe_context(NestedValue with tracker callback) - Set up PlaceholderManager for on-demand placeholder creation
- Install
_ProbeVibeContext(closure-based VibeContext subclass) asenv.context_class. Internal keys (_host_template,_is_probing,_probe_runtime, etc.) come from the closure, not from the data dict. - Suppress NestedValue tracking -- Before
template.render(probe_context), setsuppress_nv_trackingcontextvars flag (vibe/nested_value.py) toTrue. Jinja'sTemplate.render()internally callsdict(probe_context), which invokes__getitem__on ALL top-level keys -- this would create false-positive accesses. The flag is reset in_ProbeVibeContext.__init__(which fires afterdict()but before actual rendering begins). - Render template --
_ProbeVibeContextis constructed automatically byTemplate.render()withprobe_contextas the parent dict:- TrackingUndefined instances resolve placeholders on first use (no immediate retry needed)
_ProbeVibeContext.resolve_or_missing()catches top-level variable accesses that bypass NestedValue dunder methods (e.g., Jinja tests likeis true,is none, passing values to filters/macros) and records them via the orchestrator's tracker- Only retry on
ProbeNeedsError(component needs additional context) - Only retry on
ProbeMissingPathErrorfor local variables (component aliases, appendix paths)
- Restore original Jinja environment (undefined handler and context_class)
- Return ProbeResult
TrackingUndefined Pattern:
- Custom Jinja Undefined class installed as
env.undefined - On undefined variable access, TrackingUndefined is instantiated
- First operation (str(), bool(), etc.) triggers
_resolve_value()via PlaceholderManager - Records access path + template location (file, line number)
- Delegates all operations to resolved placeholder value
- Child attribute/item access spawns new TrackingUndefined with extended path
Important Probe Semantics: Probing is short-circuit -- it tracks what was executed for the current state, not all possible branches. accessed_keys means "touched during this probe run". Comparison hooks run on both unresolved (TrackingUndefined) and resolved (NestedValue) values. Access paths are usually dot paths (a.b.c) but bracket forms can appear (a['b']).
Return Value: ProbeResult dataclass
probe_status: "pending" | "success" | "error" | "max_attempts"needed_vars: list[str]accessed_keys: set[str]probe_context: NestedValueerror_message: str | Noneaccessed_locations: dict[str, tuple[str | None, int | None]]recommendations: list[dict] -- targets fromrecommend()calls encountered during probingrendered_markdown: str | None -- final rendered output when probe succeeds
2.3 Web Wrapper: probe_template¶
Location: vibe/web/core/state_tracker.py::probe_template
Flask wrapper -- injects g.accessed_questions tracker, updates session on errors. Called from vibe/web/interview_logic.py.
2.4 Relevance Determination¶
Two functions share the relevance algorithm, split by dependency boundary:
determine_relevant_questions_core (headless core, no Flask)
Location: vibe/probing/relevance.py::determine_relevant_questions_core
Pure-logic function usable outside Flask (e.g., vibe/testing/runner.py::HeadlessInterviewRunner). Accepts explicit previous_relevant set for component stability. Now a true headless function with no Flask dependencies.
determine_relevant_questions (web wrapper)
Location: vibe/web/core/state_tracker.py::determine_relevant_questions
Flask wrapper that reads g.interview["previous_relevant_questions"], adds assisted fields and appendix questions via the additional_relevant parameter, then delegates to the core logic in vibe/probing/relevance.py.
Algorithm (shared core):
- Start with
accessed_keys UNION needed_vars - Add component questions (if component used and question accessed/needed/previously relevant)
- Filter to known question keys
- Include parent questions via dependency_map (ancestor traversal)
- Sort by original question order
Web wrapper additions (before core):
- Add appendix questions (if appendix active)
- Add assisted fields (if prompt can render with current state)
Contract Note:
- Output is question paths only (
list[str]), not option-level state. - Option-level hidden/disabled behavior should be layered on top of this contract, not inferred as a built-in probe result.
3. DATA STRUCTURES¶
3.1 NestedValue¶
Location: vibe/nested_value.py::NestedValue
Dictionary subclass supporting nested attribute access (context.a.b.c) and access tracking during probing. Key attributes: _value, _path_segment, _parent, _source (ValueSource enum), _definition. Leaf node _value holds primitive/object value -- do not assume answered values are stored as plain types at the top level.
Tracking Suppression: suppress_nv_tracking contextvars flag suppresses access recording during dict() conversion to prevent false-positive access recording (see Section 2.2 step 5).
Helper Functions: set_nested_value, get_nested_node, get_nested_value, nested_to_dict, create_nested_structure
3.2 Path Utilities¶
Location: vibe/utils/path.py
parse_path(path_str) -- Parse "items[0].name" -> ("items", 0, "name") with @lru_cache(maxsize=1024). path_to_string(parts) -- reverse.
3.3 VibeContext & Rendering Functions¶
Location: vibe/jinja/context.py
Custom Jinja2 context separating template data from internal rendering state. Internal keys (e.g., _host_template, _is_probing, meta) are stored in a _vibe_ctx dict, not in the template data tree. A single _KEY_NAMES mapping (kwarg name -> template-facing key name) is the source of truth; INTERNAL_KEYS and _DEFAULTS are derived from it. Set as context_class on all Jinja environments (vibe/jinja/env.py).
Rendering entry points (bypass Template.render()'s dict conversion to avoid mutating NestedValue): vibe_render() for Markdown/Jinja paths, make_docx_render_context() for DOCX. Web preview mode returns ChainableUndefined for missing variables (graceful degradation). VibeProbeContext subclass adds placeholder resolution.
3.4 ValueSource¶
Location: vibe/structures.py::ValueSource
Enum tracking origin of each value: UNKNOWN, INTERMEDIATE, SESSION_CONTEXT, LINKED, USER_ANSWER, PROBE_PLACEHOLDER, HOST_MAPPING, COMPONENT_DEFAULT, COMPUTED, JINJA_RESULT. Used for priority checking (don't overwrite USER_ANSWER with PROBE_PLACEHOLDER; never overwrite SESSION_CONTEXT or LINKED from form posts).
3.5 Question Definition Models¶
Location: vibe/runtime_models/definitions.py
Question definitions from config.yml are parsed into frozen Pydantic v2 models at the provider boundary via parse_question_def(). Key types: QuestionDefBase (shared fields), TextDef, BoolDef, TristateDef, EnumDef, NumberDef, DateDef, AmountDef, PeriodDef, ListDef, StructuredDef, ComputableDef, MessageDef, MultiChoiceDef. def_attr(definition, key, default) bridges Pydantic models and raw dicts. Design: frozen=True, extra="forbid", discriminated union via type field.
3.6 TemplateData¶
Location: vibe/structures.py::TemplateData
Comprehensive dataclass containing all template metadata, questions, compiled template, and validation results.
Key Fields:
| Field | Type | Purpose |
|---|---|---|
template_id |
str | Unique template identifier |
version_identifier |
str | Git SHA or "WORKING_TREE" |
template_obj |
jinja2.Template | Compiled Jinja template |
template_env |
jinja2.Environment | Template-specific Jinja env |
questions |
Mapping | Question definitions (ID -> definition dict) |
definitions |
Mapping | Structured type definitions |
order |
list | Original question ordering |
dependencies |
dict | Dependency map (question -> parent) |
loaded_components_map |
dict | Component data (comp_id -> ComponentTemplateData) |
followup_placements |
dict | Parent -> option -> followup IDs mapping |
extension_data |
dict[str, Any] | Extension data (e.g., assistant prompts via extension_data.get("assistant")) |
interview_mode |
str | None | Runtime-validated via interview_modes.is_valid_interview_mode() |
uses_declarations |
list | Raw uses: declarations; imports definitions and questions from components |
parsed_uses_declarations |
list[UsesDeclaration] | Normalized uses declarations |
inline_source_template_ids |
list[str] | Template IDs sourced via components.sources |
Creation: vibe/templates_mgmt/provider_core.py::_load_template
3.7 ProbeResult¶
Location: vibe/probing/orchestrator.py::ProbeResult
Return value from run_probe. See Section 2.2 for fields.
4. TEMPLATE PROVIDER & VFS¶
4.1 TemplateDataProvider¶
Location: vibe/templates_mgmt/provider_core.py::TemplateDataProvider
Key Responsibilities:
- Load and parse
config.yml(questions, definitions, settings) - Resolve
include:directives in config files (YAML include inheritance) - Compile Jinja templates with custom filters/globals
- Run AST analysis to extract components, assistant blocks, appendices
- Recursively load components with dependency resolution
- Cache templates by
(template_id, version_identifier)
Template Source Configuration: Each template_sources entry is either an explicit path: to a template directory, or an include: that auto-discovers subdirectories containing config.yml. Collisions raise ValueError at startup.
YAML Include (Config Inheritance): Any YAML config file can declare include: with relative paths to inherit from base configs. Recursive with circular detection, deep dict merging (including file's keys overlay base). Works across all VFS schemes.
Question Placement System: Component questions are positioned in the host template via a declarative 2-phase approach (vibe/templates_mgmt/question_placement.py):
- Collection phase (
collect_placements) -- Iterates over component instances and producesQuestionPlacementrecords with typed placement specs:AfterQuestion(position after a host question),FollowupOf(nest as followup),InMultichoice(gate behind multichoice option), orStandalone(append to order). - Resolution phase (
resolve_placements) -- Single pass that writestemplate.questions,template.order, andtemplate.followup_placements. Invalid placements (referencing nonexistent targets) fall through to Standalone with a validation error.
This replaces the former multi-stage mutation pipeline with an explicit data model.
Caching: Filesystem (mtime-based), Git (SHA-based immutable), Embedded (always fresh)
4.2 VirtualFileSystem¶
Location: vibe/templates_mgmt/provider_vfs.py::VirtualFileSystem
Unified API for reading files across storage backends.
URI Schemes: file://, git://<base64_repo>/<sha>/<path>, embedded://<template_id>/<path>
Key Methods: read(vpath), locate_component(component_id, host_template), load_python_module
Component Discovery: Global sources first, then relative to host (traverse up directory tree), prioritize files over directories.
See also: components.md for component system details
5. HANDLER SYSTEM (FIELD TYPES)¶
Purpose: Plugin system for field types -- each handler encapsulates widget rendering, form parsing, validation, and probe placeholders.
Location: vibe/handlers/ package
Architecture:
DataTypeHandlerabstract base class (vibe/handlers/base.py)QuestionRenderContextfrozen dataclass (vibe/handlers/base.py) -- per-request rendering stateHANDLER_REGISTRY-- Type name -> handler class mapping@register_handler(type_name)decorator for registrationget_handler_for_definition(definition, render_context=...)-- Factory function
Schema vs. Rendering State Separation: Handler construction separates static schema (definition dict -- immutable YAML config) from per-request state (QuestionRenderContext -- frozen dataclass with internal_name, locked, question_disabled). The factory get_handler_for_definition(definition, render_context=...) passes both to DataTypeHandler.__init__().
Base Handler Methods: render_widget, process_form_data, validate_input, get_probe_placeholder
Built-in Handlers: TextHandler (text/email/password/textarea), NumberHandler, BoolHandler, TristateHandler, EnumHandler (select/radio), MultiChoiceHandler, DateHandler, AmountHandler, PeriodHandler, ListHandler, StructuredHandler, ComputableHandler, MessageHandler (note/warning/error)
6. SESSION MANAGEMENT¶
Location: vibe/web/core/session_mgmt.py
Storage: Flask session (server-side FileSystemCache in DataDirectoryManager.get_sessions_dir())
6.1 Multi-Interview Session Structure¶
The session uses a two-level structure: auth data at the session root and interview state nested under session['interviews'][key].
session = {
# Auth-level data (shared across interviews)
"email": str, "user_name": str, "grants": list,
"_csrf_token": str, "devel": bool,
# Interview data (keyed by "template_id:version_identifier")
"interviews": {
"my_template:abc123": {
"session_id": str,
"template_id": str,
"version_id": str,
"current_state": NestedValue, # All answers (hierarchical)
"previous_relevant_questions": list,
"asked_questions": list,
"status": "pending"|"error"|"complete",
"error_message": str | None,
"validation_errors": dict,
"_generation": int, # Optimistic concurrency
"_insert_cache": dict, # Insert-level memoization (see components.md ยง9)
"linked_from": dict | None, # Source interview metadata (linked interviews)
"linked_bindings": list[dict], # Data bindings from source interview
"active_recommendations": list, # recommend() targets for linked launches
"assistants": dict,
"finalized_assistants": dict,
},
},
}
6.2 Interview Key Derivation¶
Key format: f"{template_id}:{version_identifier}". The route_setup decorator extracts template_id and version from URL, looks up session['interviews'][key], and sets g.interview. Most code accesses state through g.interview; set session.modified = True after changes.
6.3 Key Functions¶
initialize_session(template_id, version_identifier, group_id) -- Creates interview key, initializes interview state, creates NestedValue with ValueSource.SESSION_CONTEXT. Accepts optional linked_data, linked_from, and linked_bindings for linked interview launches.
update_answers_from_form(...) -- Parses form data via handlers, updates g.interview["current_state"], validates, stores errors. Refuses to overwrite SESSION_CONTEXT or LINKED values from form posts.
7. INTERVIEW FLOW¶
7.1 Initial Request¶
GET /interview/<template_id>/@<version>/
-> @route_setup(load_template=True)
-> initialize_session
-> probe_template -> run_probe -> ProbeResult
-> determine_relevant_questions -> Ordered list
-> Render widgets via handlers -> HTML
-> Return full page
7.2 HTMX Auto-Submit (Field Change)¶
User changes field -> HTMX auto-submits (hx-post="/process/<template_id>/@<version>/")
-> update_answers_from_form -> Parse + Validate
-> probe_template -> ProbeResult
-> Compare previous_relevant vs. new_relevant -> Identify changes
-> Render OOB swaps (removed/new/error divs, progress bar, preview)
-> Return HTML fragments -> HTMX swaps DOM (no page reload)
7.3 Key Routes¶
| Route | Method | Purpose |
|---|---|---|
/interview/<id>/@<version>/ |
GET | Start interview |
/process/<id>/@<version>/ |
POST | Process form updates |
/reset/<id>/@<version>/ |
POST | Reset session |
/download/<id>/@<version>/ |
GET | Generate document |
/state/save |
GET | Save .vibestate file |
/state/load |
POST | Resume from .vibestate |
8. DEFINED TERMS SYSTEM¶
Purpose: Automatically extract defined terms, inject interactive tooltips into rendered HTML, and validate term usage for consistency.
Key File: vibe/document/defined_terms.py
Configuration: term_definitions: block in config.yml with keys enable (bool), validate (bool, requires enable), heading (str), whitelist (list). Resolved into frozen TermDefinitionsConfig dataclass.
Extraction: Two strategies -- regex-based Markdown extraction at startup (best-effort with Jinja tags), and HTML extraction at render time (accurate, post-Jinja). Host terms take precedence over component terms (first-occurrence-wins).
Inflection: _build_term_forms() generates locale-specific inflected forms (plural, definite, possessive, genitive) via LanguageRegistry. Multi-word terms inflect only the head noun.
Tooltip Injection: Wraps term occurrences in <span class="defined-term"> elements. Longest-match-first regex, skips code blocks/links/script tags.
Validation: Two checks producing ValidationIssue(severity="warning", source="term_defs"):
- Reverse check (all locales): every defined term must appear in the document body.
- Forward check (non-German): detects title-cased sequences that look like undefined terms.
Runs at startup (on raw template text) and at render time (on rendered HTML).
9. CONTRIBUTIONS SYSTEM¶
Purpose: Cross-cutting content routing allowing components to contribute content to named slots defined by the host template. Enables decoupled document assembly where components inject definitions, clauses, or other content into host-defined collection points.
Key Files: vibe/contributions/ package
Architecture: Two-pass marker-based resolution:
- Pass 1 (Jinja render):
{% contribute "slot_name" %}...{% endcontribute %}blocks capture content and register it with a request-scopedContributionManagerinstead of emitting inline.insert_contributions("slot_name")emits an HTML comment marker at the collection point. - Pass 2 (post-render):
resolve_markers()replaces markers with drained contribution content in document order.
Key Components:
ContributionManager(vibe/contributions/manager.py) -- request-scoped store with hierarchical scoping (appendix subtrees drain only their own contributions)ContributeExtension(vibe/jinja/contribute_ext.py) -- Jinja2 extension parsing{% contribute %}blocks (multilingual aliases)DefinitionExtension(vibe/jinja/definition_ext.py) --{% definition %}and{% term %}semantic markup, registers terms withDefinitionRegistryDefinitionRegistry(vibe/contributions/definitions.py) -- request-scoped term registry for tooltip matchingContributeSlotVisitor(vibe/static_analysis/visitors_extraction.py) -- AST visitor extracting slot graph for validation (contributed vs. collected slots)
Static Validation: The provider validates that every contributed slot has a corresponding collector; orphaned contributions produce warnings.
10. LINKED INTERVIEWS¶
Purpose: Allow one interview to launch another with pre-populated data via recommend() template function calls.
Data Flow:
- Source template calls
recommend("target_template_id", mapped_var=source_var)during rendering - AST validation (
RecommendTemplateVisitor) verifies target template IDs exist - Session stores
active_recommendationslist with target IDs, mappings, and snapshot data - Launch via URL query parameters (
recommendation_index,linked_from_template, etc.) - Target session receives
linked_data(source state under_linked.<source_template_id>) and explicit mappings resolved againstuses:declarations - Protection:
ValueSource.LINKEDvalues cannot be overwritten from form submissions
Session Fields: linked_from (source metadata), linked_bindings (data binding records), active_recommendations (available launch targets)
11. UTILITY MODULES¶
| Module | Location | Purpose |
|---|---|---|
| Request caching | vibe/utils/caching.py |
@request_cached decorator using Flask g |
| Form parsing | vibe/utils/form.py |
Parse flat HTML form data into nested structures |
| JSON serialization | vibe/utils/serialization.py |
safe_json_serialize with fallbacks |
| SSE formatting | vibe/web/sse.py |
SSEEvent, format_sse_event |
| HTMX utilities | vibe/web/htmx.py |
OOBSwap, render_oob_div |
| HTML fragments | vibe/web/core/html_fragments.py |
Common HTML patterns via Jinja |
| Developer mode | vibe/web/core/devel.py |
is_devel(), sticky session-based dev mode |
| YAML include | vibe/templates_mgmt/yaml_include.py |
Config inheritance via include: directive |
Server-Timing: Debug/test mode collects performance metrics via g.timings and emits Server-Timing HTTP headers.
12. FILE LOCATION INDEX¶
Core Probing¶
| What | Where |
|---|---|
| Core probe logic | vibe/probing/orchestrator.py::run_probe, ProbeOrchestrator, TrackingUndefined |
| Web probe wrapper | vibe/web/core/state_tracker.py::probe_template |
| Relevance determination (core) | vibe/probing/relevance.py::determine_relevant_questions_core |
| Relevance determination (web) | vibe/web/core/state_tracker.py::determine_relevant_questions |
| ProbeResult | vibe/probing/orchestrator.py::ProbeResult |
| Probe exceptions | vibe/probing/exceptions.py::ProbeMissingPathError, ProbeNeedsError |
Data Structures¶
| What | Where |
|---|---|
| NestedValue | vibe/nested_value.py::NestedValue + helpers |
| Path utilities | vibe/utils/path.py::parse_path, path_to_string |
| VibeContext & rendering | vibe/jinja/context.py::VibeContext, VibeProbeContext, vibe_render, make_docx_render_context |
| ValueSource, TemplateData | vibe/structures.py |
| Question definition models | vibe/runtime_models/definitions.py::QuestionDefBase, parse_question_def, def_attr |
Template Provider & VFS¶
| What | Where |
|---|---|
| Provider class | vibe/templates_mgmt/provider_core.py::TemplateDataProvider |
| Question placement | vibe/templates_mgmt/question_placement.py::collect_placements, resolve_placements |
| VirtualFileSystem | vibe/templates_mgmt/provider_vfs.py::VirtualFileSystem |
| Provider types | vibe/templates_mgmt/provider_types.py::ComponentSource |
| YAML include resolver | vibe/templates_mgmt/yaml_include.py::resolve_includes |
Handler System¶
| What | Where |
|---|---|
| Base class & registry | vibe/handlers/base.py::DataTypeHandler, HANDLER_REGISTRY |
| Render context | vibe/handlers/base.py::QuestionRenderContext |
| Factory | vibe/handlers/__init__.py::get_handler_for_definition |
| Handlers | vibe/handlers/{text,number,bool,enum,multichoice,list_handler,structured,computable,tristate,message,date,amount,period}.py |
Defined Terms¶
| What | Where |
|---|---|
| Config, extraction, injection, validation | vibe/document/defined_terms.py |
| Startup validation call | vibe/templates_mgmt/provider_core.py::_load_template |
| Render-time integration | vibe/web/core/rendering.py::render_preview |
| Inflection rules | vibe/linguistics/registry.py::LanguageRegistry, vibe/linguistics/base.py |
Contributions System¶
| What | Where |
|---|---|
| Manager & Contribution | vibe/contributions/manager.py::ContributionManager, Contribution |
| Marker resolution | vibe/contributions/resolution.py::resolve_markers, generate_marker |
| Definition registry | vibe/contributions/definitions.py::DefinitionRegistry |
| Contribute extension | vibe/jinja/contribute_ext.py::ContributeExtension |
| Definition extension | vibe/jinja/definition_ext.py::DefinitionExtension |
| Slot graph visitor | vibe/static_analysis/visitors_extraction.py::ContributeSlotVisitor |
| Recommend visitor | vibe/static_analysis/visitors_extraction.py::RecommendTemplateVisitor |
Behavioral Testing¶
| What | Where |
|---|---|
| Headless interview runner | vibe/testing/runner.py::HeadlessInterviewRunner |
| Test spec parser | vibe/testing/spec_parser.py::parse_test_spec, TestSpec |
| Assertions | vibe/testing/assertions.py::check_assertions |
| Pytest plugin | vibe/testing/pytest_plugin.py |
Session, Interview & Application¶
| What | Where |
|---|---|
| Session management | vibe/web/core/session_mgmt.py |
| Interview logic | vibe/web/interview_logic.py |
| Web routes | vibe/web/routes/{interview,download,persistence}.py |
| App factory | vibe/core.py::create_app, VibeFlask |
| Route decorator | vibe/web/decorators.py::route_setup |
| Data directory | vibe/infrastructure/data_directory.py::DataDirectoryManager |
| Template functions | vibe/component/::insert, need, show_message |
| Component operations | vibe/component/operations.py::InsertOperation, AppendixOperation |
| Component probing | vibe/component/probe.py |
| Component relevance | vibe/component/relevance.py |
| Validation | vibe/validation/validator.py::validate |
| Developer mode | vibe/web/core/devel.py::is_devel, set_devel_from_request |
Document Version: 6.0 Last Updated: 2026-03-31 Notes: Added contributions system (section 9), linked interviews (section 10), question placement system, ContributeSlotVisitor/RecommendTemplateVisitor, ValueSource.LINKED/JINJA_RESULT, component package split (operations/probe/relevance/cache)