alma 0.1.1

A Bevy-native modal text editor with Vim-style navigation.
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
# Plugin Runtime

Alma plugins are untrusted Wasm components. The runtime is a mediation layer,
not an editor owner. It validates static input, constructs authority proofs,
runs bounded guest updates, and publishes only typed proposals to existing
owners.

The v1 product goal is local Wasm plugins that can observe editor state and
propose bounded work without compromising editor correctness, local files, user
text, or UI responsiveness. Default builds and default configs remain
plugin-runtime-free and default-deny.

## Status

Implemented:

- static registry config, plugin identity validation, component path shape
  validation, manifest parsing, and effective grant projection
- explicit whole-workspace grant spelling and workspace-relative grant
  validation
- runtime limit validation with closed field diagnostics, including a
  host-sized non-zero sealed-batch cap for registry-level `PluginIntentQueue`
  scheduling
- policy-opened manifest and component byte tokens
- typed WIT host-import metadata for exposed import name, capability atom, and
  redacted operational class
- closed guest-decode field vocabulary for generated-to-Alma validation
  diagnostics at host-import boundaries
- public task-based `workspace.observe` start/poll/take WIT imports, including
  an opaque task resource, closed poll/take result variants, redacted
  operational import classes, and drift coverage proving the WIT has no
  blocking read import and no partial task group
- host-owned buffer and view handles with generation invalidation and
  live-handle limits
- borrowed WIT resources for update-scoped view and buffer authority, resolved
  through store-local Wasmtime `ResourceTable` lookup
- typed Wasmtime update-resource reps for view and buffer resources, so
  guest-call borrows, cleanup, and setup rollback cannot swap resource kinds by
  raw table-index convention
- shared host authority proof for per-plugin identity and effective
  capabilities, reused by live contexts and per-update snapshots
- per-update host import sessions with discardable effect and workspace I/O
  batches
- Wasmtime component validation, loading, lifecycle calls, fuel limits,
  shared epoch-driven wall-clock timeouts, memory limits, and message-size
  limits behind `plugin-runtime`, split under `runtime/wasmtime/` by adapter,
  store/import state, resource-table vocabulary, workspace observe-task
  resources, scheduled-update proofs, execution guards, errors, and tests
- generated `status.publish`, `buffer.observe`, `buffer.propose_edit`,
  task-based `workspace.observe`, and `workspace.artifact_write` host import
  adapters
- typed Wasmtime failure phases for redacted outer diagnostics, while exact
  runtime errors retain their source enums
- adapter-local Wasmtime host-import rejection envelopes that keep the first
  redacted import class paired with its typed source error
- closed Wasmtime failure classes for redacted lower-level runtime detail
- closed operational runtime-failure classes, including canonical ABI
  post-return cleanup
- closed host-import diagnostic names for Wasmtime operational events
- revision-guarded plugin buffer edit proposals that reach the buffer owner
  through `PluginIntentQueue`
- retry-safe `PluginIntentQueue` admission: saturation returns the closed
  queue rejection with the still-sealed effect batch for retry or explicit
  redacted discard, and its consuming split returns named queue-error and
  batch fields
- empty sealed effect, workspace I/O, and workspace observe-task batches are
  no-op scheduler admissions; they do not consume bounded queue capacity or
  emit saturation diagnostics
- a typed proposal lane for plugin buffer edit proposals, with compatibility
  auto-apply and explicit manual apply/reject request paths
- closed error-kind vocabularies for plugin intent queue, proposal lane,
  proposal decision, and proposal receipt-log diagnostics
- per-plugin config policy for buffer edit proposal review, defaulting to
  `auto_apply` and allowing explicit `manual_review`
- buffer edit proposal provenance and receipts whose proposal-specific
  capability type is backed by `CapabilityAtom`
- capability atoms that own stable spellings, authorization-ref path arity, and
  redacted shapes for WIT and host authorization adapters
- a first visible chrome summary for pending proposals, using redacted edit
  shape and no raw ECS ids
- a redacted one-hunk diff preview for the first pending proposal
- chrome apply/reject controls that emit typed proposal request messages
- bounded in-session proposal receipts for proposal-lane rejection,
  buffer-owner acceptance, and buffer-owner rejection
- chrome proposal status for pending proposals and the latest retained receipt
- real observe-plus-propose component coverage through the runtime, intent
  queue, and buffer owner
- real workspace artifact-write component coverage through the runtime and
  deferred workspace I/O boundary
- a single active-update scheduling proof consumed by Wasmtime update setup
- store-local Wasmtime active update state that pairs the host import session
  with the rooted update resources it must clean up after guest return
- store-local Wasmtime workspace observation task state that pairs the task
  queue, persistent task resources, and active-update task resource reps; the
  reps are typed inside the adapter, and the persistent-resource cap is a
  non-zero proof derived from the same queue limit as task scheduling
- host-import snapshot construction rejects host grants and handle stores from
  different plugin identities
- Wasmtime update setup rejects nested active sessions instead of relying on a
  debug assertion
- `PluginHostImportError` owns the closed operational rejection class for
  non-authorization import failures; authorization failures continue to emit
  denied-import events
- operation-typed workspace I/O execution completions with distinct read and
  write success/error result types
- workspace I/O success accessors for deliberate owner/user surfaces, with
  debug output reduced to redacted operation and length shapes
- bytes-only `workspace.observe` delivery projection from read completions,
  keeping guest-facing read results separate from owner-facing display path and
  filesystem error metadata
- a redacted `workspace.observe` delivery shape used by task result debug and
  runtime trace adapters, so byte payloads are not inspected at later
  diagnostic boundaries
- direct host-session workspace observations that require explicit
  `FilesystemConfig`, authorize through captured plugin authority, read through
  the pending workspace I/O ledger and `fs_utils`, return only
  `PluginWorkspaceObserveOutcome`, spend the per-update workspace request
  budget, do not enqueue deferred workspace I/O, and remain plugin-internal;
  public guest reads use the task/result ABI instead
- shared workspace request-budget accounting for deferred workspace I/O, direct
  host-session observations, and task-style observation reservations
- deferred workspace I/O request counts derive from the pending batch's
  retained operations instead of a second mutable ledger counter; the shared
  ledger owns identity, budget, and non-deferred charges
- task-style workspace observation reservations reject paired workspace I/O
  ledgers from other plugin identities before charging budget or reserving a
  task id
- workspace I/O and observe-task queue admission errors expose closed error
  classes and closed mismatch source vocabularies for access-proof,
  request-ledger, identity, and queue reservation failures
- workspace request-budget, pending-effect, intent queue, proposal lane,
  observe-task pending-capacity, workspace worker, and operational queue
  saturation diagnostics carry the validated non-zero cap proof internally
  while preserving the existing redacted display and event text
- workspace read/write access proofs retain the issuing `PluginIdentity`;
  filesystem-policy tokens stay internal to `workspace_io`, and pending
  workspace I/O rejects access proofs from a different plugin identity before
  any filesystem policy execution
- a runtime-owned workspace observation task queue with non-zero host task ids,
  bounded pending reads, bounded retained results, identity-scoped poll/take,
  FIFO filesystem-policy execution, bounded single-task and capped batch
  execution, an explicitly named all-task drain for callers that choose
  unbounded execution, retention eviction, revocation cleanup, and
  pending-capacity plus non-reused task-id reservation before guest-visible
  return, with queue debug output reduced to counts
- pending and sealed workspace observation task batches in the host-import
  session. Failed updates discard task requests, while successful updates can
  enqueue sealed task batches with already-reserved ids all-or-nothing before
  the task queue performs any filesystem-policy work. The host session returns
  one resource-authority proof that pairs the identity-scoped handle with the
  workspace path authorized for later poll/take revalidation. The public start
  import returns the identity-scoped handle as an opaque WIT resource. Dropping
  that resource before successful guest return removes the uncommitted task
  request and releases its pending-capacity reservation. Batch debug output is
  count-shaped; task handles remain behind explicit accessors.
- pending effect batch limit field and rejection-class vocabulary for closed
  host-import diagnostics
- workspace observation task requests retain the producing update's non-zero
  read byte cap, so later queue execution cannot widen the result bound by
  caller convention.
- workspace read and write execution paths accept non-zero byte cap proofs
  owned by the workspace I/O budget boundary instead of raw numeric
  conventions.
- deferred workspace artifact writes retain a bounded payload proof after
  queue admission, so pending and sealed write work cannot carry an over-budget
  payload by internal convention.
- host queues, handle stores, ledgers, and pending batches consume validated
  limit and budget proofs directly; zero-limit validation stays at proof
  constructors, and constructors that receive those proofs are infallible.
- paired host-import, post-update scheduling, and scheduled owner-publication
  proof constructors enforce same-plugin identity in release builds before
  constructing the proof value
- validated runtime limits retain the sealed-batch scheduler cap as a
  host-sized non-zero proof, so scheduler policy does not reinterpret serialized
  config integers.
- runtime limits, workspace I/O budgets, and workspace observation task queue
  limits report zero-limit failures through closed field vocabularies with
  stable text.
- production workspace observation task enqueueing through sealed
  successful-return batches only. Direct queue insertion from an authorized read
  proof is test-only, so runtime code cannot bypass the session request ledger
  or failed-update discard boundary.
- retry-safe sealed workspace observation task admission: a queue mismatch
  returns the closed queue rejection with the still-sealed batch, so callers can
  retry on the owning queue or drop the batch deliberately. Its consuming split
  returns named queue-error and batch fields.
- sealed workspace observation task admission retains the validated pending
  queue storage through enqueue, so reservation validation and pending
  publication cannot drift as separate caller conventions.
- explicit sealed workspace observation task discard after successful guest
  return but before queue admission, returning a redacted discard report while
  releasing the held queue reservations.
- bounded workspace I/O queue with FIFO execution and revocation cancellation
- retry-safe sealed workspace I/O worker queue admission: saturation returns
  the closed queue rejection with the still-sealed batch, so callers can retry
  after capacity frees or explicitly discard the batch with a redacted cleanup
  report. Its consuming split returns named queue-error and batch fields.
- all-identity workspace I/O worker and workspace observation task queue
  cancellation for shutdown or broad teardown, returning deterministic
  per-identity redacted reports without filesystem work or guest delivery
- Wasmtime instance revocation cleanup for workspace observation tasks through
  `cancel_workspace_observe_tasks_for_revocation`, gated by a
  `PluginRevocationReport` identity proof and clearing queue-owned task state,
  uncommitted active-update task requests, and persistent task resources
- Wasmtime instance shutdown cleanup for workspace observation tasks through
  `cancel_workspace_observe_tasks_for_shutdown`, clearing runtime-owned
  queue state, uncommitted active-update task requests, and persistent task
  resources without requiring lifecycle mutation
- a Wasmtime revocation helper that prechecks runtime/state identity before
  mutating host state, then pairs the `PluginRevocationReport` with
  runtime-owned workspace observation task cleanup in one result
- Wasmtime revocation cleanup splits lifecycle revocation from runtime-owned
  workspace observation task cleanup through named fields instead of a
  positional tuple
- task-based workspace observation enqueue rejects sealed batches whose plugin
  identity does not match the runtime instance, and enqueue, single-task
  execution, non-zero capped batch execution, and drain-all execution require
  the matching active `PluginInstanceState`, so revoked instances cannot admit
  sealed observe-task batches or run queued filesystem work
- a Wasmtime update helper that schedules task-based workspace observations
  back onto the producing runtime queue after successful guest return, while
  returning a `WasmtimePluginScheduledUpdate` proof that pairs sealed editor
  and workspace I/O owner work with already-scheduled task evidence
- post-update observe-task schedule recovery consumes the paired schedule-error
  proof and rebuilds the scheduled-update proof after a successful task retry,
  so owner-loop callers do not split retryable owner work from retryable task
  work by convention
- post-update observe-task schedule discard consumes that same proof and returns
  one redacted report for discarded owner work and unscheduled task work
- failed-update, owner-work, post-update schedule, and scheduled owner discard
  report debug output is count-shaped at the outer boundary, without nested
  discard-report formatting or task-handle lists
- Wasmtime scheduled-update debug output reports identity and work counts
  only. Post-update schedule-error debug output also reports the closed
  enqueue rejection class, without formatting retained owner batches or
  retryable task batches.
- paired owner-publication queue admission for sealed editor effects and sealed
  workspace I/O, validating both owner queues into a private paired admission
  proof that retains the target queue borrows until publication. Each
  individual owner queue admission owns its sealed batch until publication, and
  rejection returns the owner-work proof intact while success returns a named
  owner-publication report; debug output reports only identity, closed
  rejection class when present, and work counts. Consuming owner-queue enqueue
  failures expose named queue-error and owner-work fields for retry decisions.
- scheduled-update owner-publication API that consumes
  `WasmtimePluginScheduledUpdate`, publishes the remaining owner work through
  the paired owner queues, returns a named success report with both the
  owner-publication report and already-admitted observe-task scheduling report,
  and on owner-queue rejection keeps the retryable owner work paired with that
  scheduled-task report
- scheduled-update owner-publication retry that consumes the paired
  owner-queue failure and either returns the named publication report or the
  same paired failure shape, so callers do not split already-scheduled task
  evidence from retryable owner work by convention
- scheduled-update owner-publication discard returns a named report that keeps
  discarded owner work paired with the already-admitted task scheduling report;
  report accessors name that evidence as scheduled task work, and debug output
  uses counts rather than retained batch internals or task-handle lists
- scheduled-update and scheduled-owner-publication public split APIs return
  named part structs for owner work, retryable queue errors, discard evidence,
  and already-scheduled task evidence instead of positional tuples
- successful-return and owner-batch public split APIs return named part structs
  for editor effects, workspace I/O, and runtime-owned observe-task work
  instead of positional tuples
- drained effect reports split into named owner request batches that retain the
  drained plugin identity, so editor-effect and status request vectors are not
  separated by tuple position
- active-update setup, task-resource authority, and adapter-local update
  resource splits return named boundary structs for captured snapshots,
  update handles, resource-table authority, and guest borrows
- a private-field Wasmtime observe-task schedule error payload that keeps the
  unpublished owner-work proof and the retryable task enqueue error paired
  after a successful update, instead of exposing those fields as a public enum
  construction convention
- private-field Wasmtime observe-task enqueue failures with a closed public kind
  and accessors for lifecycle, instance-state, batch-identity, queue, retry,
  discard, and redacted operational reporting, so callers cannot construct
  source and batch mismatches by convention. Instance-state and batch-identity
  mismatch accessors return named borrowed identity pairs instead of positional
  tuples.
- Wasmtime observe-task enqueue failure debug output reports the closed public
  kind, relevant identity proofs, queue rejection class when present, and
  retained task count without formatting the retryable sealed batch
- scheduled-update and observe-task enqueue failures expose the same redacted
  operational event projection as runtime failures, so owner-loop callers do
  not need to destructure private scheduling payloads for diagnostics
- persistent Wasmtime workspace observation task resources retain the
  authorizing workspace path and revalidate it against the current update
  snapshot before poll or take can reach task queue state; denied revalidation
  tombstones the resource without freeing the table rep and returns the typed
  authorization rejection
- Wasmtime workspace observation task resource resolution and drop reject
  resource-table/tracker divergence as a typed resource-handle failure in
  release builds. If a new task resource would reuse a table rep that the
  tracker still records, the stale tracked resource is tombstoned, the new
  table entry is removed, and the start import fails closed. Table
  lookup/delete errors tombstone the tracked resource before returning unless
  drop already freed the table slot, and diagnostics do not expose table reps,
  paths, or task payloads.
- Wasmtime update setup tombstones workspace observation task resources still
  marked as started by a prior abandoned update before accepting fresh update
  resources
- closed workspace I/O worker queue limit field and rejection-class vocabulary
- closed workspace observation task poll and take result shapes that distinguish
  pending, completed, and unknown or already-consumed task ids without exposing
  paths or filesystem error detail; poll results carry only redacted outcome
  shape, while take remains the consuming byte-delivery path
- a separate workspace observation task result vocabulary for inert task ids,
  owned identity-scoped task handles, queue keys, internal handle-borrowed
  lookup matching, shared closed task state, payload-free queue state queries,
  payload-free poll results, consuming take results, shared redacted poll/take
  result shapes, and `PluginWorkspaceObserveTaskCompletionShape`, so Wasmtime
  resource adapters can encode task results without owning queue mutation
- redacted operational events for load, unload, revocation, denied import,
  update setup rejection, non-authorization host import rejection, timeout,
  guest trap, runtime setup/fuel failure, intent queue saturation, workspace
  I/O queue saturation, workspace observation task queue saturation, and
  proposal lane saturation
- explicit stable text for operational queue, revocation-reason, handle-kind,
  resource-handle rejection, host-state mismatch, and host-import rejection
  classes
- redacted plugin runtime trace vocabulary for drained effects, discarded
  updates, workspace I/O completions, workspace I/O cancellations, workspace
  observation task completions with identity-scoped completion shapes,
  workspace observation task cancellations, operational events, and proposal
  receipts
- checked-in runtime trace replay golden coverage over line-oriented
  `PluginRuntimeTraceEvent` display output

Not implemented:

- host imports beyond `status.publish`, `buffer.observe`,
  `buffer.propose_edit`, task-based `workspace.observe`, and
  `workspace.artifact_write`
- plugin event subscriptions
- background workspace I/O worker threads
- guest-driven scheduling and subscriptions
- synchronous guest-visible `workspace.observe`; public workspace reads use
  task resources
- automatic background execution of pending workspace observation tasks

Non-goals for v1:

- remote plugin downloads or marketplace discovery
- runtime permission prompts
- process execution, shell access, or environment access
- raw filesystem paths in the guest API
- raw ECS access or Bevy system registration from plugins
- synthetic user input
- arbitrary config mutation
- unrestricted clipboard access
- lifecycle shutdown authority
- unbounded or long-running guest tasks on the Bevy update thread

## Dataflow

Plugins add one explicit stage between interpreted intent and owner mutation:

```text
Input -> Intent -> PluginIntent -> Edit -> Layout -> Shape -> Render
```

Guest code runs only in `PluginIntent`. Host imports can observe bounded data or
queue discardable effects. A successful guest return seals the batch. Draining
publishes status requests and routes buffer edit proposals into the proposal
lane. Per-plugin config policy chooses whether buffer edit proposals auto-apply
through the existing buffer owner or remain pending until an explicit apply or
reject request arrives. Id-bearing proposals produce bounded receipts when the
proposal lane rejects them or the buffer owner accepts or rejects them.
Intent queue saturation is retry-safe: a rejected sealed effect batch stays
paired with the closed queue rejection until the caller retries it or discards
it deliberately.

Host imports do not mutate `EditorBuffer`, `EditorView`, `VimModalState`,
filesystem state, or render state. They return bounded observations or append
to the pending per-update batch.

The component-model boundary carries three separate invariants. WIT defines the
public shape, resources carry editor view and buffer authority, and Wasmtime
store/session state defines lifetime. Resource reps are not part of Alma's
public API.

Generated-to-Alma decode accepts only closed guest-decode field labels. Adapter
call sites choose from that vocabulary instead of passing ad hoc diagnostic
strings, so oversized, malformed, or invalid guest fields cannot drift by
caller convention. Decode limits derive from validated runtime policy and carry
non-zero byte/count caps before adapters can bound guest strings, payloads, or
returned buffer snapshots.

Workspace authority is deliberately not an ambient update resource. Workspace
host imports must create typed read or write authority at the import boundary
from the requested operation kind, validated workspace-relative path, bounded
payload, explicit filesystem context when bytes are returned synchronously, and
effective grants captured in the host import session. Deferred requests become
workspace I/O; failed guest updates discard them before filesystem policy
execution. Direct observations spend the same per-update request cap before
filesystem access even though they do not enter the deferred worker queue.

The existing direct workspace observation helper is a host-session policy path,
not a guest-visible Wasmtime import. It proves the result shape reused by the
task-based `workspace.observe` ABI: bounded bytes or one closed rejection, with
no workspace paths, display paths, filesystem error detail, or diagnostic text.
Do not expose a synchronous Wasmtime host import unless filesystem work has an
enforceable host-side deadline or cancellation path. Wasmtime epoch
interruption can stop guest Wasm, but it cannot preempt Rust host code blocked
in filesystem I/O.

The workspace observation task queue is the host-side shape for public
workspace reads. It treats task ids as inert lookup keys, requires an
identity-scoped handle for polling or taking results, retains only
`PluginWorkspaceObserveOutcome`, and cleans both pending tasks and retained
results on revocation. The host-import session has a separate pending task
batch and sealed task batch, so task filesystem work cannot be published before
successful guest return. Pending task batch insertion owns plugin-identity
validation before charging the shared workspace request budget or retaining the
task proof. The retained task proof also carries the update's non-zero read
byte cap into queue execution. The start import reserves both pending capacity
and a non-reused identity-scoped task handle before returning an opaque task
resource; failed updates release the pending-capacity slot and discard the
filesystem work, but they do not roll the id space back because guest memory
may already contain the resource. Sealed batch enqueue consumes those reserved
handles, slots, and read caps. Reservation accounting remains safe for
scheduler or worker handoff through an explicit RAII slot counter owned by the
queue token.
The queue exposes a payload-free closed state query, payload-free polling, and
a consuming take result for adapter use: `pending`, `completed`, and `unknown`.
Completed poll/take shapes carry only the redacted guest-delivery outcome
shape, retained completion shapes carry the owning plugin identity with the
task id, and only `take` carries the byte-bearing guest-delivery outcome. A
pending task cannot be consumed, a completed task can be consumed once, and ids
that are stale, evicted, already taken, or owned by another plugin collapse to
`unknown`.
The shared task-state projection is payload-free, and both pending and retained
queue records match through an internal lookup borrowed from the identity-scoped
task handle. Public Rust callers poll, take, or query state with the owned
handle rather than constructing arbitrary identity/task-id pairs.
The public ABI exposes the start/poll/take group together. `start` validates and
authorizes the path during an active update, returns a bounded host-owned task
resource, and keeps filesystem work behind the successful-return boundary. The
host-session boundary pairs the reserved task handle with the authorized path in
one proof before Wasmtime can persist the resource. If the guest drops that
resource before the update commits, the host session removes the pending request
instead of sealing later filesystem work for an unreachable task handle.
The resource stores the authorizing workspace path, so `poll` and `take`
revalidate that path against the active update snapshot before reading queue
state. Denied revalidation tombstones the resource and returns the typed
authorization rejection while keeping the table rep occupied until guest drop.
A later canonical drop of that invalidated task resource is an idempotent
cleanup no-op. `poll` is payload-free and reports only pending, unknown, or a
redacted completed outcome shape. `take` is the only byte-bearing guest
delivery path and consumes completed outcomes at most once.
Production enqueueing into the host-owned task queue accepts sealed
successful-return batches, not raw read proofs from adapters, and requires the
matching active `PluginInstanceState`. The direct queue push remains a focused
test helper for queue behavior. Execution uses the same active-state gate, so
revocation blocks both late enqueue of a caller-held sealed batch and later
filesystem reads from queue-owned pending work.
Successful-return aggregate debug output reports identity and work counts
instead of formatting nested sealed effect, workspace I/O, or observe-task
batches.
Failed sealed-batch admission returns both the closed queue rejection and the
still-sealed batch. The reservation slots remain live while the returned batch
is live, so a scheduler can retry on the owning queue without losing task ids,
or explicitly discard the batch and get a redacted cleanup report while
releasing capacity.
The WIT metadata ties each task function name to `workspace.observe` and a
stable operational import class. That metadata is not runtime authority; it
keeps capability checks, generated bindings, diagnostics, and drift tests in
lockstep.

## Module Map

- `src/plugin/policy/config/mod.rs`: static config facade and public re-exports
- `src/plugin/policy/config/registry.rs`: registry uniqueness validation and
  enabled load-entry proofs
- `src/plugin/policy/config/entry.rs`: untrusted static config entries and
  effective manifest grant projection
- `src/plugin/policy/config/identity.rs`: stable plugin identity grammar
- `src/plugin/policy/config/world.rs`: current WIT-world proof
- `src/plugin/policy/config/component.rs`: component path shape validation
- `src/plugin/policy/config/proposal.rs`: proposal review policy schema
- `src/plugin/policy/config/tests.rs`: config-boundary tests and property
  coverage
- `src/plugin/policy/capability.rs`: capability grants, capability atoms,
  authorization-ref path arity, and host-import query shapes
- `src/plugin/policy/workspace.rs`: workspace-relative grants and path refs,
  not filesystem authority
- `src/plugin/policy/manifest.rs`: untrusted manifest parsing and effective
  grant projection
- `src/plugin/policy/scheduler.rs`: registry-level publication burst policy
- `src/plugin/runtime/component.rs`: policy-opened component bytes
- `src/plugin/runtime/limits.rs`: bounded execution and ECS publication limits
- `src/plugin/runtime/instance.rs`: runtime specs, loaded instance lifecycle,
  and revocation policy
- `src/plugin/runtime/wasmtime/mod.rs`: feature-gated Wasmtime adapter facade
- `src/plugin/runtime/wasmtime/adapter.rs`: runtime and instance orchestration
- `src/plugin/runtime/wasmtime/error.rs`: redacted Wasmtime failure and
  observe-task enqueue error vocabulary
- `src/plugin/runtime/wasmtime/execution.rs`: fuel and epoch-deadline guards
- `src/plugin/runtime/wasmtime/resources.rs`: typed update-resource table reps
- `src/plugin/runtime/wasmtime/schedule.rs`: scheduled-update and revocation
  proof shapes
- `src/plugin/runtime/wasmtime/store.rs`: store-local host-import state and
  generated host import adapters
- `src/plugin/runtime/wasmtime/workspace_observe.rs`: workspace observe-task
  queue/resource state and guest ABI projections
- `src/plugin/runtime/wasmtime/tests.rs`: Wasmtime adapter and component
  fixture coverage
- `src/plugin/host/context.rs`: per-plugin authorization context and shared
  host authority proof
- `src/plugin/host/import/mod.rs`: host-import boundary facade and re-export
  surface
- `src/plugin/host/import/snapshot.rs`: per-update authority and handle-store
  capture
- `src/plugin/host/import/session.rs`: active import-session mutation methods,
  direct workspace observation policy path, and discardable work collection
- `src/plugin/host/import/batches.rs`: successful-return owner/task batches
  and failed update discard reports
- `src/plugin/host/import/resource.rs`: observe-task resource-authority proofs
  and component-resource rejection vocabulary
- `src/plugin/host/import/error.rs`: layered host-import rejection types and
  host-import rejection projection
- `src/plugin/host/effect/mod.rs`: effect boundary facade and re-export
  surface
- `src/plugin/host/effect/limit.rs`: non-zero effect admission limit proof
  and stable limit-field vocabulary
- `src/plugin/host/effect/error.rs`: effect admission rejection classes and
  commit error vocabulary
- `src/plugin/host/effect/proposal.rs`: internal effect payload storage,
  status shapes, and snapshot-derived buffer edit proposals
- `src/plugin/host/effect/batch.rs`: pending and sealed effect batches,
  successful-return sealing, and typed admission methods
- `src/plugin/host/effect/report.rs`: discard evidence, drained owner request
  reports, named owner request splits, and redacted drained request shapes
- `src/plugin/host/handles.rs`: per-plugin typed handle table and short-lived
  resolved proofs
- `src/plugin/host/workspace_io/mod.rs`: workspace I/O facade and re-export
  surface
- `src/plugin/host/workspace_io/batch.rs`: pending and sealed deferred
  workspace I/O batch ownership
- `src/plugin/host/workspace_io/error.rs`: shared workspace I/O commit
  rejection classes and identity-mismatch source vocabulary
- `src/plugin/host/workspace_io/budget.rs`: workspace I/O limit proofs and
  shared per-update request accounting
- `src/plugin/host/workspace_io/access.rs`: workspace read/write access
  proofs, internal filesystem-policy tokens, and operation-specific
  filesystem-policy errors
- `src/plugin/host/workspace_io/report.rs`: owner-facing workspace I/O
  execution reports, operation-typed completions, explicit success accessors,
  and guest-delivery read projections
- `src/plugin/host/workspace_io/observe_result.rs`: task ids, owned
  identity-scoped task handles and queue keys, internal handle-borrowed lookup
  matching, shared closed task state, redacted poll/take result shapes,
  payload-free poll results, consuming take results, and identity-scoped
  `PluginWorkspaceObserveTaskCompletionShape` for guest-visible workspace
  observation resources
- `src/plugin/host/workspace_io/observe_tasks/mod.rs`: workspace observe-task
  facade and re-export surface
- `src/plugin/host/workspace_io/observe_tasks/batch.rs`: pending and sealed
  observe-task batches plus successful-return sealing and explicit discard
- `src/plugin/host/workspace_io/observe_tasks/queue.rs`: host-owned task queue,
  queue limits, non-reusing task ids, FIFO execution, retained outcomes,
  state, poll, take, and cancellation
- `src/plugin/host/workspace_io/observe_tasks/error.rs`: reserve/enqueue
  errors, closed queue rejection classes, limit-field vocabulary, and
  reservation mismatch vocabulary
- `src/plugin/host/workspace_io/observe_tasks/report.rs`: redacted discard,
  enqueue, and cancellation reports
- `src/plugin/host/workspace_io/observe_tasks/reservation.rs`: identity-scoped
  task reservations and RAII pending-slot accounting
- `src/plugin/host/workspace_io/worker.rs`: sealed workspace I/O FIFO worker
  queue, retryable queue admission, queue limit, revocation or shutdown
  cancellation, and saturation diagnostics
- `src/plugin/trace/`: redacted replay/telemetry facade split by event
  envelope, effect/status payloads, workspace payloads, proposal receipts, and
  shared display adapters
- `src/plugin/abi/wit.rs`: stable hand-written ABI vocabulary and host-import
  metadata for default builds, including task-style workspace observe names,
  capability, and operational classes
- `src/plugin/abi/decode/mod.rs`: generated-to-Alma decode facade and re-export
  surface
- `src/plugin/abi/decode/limits.rs`: decode limits projected from validated
  runtime policy
- `src/plugin/abi/decode/field.rs`: closed guest-decode diagnostic field
  vocabulary
- `src/plugin/abi/decode/error.rs`: redacted guest-decode error vocabulary
- `src/plugin/abi/decode/scalar.rs`: bounded guest string, payload, count, and
  text-range proofs
- `src/plugin/abi/decode/workspace_path.rs`: normalized workspace path decode
  proof
- `src/plugin/abi/decode/capability.rs`: WIT capability references decoded into
  Alma-owned authorization refs
- `src/plugin/abi/decode/buffer_edit.rs`: guest buffer edits decoded into
  bounded owner-facing edit requests
- `src/plugin/abi/decode/tests.rs`: decode-boundary field, limit, redaction,
  and owner conversion tests
- `src/plugin/abi/bindings.rs`: private generated component bindings behind
  `plugin-runtime`
- `src/plugin/operational.rs`: redacted operational event vocabulary
- `src/ecs/events/plugin.rs`: ECS diagnostic message for redacted plugin
  operational events
- `src/ecs/plugin.rs`: ECS queue, paired owner-publication helper, and drain
  adapter for sealed plugin effects

## Commit Points

Plugin work has three commit points:

1. Guest return succeeds.
   Pending effects and workspace I/O may become sealed batches.

2. Sealed effects drain.
   The host publishes status requests and creates typed pending buffer edit
   proposals.

3. Proposal policy, ECS owners, and filesystem owners apply or reject.
   Buffer, status, layout, and filesystem policy remain authoritative.
   Id-bearing plugin proposals produce a receipt after this decision boundary.

Trap, timeout, interruption, decode failure, denied capability, malformed data,
stale handle, or exceeded limit before successful return discards the pending
batch. Draining is not mutation. A pending or auto-applied buffer edit can still
be rejected by the buffer owner.

When one successful update carries both editor effects and deferred workspace
I/O, owner publication treats them as one proof until both target queues accept
admission. The paired admission proof carries the validated queue borrows
through publication, and a saturated intent queue or workspace I/O worker queue
returns the paired owner work without mutating either queue.

Deferred workspace I/O follows the same first commit point. Host imports queue
bounded read/write requests, failed guest updates discard them, and only sealed
batches may enter `PluginWorkspaceIoWorkerQueue`. Direct observations are owned
by the pending workspace I/O ledger, spend the same per-update request cap, and
bypass the queue, but they are not a public Wasmtime import because synchronous
host filesystem work is not preemptible by guest timeout machinery. Task-style
workspace observations also follow the first commit point: task read proofs are
pending during the update, failed updates discard them, successful updates seal
them, and the task queue enqueues sealed batches all-or-nothing before
filesystem policy runs. Task resources returned before a failed update are
tombstoned, leaving their table reps occupied until guest cleanup so stale
handles cannot alias later resources. Revocation cancels queued batches by
plugin identity before filesystem work. The current worker executes through
typed workspace policy tokens and `fs_utils` in FIFO order.
Worker queue saturation returns the still-sealed workspace I/O batch with the
closed queue rejection, so scheduler code can retry after capacity frees or
explicitly discard the batch and retain redacted cleanup evidence.
Both workspace queues can cancel all queue-owned work for shutdown or broad
teardown, grouping redacted cancellation reports by plugin identity in
deterministic cleanup order. Retryable sealed batches held outside the queues
remain caller-owned and must still be retried or explicitly discarded by that
caller.
The Wasmtime shutdown cleanup hook applies the same rule to runtime-owned
workspace observation task state: it removes uncommitted active-update task
requests, cancels queue-owned work, and tombstones persistent task resources
without touching caller-held sealed batches.
Execution reports may retain owner-facing success data behind explicit
accessors. Debug and future replay diagnostics must use redacted operation
shapes and byte counts rather than host paths or file bytes.

## Lifecycle And Cancellation

`PluginInstanceState` owns runtime spec, host context, handles, and lifecycle
state for one plugin generation. Scheduling first checks the lifecycle gate,
then creates one active-update proof containing the owned host import snapshot
and update handles. Snapshot construction rejects any host context and handle
store pairing that does not share the same validated plugin identity.
The Wasmtime adapter retains the first host-import rejection for an active
update as a single `{ import, source }` envelope. That keeps redacted
operational attribution and the typed rejection cause together through guest
trap handling and canonical ABI cleanup. The typed `source` owns its
non-authorization operational rejection class, so runtime adapters attach
import attribution without reclassifying host-import causes. Revocation stops
future scheduling, invalidates handles, drops pending effects, and exposes an
explicit `PluginRevocationReport`-gated cleanup path for queue-owned workspace
observation tasks and their persistent task resources. The Wasmtime
observe-task scheduler methods also require the matching active state; a
revoked state denies enqueue, single-task execution, capped batch execution,
and drain-all execution, while failed enqueue still returns the sealed batch
for explicit discard. The drain-all runtime method is named
`execute_all_workspace_observe_tasks`; the bounded owner-loop methods remain
`execute_next_workspace_observe_task` and
`execute_workspace_observe_tasks_up_to`.
The preferred Wasmtime revocation path is `revoke_state`: it rejects
runtime/state identity mismatches before mutating the provided state, then
returns lifecycle revocation and runtime-owned observe-task cleanup together.
Host shutdown can call `cancel_workspace_observe_tasks_for_shutdown` on the
runtime instance without a revocation proof; it is cleanup of authority already
owned by that instance, not guest lifecycle authority.

The v1 unload policy is conservative: every revocation reason unloads the
runtime instance. Reuse after config reload requires an explicit policy change
with tests proving unchanged authority.