# Alma Active Roadmap
Completed roadmap history lives in `archive/todos.md`. Keep this file focused
on active work, open design gaps, and the next slice of implementation.
## Plugin Runtime
- [x] Build the first visible proposal lane.
- Scope: a plugin observes a buffer snapshot, proposes a
`buffer.propose_edit` change against a base revision, and Alma shows the
proposal before mutation.
- Current state: a real component fixture observes a host-issued buffer
snapshot, proposes a revision-guarded edit, reaches `PluginIntentQueue`,
enters a typed proposal lane, and mutates only through the buffer owner.
The default proposal policy still auto-applies for compatibility. Manual
review mode stores pending proposals until an explicit apply or reject
request. Proposal lane saturation emits a redacted operational diagnostic. A
first chrome summary renders pending proposals with proposer identity,
capability, target shape, base revision, redacted edit shape, and a
redacted one-hunk diff preview. Chrome apply/reject controls emit the
existing typed proposal request messages. A bounded in-session receipt log
now records proposal id, proposer, capability, target, base revision,
redacted edit shape, and apply, reject, owner-accept, or owner-reject
outcome. Chrome now renders pending status and latest receipt outcome status
without exposing proposed text or raw ECS ids.
- UI: proposal status renders in the proposal lane.
- Owner path: apply routes through the buffer owner, stale proposals are
rejected at the owner boundary, and rejection never mutates text.
- Receipt: receipt status renders in chrome from the bounded receipt log.
- [x] Add runtime abuse tests around resource limits and message bounds.
- Existing key types: `PluginRuntimeLimits`, `PluginRuntimeSpec`,
`PluginHostImportSession`, `PluginHandleStore`, `WitCapability`.
- Current state: real Wasm component fixtures cover Wasmtime fuel exhaustion,
wall-clock timeout, malformed generated handle payloads, invalid UTF-8 guest
strings, oversized host-call payloads, and stale handles after discardable
effects have been queued. Generated `workspace.artifact_write` fixture
coverage proves invalid workspace paths discard queued workspace I/O before
filesystem policy execution.
- Remaining fixture: none for exposed host imports.
- Acceptance: every failed guest update discards pending effects and pending
workspace I/O before ECS publication or filesystem policy execution.
- [ ] Add guest-driven scheduling integration tests around `PluginIntent`.
- Existing key types: `EditorSet::PluginIntent`, `PluginInstanceState`,
`PluginHostImportSession`, `PluginIntentQueue`,
`RevisionGuardedBufferEditRequested`, `StatusMessageRequested`.
- Current state: ECS integration tests cover accepted publication into owner
systems, missing targets, stale revisions, FIFO queue drain, queue
saturation, runtime-denied capability before publication, stale handle
rejection before effect creation, generated `status.publish` and
`buffer.propose_edit` host import adapters queuing only through the active
update session, and a real Wasm component fixture publishing status through
runtime update. A real `buffer.propose_edit` component fixture now publishes
through `PluginIntentQueue`, reaches the buffer owner, and preserves
deterministic FIFO ordering across runtime-produced batches from multiple
plugins. Wasmtime update setup now consumes one active-update proof that
captures host import authority and update handles after lifecycle gating, so
missing handles fail before guest execution or session creation.
- Remaining fixtures: none before `buffer.observe`; scheduling/subscription
fixtures resume once observation events exist.
- Acceptance: rejected guest work produces no authoritative mutation, and
accepted work still reaches only existing owner systems.
- [x] Make `PluginIntentQueue` capacity configurable from validated runtime
configuration.
- Current state: `PluginRuntimeLimits` validates `max_intent_batches`, and
the ECS queue derives its cap from validated enabled-plugin runtime proofs.
- Acceptance: invalid zero queue limits fail during config validation, and
the ECS resource is initialized from a validated proof type.
- [x] Add a first Wasmtime adapter boundary behind `plugin-runtime`.
- Existing key types: `PluginRuntimeSpec`, `PluginInstanceState`,
`PluginHostContext`, `PluginHostImportSession`, generated bindings in
`plugin::bindings`.
- Current state: component validation, lifecycle calls, resource limits,
timeout handling, discard evidence, generated `status.publish`,
`buffer.observe`, `buffer.propose_edit`, and `workspace.artifact_write`
host import adapters, and real component fixtures for accepted and denied
status publication, buffer observation, buffer edit proposals, and
workspace artifact writes exist.
- Remaining scope: none for the first adapter boundary. Next runtime work is
abuse-test coverage and then the first useful observe-plus-propose plugin.
- Acceptance: generated WIT types remain private, all guest strings and
handles are decoded with `TryFrom`-style failures, and traps/timeouts or
import rejections discard pending work.
- [x] Split plugin docs once the runtime adapter lands.
- Current state: `docs/plugins/runtime.md`, `docs/plugins/security.md`, and
`docs/plugins/testing.md` now hold the detailed plugin runtime records.
- Target files: `docs/plugins/runtime.md`, `docs/plugins/security.md`, and
`docs/plugins/testing.md`.
- Acceptance: the top-level architecture stays short, while plugin security
invariants, runtime dataflow, and test obligations remain auditable.
- [x] Audit checked-in plugin goldens.
- Current state: `tests/goldens/plugin` contains the checked-in config,
manifest, and schema fixtures. `tests/plugin_schema.rs` runs as a normal
Cargo integration test and now enforces required coverage labels, rejects
orphan JSON fixtures, validates accepted and rejected fixtures through the
checked-in schemas and typed Rust loaders, checks both schemas against
`CURRENT_WIT_WORLD`, checks capability vocabulary drift, and checks config
runtime-limit maxima against Rust host caps.
- Next extension: add runtime replay goldens only after choosing a stable
redacted trace format for update inputs, emitted effects, workspace I/O,
operational events, and proposal receipts.
## Vim And Editor Core
- [ ] Decide whether stored cursor coordinates should become typed.
- Current state: cursor move requests distinguish normal cursor cells from
insert caret boundaries, while `CursorPosition` stores a shared byte index.
- Gap: public request types are safer than stored view state, but future
features such as replace mode, mouse placement, and plugin-originated
cursor effects may benefit from a typed stored coordinate.
- [ ] Finish richer insert-mode command coverage.
- Candidate commands: Delete, Ctrl-W, Ctrl-U, Tab, indentation, completion,
replace mode, and arrow-key movement.
- Acceptance: raw text mutation remains in the insert adapter, payloads stay
bounded, and owner systems preserve UTF-8 boundary checks.
- [ ] Define undo transaction grouping for insert sessions and plugin proposals.
- Current state: undo exists, but proposal and insert transaction boundaries
need explicit policy before broad repeat or macro support.
- Acceptance: one logical user or plugin action maps to one replayable undo
record unless a typed policy says otherwise.
## Cross-Cutting Security
- [x] Define the repo-wide operation error taxonomy before adding plugin error envelopes.
- Current state: `error.rs` files already favor typed enums and `thiserror`
over boxed public errors. Filesystem and config errors may include escaped
user-facing paths, while ECS and plugin owner boundaries adapt lower errors
into redacted shapes. `ecs::events::operation` now owns shared
owner-boundary failure classes and redacted lower-source shapes, with
command diagnostics re-exporting command-local aliases.
- Target style: keep boundary-specific error enums, add small operation
envelopes only where they preserve failure phase information, and avoid a
single catch-all app error.
- Plugin candidate: model load, update, or workspace execution with small
operation envelopes only where a caller would otherwise lose policy,
decode, authorization, lifecycle, runtime, timeout, or queue-saturation
phase information.
- Acceptance: callers can match exact causes, `source()` preserves useful
lower errors where safe, plugin/runtime `Debug` and `Display` stay
shape-only, and no public boundary uses `Box<dyn Error>` as its primary
type.
- [ ] Add redacted diagnostics for future runtime execution failures.
- Scope: trap, timeout, malformed guest handle, malformed guest string,
denied capability, stale handle, and over-limit queue rejection.
- Current state: timeouts and capability denials emit redacted operational
events. Wasmtime host-import failures now retain the generated import name
through a closed diagnostic vocabulary and map non-authorization failures
to closed rejection shapes for malformed guest data, stale or invalid
handles, resource lookup failures, missing observed revisions, and bounded
queue rejection. Guest traps now emit redacted operational events with a
closed lifecycle-export vocabulary. Lower-level Wasmtime failure detail now
uses a closed failure-class vocabulary instead of classifier strings.
- Acceptance: user-facing diagnostics disclose stable identity and closed
reason shape only, not raw guest payloads, host paths, buffer text, or OS
strings.
- [ ] Keep supply-chain policy current as runtime execution becomes real.
- Current tracked risk: `block 0.1.6` appears through the Bevy/wgpu/Metal
stack in future-incompatibility reports.
- Acceptance: runtime dependency changes update `docs/supply-chain.md` before
new plugin execution paths are enabled by default.
## Acceptance Bar
- Pure behavior has unit or property tests before ECS wiring.
- New ECS systems are placed in existing `EditorSet`s with explicit ordering.
- No plugin path bypasses `fs_utils` or existing owner mutation boundaries.
- Runtime limits, queue limits, and payload limits are validated before use.
- Diagnostics stay redacted and shape-based at untrusted boundaries.
- Comments in touched files stay laconic and assume a senior Rust reader.