Universal Launcher: Action Registry, Fuzzy Search, and Plugin System
The Portal Launcher is the single entry point for every user action on Portal OS — whether triggered by keyboard shortcut, touch gesture, or voice command. It unifies application launching, system controls, spatial dimension switching, web search, and PCP capability invocation under one searchable, ranked, and execution-safe interface. This page explains the three pillars of the launcher: the Action Registry that stores every discoverable action, the Fuzzy Search Engine that ranks them by relevance, and the Plugin System that allows third-party extensions without compromising security.
Architectural Overview
Section titled “Architectural Overview”The launcher is structured as a layered system where concerns are cleanly separated: providers discover and register actions, the registry stores them, the search engine ranks them, and the execution pipeline safely dispatches the chosen action to its target (PCP capability, D-Bus method, process spawn, or internal handler). A voice bridge sits alongside the pipeline to translate NLU intent classifications into the same action flow.
graph TB
subgraph "Action Discovery"
AP[App Provider<br/>.desktop files]
WP[Web Provider]
SP[Spatial Provider]
PP[PCP Provider]
PL[Plugin Loader<br/>TOML manifests]
end
subgraph "Registry Layer"
AR[Action Registry<br/>InMemoryRegistry]
AR --> |broadcast events| EV[RegistryEvent<br/>broadcast channel]
end
subgraph "Search Layer"
SE[Search Engine]
AI[Acronym Index]
SE --> AI
SE --> |Jaro-Winkler| FW[Field Weights<br/>name:0.5 kw:0.3 desc:0.2]
end
subgraph "Execution Pipeline"
R1[1. Resolve]
R2[2. Confirm]
R3[3. Execute]
R4[4. Grace Period]
R5[5. Audit]
R1 --> R2 --> R3 --> R4 --> R5
end
AP --> AR
WP --> AR
SP --> AR
PP --> AR
PL --> AR
AR --> |all_actions| SE
SE --> |SearchResult| EP[Execute Entry Point]
EP --> R1
R3 --> |PCP / D-Bus / Process / Internal| TGT[Execution Target]
R5 --> TM[Telemetry<br/>lock-free atomics]
VB[Voice Bridge<br/>IntentMap + DenyList] --> EP
style AR fill:#2d4a7a,color:#fff
style SE fill:#2d4a7a,color:#fff
style R3 fill:#3a6b3a,color:#fff
At the top level, the Launcher struct wires all components together and serves as the facade through which the launcherd daemon and any IPC clients interact. It holds the registry, search engine, execution pipeline, voice bridge, telemetry collector, persistent SQLite index, and provider list — all behind Arc shared references for thread-safe concurrent access.
Sources: portal/launcher/src/lib.rs#L46-L60, portal/launcher/src/facade.rs#L21-L64, portal/launcherd/src/main.rs#L19-L26
Action Registry: Central Action Store
Section titled “Action Registry: Central Action Store”The Action Data Model
Section titled “The Action Data Model”Every launchable operation in Portal OS is represented as an Action — a self-describing struct containing its identity, search metadata, execution target, confirmation policy, and usage statistics. The key fields are:
| Field | Type | Purpose |
|---|---|---|
id |
ActionId |
Globally unique identifier (category.provider.name) |
name |
String |
Display name shown in search results |
keywords |
Vec<String> |
Search keywords (name + aliases) |
category |
ActionCategory |
Grouping enum: App, System, Web, Spatial, Media, File, Pcp, etc. |
target |
ExecutionTarget |
How the action is dispatched: PCP, D-Bus, ProcessSpawn, Internal |
confirmation |
ActionConfirmation |
Voice-triggered confirmation tier |
base_priority |
f32 |
Static ranking weight (0.0–1.0) |
execution_count |
u64 |
Number of times executed (feeds frequency boost) |
last_executed_at |
Option<DateTime<Utc>> |
Last execution timestamp (feeds recency boost) |
The ActionId follows a hierarchical dot-separated convention: {category}.{provider}.{name}. At least three components are required, but the format intentionally permits four or more to support hierarchical names like system.display.brightness.set or pcp.pcp.weather.query. Each component must be lowercase alphanumeric with underscores — enforced at construction time by ActionId::new().
Sources: portal/launcher/src/action_registry/types.rs#L13-L98, portal/launcher/src/action_registry/types.rs#L220-L267
Action Categories and Confirmation Policies
Section titled “Action Categories and Confirmation Policies”The ActionCategory enum determines how actions are grouped in the UI and filtered during search. There are nine categories, covering everything from app launching to PCP-mirrored capabilities:
pub enum ActionCategory { App, Window, System, Web, Media, Spatial, File, Settings, Communication, Pcp,}Confirmation is governed by two separate policies working in concert:
| Policy | Applies To | Values | When Used |
|---|---|---|---|
ConfirmationPolicy |
Keyboard/gesture triggers | None, Destructive, SideEffect, System, VoiceApproval |
General UI execution |
ActionConfirmation |
Voice triggers only | AutoExecute, ConfirmOnVoice, AlwaysConfirm |
Voice bridge path |
For example, a volume-up action is ConfirmationPolicy::None and ActionConfirmation::AutoExecute — it fires instantly regardless of input modality. A shutdown action is ConfirmationPolicy::Destructive and ActionConfirmation::AlwaysConfirm — it requires explicit confirmation from every source and enters a 5-second grace period during which the user can cancel.
Sources: portal/launcher/src/action_registry/types.rs#L112-L137, portal/launcher/src/action_registry/types.rs#L140-L175
Registry Implementation: Thread-Safe In-Memory Storage
Section titled “Registry Implementation: Thread-Safe In-Memory Storage”The registry is backed by InMemoryRegistry, a parking_lot::RwLock<HashMap<ActionId, Arc<Action>>> with a tokio::sync::broadcast channel for change events. The RegistryHandle wraps this and provides a clean API surface — it is Clone, Send, and Sync, making it safe to share across async tasks.
Three traits define the registry contract:
ActionRegistry— Read operations:get(),contains(),all_actions(),actions_by_category(),actions_by_provider(),action_count()ActionRegistryMut— Write operations:register(),unregister(),register_batch(),clear()ActionRegistryEvents— Event subscription viampsc::Receiver<RegistryEvent>
Every mutation emits a RegistryEvent (ActionsChanged, ProviderRefreshed, or FullRebuild) through the broadcast channel. Subscribers receive these events asynchronously, enabling the search engine and UI to stay in sync with registry changes without polling.
Sources: portal/launcher/src/action_registry/registry/in_memory.rs#L17-L36, portal/launcher/src/action_registry/registry/mod.rs#L34-L60, portal/launcher/src/action_registry/registry/handle.rs#L17-L46
Action Providers: How Actions Enter the Registry
Section titled “Action Providers: How Actions Enter the Registry”Providers are the pluggable source layer — each implements the ActionProvider trait and registers its actions with the registry during launcher initialization. The trait defines a clear lifecycle:
sequenceDiagram
participant L as Launcher
participant P as ActionProvider
participant R as RegistryHandle
L->>P: register_actions(®istry)
P->>P: Scan data source (.desktop files, PCP, etc.)
P->>R: register(Arc<Action>) per action
R-->>P: (implicit, events broadcast)
P-->>L: Ok(count)
Note over L,R: Periodic or on-demand refresh
L->>P: refresh(®istry)
P->>R: unregister stale, register new
P-->>L: Ok((added, removed))
Note over L,R: Shutdown
L->>P: unregister_actions(®istry)
P-->>L: Ok(count)
Four built-in providers ship with the launcher, each responsible for a different category of actions:
| Provider | Source | Example Actions |
|---|---|---|
AppProvider |
.desktop file parsing |
app.app.firefox.open, app.app.firefox.close |
WebProvider |
Hardcoded web search action | web.web.search |
SpatialProvider |
Spatial dimension state | spatial.spatial.dimension.switch |
PcpProvider |
PCP capability registry | pcp.pcp.{app}.{action} |
The PCP Provider deserves special attention: it mirrors the Portal Capability Protocol’s capability registry into the launcher. Each PCP capability becomes a searchable action, with confirmation policy derived from the PCP domain — System capabilities get AlwaysConfirm, Compositor capabilities get ConfirmOnVoice, and App capabilities get AutoExecute. This means any application that registers a PCP capability automatically becomes launchable through the launcher.
Sources: portal/launcher/src/providers/mod.rs#L27-L78, portal/launcher/src/providers/pcp.rs#L14-L49, portal/launcher/src/providers/app/mod.rs#L1-L30, portal/launcherd/src/main.rs#L19-L26
Fuzzy Search Engine: Ranking Actions by Relevance
Section titled “Fuzzy Search Engine: Ranking Actions by Relevance”Search Flow
Section titled “Search Flow”When the user types a query, the search engine processes it through a multi-stage pipeline that short-circuits at the earliest possible match:
flowchart TD
Q[User Query] --> E{Empty?}
E -->|Yes| ER[Return empty]
E -->|No| CALC{Calc/Convert<br/>pattern?}
CALC -->|Yes| WR[Web reroute<br/>score: 1.0]
CALC -->|No| AC{Acronym<br/>exact match?}
AC -->|Yes| AS[Score & return<br/>MatchType::Exact]
AC -->|No| AP{Acronym<br/>prefix match?}
AP -->|Yes| APS[Field score + boost<br/>truncate & return]
AP -->|No| FS[Full fuzzy search]
FS --> F1[Compute field scores<br/>name, keywords, description]
F1 --> F2[Apply context boosts]
F1 --> F3[Composite score:<br/>fuzzy×text + priority + freq + recency + ctx]
F3 --> F4{Score ≥ threshold?}
F4 -->|No| FILTER[Drop]
F4 -->|Yes| KEEP[Keep]
KEEP --> SORT[Sort by score desc]
SORT --> TRUNC[Truncate to limit]
The engine first checks for calculator and currency conversion patterns using compiled regexes — if the query matches ^\d+[\+\-\*\/\%]\d+ or a currency conversion like 100 usd to eur, it immediately returns a web search reroute result rather than searching the action registry. This provides instant “type-to-calculate” behavior.
Sources: portal/launcher/src/search_engine/search.rs#L16-L78, portal/launcher/src/search_engine/mod.rs#L21-L28
Field-Weighted Scoring with Jaro-Winkler
Section titled “Field-Weighted Scoring with Jaro-Winkler”For each candidate action, the engine computes a text similarity score across three fields — name, keywords, and description — using the Jaro-Winkler string similarity algorithm from the strsim crate. Each field is checked in priority order:
- Exact match (score: 1.0) — query equals field text
- Prefix match (score: 0.9) — field starts with query or vice versa
- Fuzzy match — Jaro-Winkler similarity (0.0–1.0)
The best match kind across all fields is tracked, and the final weighted score is:
score = (weight_name × name_score) + (weight_keyword × keyword_score) + (weight_description × desc_score)Default field weights are name: 0.5, keyword: 0.3, description: 0.2 — giving the action’s display name the highest influence on ranking.
Sources: portal/launcher/src/search_engine/ranking/scoring.rs#L47-L115, portal/launcher/src/search_engine/ranking/mod.rs#L12-L17
Composite Ranking: Beyond Text Similarity
Section titled “Composite Ranking: Beyond Text Similarity”Text similarity alone is not enough — the launcher needs to surface frequently-used actions and account for contextual signals. The composite score formula combines five weighted components:
| Component | Weight (Default) | Formula | Purpose |
|---|---|---|---|
| Text (fuzzy) | 0.5 | weight_fuzzy × field_weighted_score |
Query relevance |
| Base Priority | 0.2 | weight_priority × action.base_priority |
Static importance |
| Frequency | 0.1 | weight_frequency × time_decay_frequency(...) |
Usage history (decaying) |
| Recency | 0.1 | weight_recency × recency_boost(...) |
Recent usage bonus |
| Context | 0.1 | Sum of matching RankingBoost values |
Situational relevance |
The frequency component uses exponential time decay: count × 2^(-elapsed_days / half_life) with a 30-day half-life. This means an action executed 100 times a month ago contributes roughly the same boost as one executed 50 times today — preventing stale high-count actions from dominating.
The recency boost is linear, decaying from a maximum of 0.3 to zero over a 7-day window. This provides a gentle “recently used” nudge without overwhelming the frequency signal.
All five weights must sum to approximately 1.0 (validated at configuration load time with a ±0.05 tolerance).
Sources: portal/launcher/src/search_engine/search.rs#L192-L203, portal/launcher/src/search_engine/ranking/scoring.rs#L117-L160, portal/launcher/src/config/defaults.rs#L25-L42, portal/launcher/src/config/mod.rs#L164-L186
Acronym Index: Quick Path for Common Abbreviations
Section titled “Acronym Index: Quick Path for Common Abbreviations”The AcronymIndex builds a lookup table from the first letters of each word in action names. For example, “Display Brightness Control” generates the acronym “dbc”. When the user types “dbc”, the search engine can bypass the full fuzzy scan and return the matching action with MatchType::Exact — significantly faster than Jaro-Winkler over the entire registry.
The index limits acronyms to the first five words of each action name to avoid overly long keys. It also supports prefix matching: typing “db” will match any acronym starting with those letters.
Sources: portal/launcher/src/search_engine/acronym.rs#L9-L79, portal/launcher/src/search_engine/search.rs#L42-L78
Context Boosts: Situational Ranking Adjustments
Section titled “Context Boosts: Situational Ranking Adjustments”The RankingBoost mechanism allows external systems (like the Context Engine) to temporarily elevate or suppress certain actions based on the user’s current situation. Each boost specifies:
- An
action_id_patternusing component-wise glob matching (e.g.,system.*.volume.*matches any volume action) - An optional
categoryfilter - An optional
keyword_matchfilter - A
boostvalue (positive or negative) - A
ttl(time-to-live) with automatic expiry
For example, if the Context Engine detects that the user is in a spatial VR session, it might submit a RankingBoost with pattern spatial.*.*, boosting all spatial actions by +0.3 for the next hour. Expired boosts are automatically filtered out during scoring.
Sources: portal/launcher/src/search_engine/ranking/boost.rs#L1-L145, portal/launcher/src/search_engine/ranking/scoring.rs#L162-L171
Plugin System: Extensible Without Compromise
Section titled “Plugin System: Extensible Without Compromise”Plugin Manifest Format
Section titled “Plugin Manifest Format”Third-party plugins are defined by TOML manifest files placed in configurable directories (default: ~/.config/portal/launcher/providers/ and /etc/portal/launcher/providers/). Each manifest contains three sections:
[manifest]id = "vendor.weather" # Format: {vendor}.{name}name = "Weather"version = "1.0.0"description = "Weather plugin"author = "Vendor"
[execution]type = "pcp" # "pcp" or "dbus" (NOT "process")capability = "weather.query" # Required for "pcp" type
[permissions]capabilities = ["weather.read"]domains = ["weather"]
[[actions]]id = "weather.query"name = "Check Weather"description = "Get current weather conditions"category = "system"Plugins cannot spawn arbitrary processes. The "process" execution type is explicitly rejected during manifest validation — only the built-in providers retain that privilege. This is a deliberate security boundary: plugins can invoke PCP capabilities or call D-Bus methods, but they cannot execute binaries directly.
Sources: portal/launcher/src/plugin_system/manifest.rs#L1-L147, portal/launcher/src/config/defaults.rs#L96-L107
Plugin ID Validation
Section titled “Plugin ID Validation”Plugin IDs follow a stricter convention than action IDs: exactly two dot-separated components (vendor.name), both lowercase alphanumeric with underscores. The vendor segment establishes a namespace that prevents collisions between different plugin authors. For example, vendor.weather and acme.weather can coexist in the same directory.
Sources: portal/launcher/src/plugin_system/manifest.rs#L126-L147
Discovery and Loading
Section titled “Discovery and Loading”The plugin lifecycle follows a discover → validate → load pattern:
flowchart LR
A[Scan .toml files<br/>in manifest dirs] --> B[Parse TOML]
B -->|Valid| C[Validate ID format]
B -->|Invalid TOML| D[Skip, log error]
C -->|Valid| E[PluginInfo loaded]
C -->|Invalid ID| D
E --> F[Semaphore(4)<br/>parallel loading]
F --> G[Insert into<br/>RwLock<HashMap>]
The PluginLoader uses a tokio::sync::Semaphore(4) to bound concurrency during parallel loading — filesystem I/O happens in spawn_blocking tasks to avoid blocking the async runtime. Invalid manifests are silently skipped (logged at warn level); they never prevent other plugins from loading.
The loader supports three runtime operations:
| Operation | Method | Behavior |
|---|---|---|
| Full load | load_plugins() |
Scans all directories, loads all valid manifests |
| Hot-reload | reload_plugin(id) |
Re-scans for a specific plugin ID, replaces entry |
| Unload | unload_plugin(id) |
Removes from loaded set |
Sources: portal/launcher/src/plugin_system/discovery.rs#L19-L44, portal/launcher/src/plugin_system/loader.rs#L16-L141
Permission Gating
Section titled “Permission Gating”Every plugin must declare its required capabilities and domains in the [permissions] section. The check_permission() function enforces a two-check policy: both the capability and the domain must be explicitly listed. If either is missing, execution is denied with a PermissionDenied error that includes the plugin ID and the missing permission.
| Check | Example | Result |
|---|---|---|
| Capability + domain both present | capabilities=["network"], domains=["weather"] → check("network", "weather") |
✅ Ok |
| Capability missing | check("bluetooth", "weather") |
❌ PermissionDenied |
| Domain missing | check("network", "bluetooth") |
❌ PermissionDenied |
Sources: portal/launcher/src/plugin_system/permissions.rs#L15-L35
Execution Pipeline: Safe Action Dispatch
Section titled “Execution Pipeline: Safe Action Dispatch”Five-Stage Pipeline
Section titled “Five-Stage Pipeline”When a user selects an action from search results, it enters the DefaultExecutionPipeline — a five-stage ordered process that resolves parameters, checks confirmation requirements, dispatches to the execution target, manages grace periods, and records telemetry:
flowchart TD
S1[Stage 1: Resolve] --> |"Registry.get(action_id)"<br/>Merge default + user params<br/>Determine target<br/>Check confirmation| S2[Stage 2: Confirm]
S2 -->|"requires_confirmation?"| Q{Needs confirm?}
Q -->|Yes| CB[Call ConfirmationCallback]
CB -->|Confirmed| S3
CB -->|Denied| PC[Store PendingConfirmation<br/>Return error]
Q -->|No| S3[Stage 3: Execute]
S3 --> PCP{Target type}
PCP -->|PcpCapability| PE[PCP Executor]
PCP -->|DbusMethod| DB[D-Bus method call]
PCP -->|ProcessSpawn| PS[Process spawn<br/>allowlist + SHA-256]
PCP -->|Internal| IN[Internal handler]
S3 --> S4[Stage 4: Grace Period]
S4 --> |"AlwaysConfirm only<br/>5-second cancel window"| S5[Stage 5: Audit]
S5 --> TM[Telemetry.record_execution]
Sources: portal/launcher/src/execution/pipeline/execute.rs#L18-L91, portal/launcher/src/execution/pipeline/stages.rs#L12-L41
Execution Targets
Section titled “Execution Targets”The ExecutionTarget enum defines four dispatch paths, each with its own security considerations:
| Target | Available To | Security Measures |
|---|---|---|
PcpCapability |
Built-in providers + plugins | PCP domain-based permission checking |
DbusMethod |
Built-in providers + plugins | Whitelist of bus names (e.g., org.freedesktop.login1) |
ProcessSpawn |
Built-in providers only | Binary allow-list file + optional SHA-256 sidecar verification |
Internal |
Built-in providers | No external side effects |
The ProcessSpawn path enforces two layers of security: the binary must appear in /etc/portal/launcher-allowlist.conf, and if a .sha256 sidecar file exists next to the binary, the hash is verified before execution. Environment variables injected from action parameters are restricted to an allow-list of keys (url, query, content, target, direction, amount, exec, terminal, app_id). URL parameters are validated to accept only http and https schemes.
Sources: portal/launcher/src/action_registry/types.rs#L182-L218, portal/launcher/src/execution/pipeline/stages.rs#L44-L200, portal/launcher/src/execution/pipeline/security.rs#L9-L98
Grace Periods for Destructive Actions
Section titled “Grace Periods for Destructive Actions”Actions tagged with ActionConfirmation::AlwaysConfirm enter a 5-second grace period after execution. During this window, the GracePeriodManager tracks the action by ActionId and Instant. The user (or a voice command) can call cancel_grace_period() — if the window hasn’t expired, the action is considered reversible.
A background cleanup task runs every 60 seconds to sweep expired grace periods, preventing unbounded memory growth. The Launcher::initialize() method spawns this task, and Launcher::shutdown() aborts it.
Sources: portal/launcher/src/execution/confirm.rs#L41-L117, portal/launcher/src/facade.rs#L102-L114
Configuration System
Section titled “Configuration System”The launcher reads a TOML configuration file (default path: /etc/portal/launcher.toml) that controls search weights, execution policies, UI appearance, and plugin directories. Configuration is validated at load time — search weights must sum to ~1.0, min_score_threshold must be 0.0–1.0, and max_results must be positive.
| Config Section | Key Defaults | Controls |
|---|---|---|
search |
weight_fuzzy: 0.5, weight_priority: 0.2, weight_frequency: 0.1, weight_recency: 0.1, weight_context: 0.1 |
Ranking weights, fuzzy/acronym toggles |
execution |
voice_confirmation_policy: VoiceApproval, max_concurrent: 10, destructive_grace: 5s |
Confirmation, concurrency, grace period |
ui |
visible_results: 12, theme: dark, font_scale: 1.0 |
Desktop UI appearance |
ui.glasses |
visible_results: 8, font_scale: 1.2, auto_dismiss: 10s |
AR glasses display adaptation |
providers |
plugins_enabled: true, 2 default directories |
Plugin discovery paths |
web |
search_engine_url: duckduckgo.com, browser: firefox |
Web search rerouting |
If the config file is missing or invalid, the launcher gracefully falls back to LauncherConfig::default() — it never fails to start due to configuration issues.
Sources: portal/launcher/src/config/mod.rs#L12-L200, portal/launcher/src/config/defaults.rs#L1-L140, portal/launcherd/src/main.rs#L77-L95
Voice Bridge: Intent to Action
Section titled “Voice Bridge: Intent to Action”The voice subsystem integrates with the launcher through the DefaultVoiceBridge, which translates NLU intent classifications (from Elara’s MiniLM classifier) into launcher actions. The bridge contains four components:
-
IntentMap — 30 hardcoded intent →
ActionIdmappings across four domains (App, Window, System, Media). Three mapping types:Fixed(direct),TargetDependent(template with{target}slot), andNotMapped(reserved for V2.1). -
SlotResolver — Converts
IntentSlots(extracted entities from the voice transcript) into action parameters. For example, the slottarget: "firefox"in anapp.openintent resolves to the action IDapp.app.firefox.open. -
DenyListChecker — Rejects transcripts containing dangerous phrases (e.g., “shut down”, “factory reset”, “uninstall”) before any action resolution occurs.
-
TtsQueue — Queues text-to-speech feedback for voice-initiated executions.
Sources: portal/launcher/src/voice_bridge/mod.rs#L1-L94, portal/launcher/src/voice_bridge/intent_map.rs#L1-L80, portal/launcher/src/config/defaults.rs#L119-L139
Telemetry: Lock-Free Metrics
Section titled “Telemetry: Lock-Free Metrics”All launcher metrics are collected via AtomicTelemetry — a lock-free implementation using Rust atomics. This design ensures that metrics collection never blocks the search or execution hot paths. The telemetry trait captures:
- Search queries (count, result count, latency)
- Search selections (query, position, total results) and abandonments
- Action executions (action ID, source, success/failure, latency)
- Voice resolution outcomes (intent type, NLU classification, slot resolution, execution)
- Provider registration counts
- Index operation latencies
All data stays on-device — nothing leaves the system. Snapshots may contain slightly stale data due to the lock-free design, but this is an acceptable trade-off for zero-latency collection.
Sources: portal/launcher/src/telemetry/mod.rs#L17-L72, portal/launcher/src/execution/audit.rs#L9-L16
Home View and Suggestions
Section titled “Home View and Suggestions”When the launcher opens without a query, it shows a frequency-recency blended view of the most likely actions. Unlike search (which uses text similarity), the home view ranks purely by how often and how recently each action was used:
score = weight_recency × exp(-elapsed_secs / half_life_secs) + weight_frequency × (execution_count / max_execution_count)This provides a personalized “most recently used” experience that adapts to the user’s patterns without any text input.
Sources: portal/launcher/src/facade_home.rs#L13-L69
Suggested Reading
Section titled “Suggested Reading”Now that you understand how the launcher discovers, ranks, and dispatches actions, these related pages provide deeper context:
- Portal Capability Protocol (PCP): Architecture, Registry, and Daemon — How the
PcpProvidermirrors PCP capabilities as launcher actions, and how the execution pipeline dispatches to PCP viaPcpExecutor. - Context Engine: Event Ingestion, Decision Making, and Template Synthesis — How the Context Engine generates
RankingBoostvalues that the search engine applies to influence ranking. - Voice Pipeline: VAD, STT (sherpa-onnx), NLU (MiniLM), and TTS (Elara VITS) — How voice intents are classified and fed into the
VoiceBridgefor action resolution. - Shell, Style, and Design Token System — How the launcher UI renders search results and confirmation dialogs on both desktop and AR glasses displays.