feat(agent): eje agéntico — motor $agent (F1) + Aura + promoción uix.scene
Materializa el eje ortogonal agéntico del ecosistema: la 8ª familia semántica
`delegate` («¿quién actúa ahora?») deja de estar sin materializar. El agente es
OTRO ACTOR (LLM, macro, regla, workflow) que actúa por la MISMA API pública del
provider; la ruta de llamada no se bifurca, la concreción semántica depende del
actor.
F0 · Doctrina
- docs/architecture/agent.md — la doctrina permanente (capítulo comparativo de
referencias + bibliografía de seguridad, máquina estados=verbos, contrato de
participación, fila §0, a11y, amenazas).
- docs/process/{PLAN,TRIAGE,INFORME}-agent — plan de ejecución con todas las
decisiones firmadas (D-AG.1–11 + ⚖️1/2/3), triage de 4 revisores externos, e
informe autocontenido para revisión externa.
F1 · Motor ($libs/actor + arts/agent, 24º arte)
- EngineAgent puro (sin DOM/runes, portable a servidor): máquina D-AG.4
(suggest/review/auto · escalated con reason+timeout · returned outcome-tipado
· kill switch · autorización journaled aunque sea auto), tool-loop D-AG.5
(acts secuenciales, fallos→verbos, unknown-capability acotado, idempotencia
por callId, presupuestos acts/turns/wall-clock vía puerto de timers), techo de
autonomía por origen no confiable (F8b).
- ActiveAgent (sesión reactiva, contrato ActiveEngine) · protocolo v1 espejo
AG-UI (5 categorías + dirección tipada + reservas) · ScriptedAgentTransport
determinista (adapters/ fuera del barrel) · journal WAL + puerto de trazas
OTel · emisor sium→JSON Schema.
- Acuñación del actor (⚖️2/F6b): ActorToken opaco en $libs/actor (hoja bajo
orca/agent), registro privado WeakMap — los forjados resuelven a null;
costura `actor?` en TriggerOptions→SemanticSignal (runtime copia verbatim;
sema no resuelve). defineActiveAgent (service-factory app-level, timers del
core — cero setTimeout a pelo).
F3 · Aura — primer componente del eje (ruta 9 fases 0–6)
- El materializador canónico de `delegate` (reservado en scene §F6): morfo con
los eventos del ciclo (offer/escalate-untilAction/return + sustain-processing
stateBound) — PRIMER morfo del ecosistema que emite familia delegate; provider
soma que observa un puerto estructural (sin importar $agent — degradación
total); orb eidos = aurora $scene modulada por estado (§F6) con fallback CSS
= render de reduced-motion; live region única atribuida (WCAG 4.1.3); cancel
compone Button (asChild). Demo v2 sobre el MOTOR REAL con compuertas
deterministas. Orb-size derivado de la primitiva Avatar (32/40/48).
D4 · Promoción uix.scene (Aura llegó)
- defineEngineScene + superficie ActiveUix/ActiveEidos/contracts; el orb prefiere
el motor compartido (presupuesto de escenas global) con fallback por-superficie.
Gates: arts/agent 18/18 · aura 6/6 · arts:check 24 · eidos battery + recipe
30/30 + eidos-lint aura 0 inválidos · morfo:vocabulary + esquemas · smoke aura
PASS · verificado en navegador (ciclo completo + estampa delegate en DOM +
aurora WebGL pintando). Los tokens de recipe base.ts + CSS generado ya entraron
en HEAD vía una sesión concurrente.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
3 months ago
|
|
|
|
---
|
|
|
|
|
|
title: Agent — the delegation axis
|
|
|
|
|
|
type: reference
|
|
|
|
|
|
audience: human + agent
|
|
|
|
|
|
authority: E1 architecture — the agentic axis: the delegation model, the actor primitive, the participation contract, the minimum contracts, the a11y + threat doctrine
|
|
|
|
|
|
status: current — F0 doctrine (track PLAN-agent.md); decisions D-AG.1–11 + ⚖️1/2/3 signed 2026-07-21
|
|
|
|
|
|
sources:
|
|
|
|
|
|
canon: docs/CANON.md (the `delegate` family, ch. 29 of the book)
|
|
|
|
|
|
plan: docs/process/PLAN-agent.md (execution record — process, not doctrine)
|
|
|
|
|
|
review: docs/process/TRIAGE-revision-externa-agente.md (4-reviewer external critique)
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
# Agent — the delegation axis
|
|
|
|
|
|
|
|
|
|
|
|
> An **agent** is another actor. Not a mode, not a chat widget, not a wrapper
|
|
|
|
|
|
> around an LLM SDK. activeUIX already asks, in its semantic canon, *"¿quién
|
|
|
|
|
|
> actúa ahora?"* — the `delegate` family (book ch. 29). The agent axis is the
|
|
|
|
|
|
> materialization of that family: the machinery by which **an actor other than
|
|
|
|
|
|
> the user** can be invoked from, and participate in, any component of the
|
|
|
|
|
|
> ecosystem — with the same events, the same undo, the same permissions, the
|
|
|
|
|
|
> same accessibility, and the same perceptual semantics that a user's action
|
|
|
|
|
|
> already gets.
|
|
|
|
|
|
|
|
|
|
|
|
This chapter is the standing doctrine. The dated execution record (phases,
|
|
|
|
|
|
signed decisions, per-item work) lives in
|
|
|
|
|
|
[`process/PLAN-agent.md`](../process/PLAN-agent.md) — process, not truth.
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 0. Why an axis, not a component (and the reference pass)
|
|
|
|
|
|
|
|
|
|
|
|
The framework's own rule is to **study reference implementations before
|
|
|
|
|
|
designing** (as it did for the framework itself in `comparison.md`). The
|
|
|
|
|
|
agentic-UI field, surveyed 2026-07, converges on a small set of contracts —
|
|
|
|
|
|
and diverges from activeUIX in exactly the places that make this axis worth
|
|
|
|
|
|
building.
|
|
|
|
|
|
|
|
|
|
|
|
| Concern | Field convergence | activeUIX position |
|
|
|
|
|
|
| --- | --- | --- |
|
|
|
|
|
|
| Readable context | CopilotKit `useCopilotReadable`: NL-description + value, hierarchical (parentId), per-readable gating | `reads` in the per-component manifest; **push→pull** index + `read(instanceId)` on demand, prioritized by focus/viewport (a UIX-native signal none of them have) |
|
|
|
|
|
|
| Frontend tool calling | CopilotKit `useCopilotAction`, Vercel AI SDK tools, MCP tools; roundtrip closes via a `role:'tool'` message | `acts` in the manifest → the component's **existing public API**; result typed by sium, failures mapped to `delegate` verbs |
|
|
|
|
|
|
| Protocol / streaming | AG-UI: 17 events / 5 categories (run · text deltas · tool-calls · state · custom); triple start/content/end; state = snapshot + JSON-Patch delta (RFC 6902), resync by re-snapshot | Own protocol **mirroring AG-UI** (parity baseline, à la `ethereal` ↔ floating-ui); snapshot-per-turn in v1, delta reserved |
|
|
|
|
|
|
| Human-in-the-loop | Two shapes: pre-act approval (CopilotKit renderAndWait) + mid-run interrupt/elicitation (LangGraph interrupts, MCP elicitation). AG-UI models approval as a *confirmation-tool*, no separate primitive | The `delegate` cycle as **observable run states**; on the wire, review/elicitation ride the confirmation-tool shape (states in the motor, interop on the cable) |
|
|
|
|
|
|
| Embedded-UI security | MCP Apps (SEP-1865): sandboxed iframes, JSON-RPC host↔UI, **the host controls authorization** | The app is the ceiling of autonomy (D-AG.7); capabilities never self-authorize |
|
|
|
|
|
|
| Provider coupling | Most are React-first; **none ship a Svelte-native path** | Svelte-5-native by construction; provider adapters isolated behind a port |
|
|
|
|
|
|
|
|
|
|
|
|
**The gaps nobody fills** — and where this axis earns its keep:
|
|
|
|
|
|
|
|
|
|
|
|
- **A perceptual semantics of delegation.** No surveyed framework has a
|
|
|
|
|
|
vocabulary for *who acts* rendered across sound / motion / a11y. The
|
|
|
|
|
|
`delegate` family is exactly that, and it predates the LLM wave.
|
|
|
|
|
|
- **Transactional undo of a run** (one delegation = one undo step) and
|
|
|
|
|
|
**reversibility declared by effect**, not by capability.
|
|
|
|
|
|
- **Accessibility of autonomous action**: attributed announcements, no
|
|
|
|
|
|
focus-theft, reduced-motion of the presence indicator.
|
|
|
|
|
|
- **Causal actor attribution** across an async, cross-component cascade —
|
|
|
|
|
|
synchronous, unforgeable, without a global async monkey-patch. A
|
|
|
|
|
|
browser-first UI framework that gets this right has no shipping precedent.
|
|
|
|
|
|
|
|
|
|
|
|
The conclusion of the pass: the correct shape is an **orthogonal axis** —
|
|
|
|
|
|
engine (an art) + per-component participation contract + registry + a few own
|
|
|
|
|
|
surfaces — not a monolithic agent component that would import every component
|
|
|
|
|
|
and invert the dependency direction. It instantiates the same anatomy every
|
|
|
|
|
|
other cross-cutting axis (sound, language, theme, motion) already uses.
|
|
|
|
|
|
|
|
|
|
|
|
Rejected alternatives, for the record: *protocol-only, no engine* pushes the
|
|
|
|
|
|
state machine, budgets and elicitation into every app (re-implemented N times);
|
|
|
|
|
|
*agent-100%-backend* kills frontend tool calling (the field's most load-bearing
|
|
|
|
|
|
contract) and the perceptual semantics; *generative-UI without manifests*
|
|
|
|
|
|
throws away the typed, auditable acts. Each can be layered on top later; none
|
|
|
|
|
|
can be the base.
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 1. The thesis
|
|
|
|
|
|
|
|
|
|
|
|
> **The agent is another actor.** Everything downstream of that sentence is
|
|
|
|
|
|
> the design.
|
|
|
|
|
|
|
|
|
|
|
|
Four principles, none negotiable without re-signing:
|
|
|
|
|
|
|
|
|
|
|
|
1. **Actor-agnostic** (book ch. 29 §1). The axis never asks "is this an LLM?".
|
|
|
|
|
|
A macro, an automation rule, a workflow, a remote human approver and a
|
|
|
|
|
|
model are all just *another actor*. Nothing in the axis depends on a
|
|
|
|
|
|
concrete LLM provider. This is what lets the architecture outlive the LLM
|
|
|
|
|
|
market.
|
|
|
|
|
|
|
|
|
|
|
|
2. **The agent knows no components.** It never names `Palabras`, `Chronos`,
|
|
|
|
|
|
`Chat`. It sees only **capabilities** declared by whatever providers are
|
|
|
|
|
|
mounted. This keeps the dependency direction intact: the canon never
|
|
|
|
|
|
imports the axis.
|
|
|
|
|
|
|
|
|
|
|
|
3. **The golden rule — same public API, actor-dependent concretion.** The
|
|
|
|
|
|
agent acts through the **same public provider API** the app's own code
|
|
|
|
|
|
would call; the call path does not bifurcate. But the **semantic concretion
|
|
|
|
|
|
depends on the actor**: a component's existing events declare `delegate`
|
|
|
|
|
|
capacity (polymorphic events, `allowedFamilies` in the morfo contract) and
|
|
|
|
|
|
the provider concretes `{ family: 'delegate', verb: 'act' }` when the actor
|
|
|
|
|
|
is the agent. So the same `insert()` fires the same `runtime.trigger`, but
|
|
|
|
|
|
sema, eidos and the a11y layer read the correct answer to *"¿quién actúa?"*.
|
|
|
|
|
|
If a capability needs a door the public API lacks, that door is **promoted
|
|
|
|
|
|
to the component** through the normal route — never bypassed.
|
|
|
|
|
|
|
|
|
|
|
|
4. **Total degradation.** With the axis absent, every component works at 100%.
|
|
|
|
|
|
Manifest registration is a no-op; nothing a component owns depends on the
|
|
|
|
|
|
agent existing. See §4.
|
|
|
|
|
|
|
|
|
|
|
|
A corollary the field taught us the hard way: **client-side budgets are UX
|
|
|
|
|
|
courtesy, not a security boundary.** The boundary lives where the credential
|
|
|
|
|
|
lives (a proxy/backend). The motor's budgets exist to drive the state machine
|
|
|
|
|
|
and the UX, and the doctrine says so honestly.
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 2. The domain model
|
|
|
|
|
|
|
|
|
|
|
|
The axis is built around a **delegation**, not a conversation. A chat is one
|
|
|
|
|
|
surface that chains delegations; it is not the core (an agent can fill a
|
|
|
|
|
|
document with no conversation at all).
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
ActiveAgent — the session (long-lived; context across runs; identity)
|
|
|
|
|
|
└── Run — a delegation: budget, authorization, undo grouping, control return
|
|
|
|
|
|
├── Turn — one exchange with the model
|
|
|
|
|
|
│ └── CapabilityCall — a delegate.act on a provider (the only thing that mutates)
|
|
|
|
|
|
└── Context — snapshot of reads at turn open (§3)
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Three readings this ladder settles:
|
|
|
|
|
|
|
|
|
|
|
|
- **The `CapabilityCall` is what mutates the world; the `Run` is the unit of
|
|
|
|
|
|
delegation.** A mutation without the delegation envelope (budget,
|
|
|
|
|
|
authorization, undo grouping, control return) is exactly what the doctrine
|
|
|
|
|
|
forbids.
|
|
|
|
|
|
- **The degenerate Run** — a single auto-authorized call — is the non-AI case
|
|
|
|
|
|
of the book (a macro, a rule, a workflow). It is a valid, cheap Run.
|
|
|
|
|
|
- **Initiative is modeled, not just actor.** Every Run carries
|
|
|
|
|
|
`initiative: 'user' | 'system' | 'scheduled'` — *why* it acts, not only
|
|
|
|
|
|
*who* — because it changes trust, announcement, audit and the autonomy
|
|
|
|
|
|
ceiling. The entry verb hints it: a cycle entered by `offer` is
|
|
|
|
|
|
system-initiative.
|
|
|
|
|
|
|
|
|
|
|
|
**Ambient mode** (always-on: autocomplete, predictive suggestions) is **out of
|
|
|
|
|
|
the axis in v1, reserved by name**: a `Subscription`/watcher emitting
|
|
|
|
|
|
`delegate.offer`, with coalesced micro-runs as future design. It is named so a
|
|
|
|
|
|
second, parallel agency system cannot grow in by the back door.
|
|
|
|
|
|
|
|
|
|
|
|
### The run state machine = the `delegate` verbs, literally
|
|
|
|
|
|
|
|
|
|
|
|
The states **are** the verbs — as *custody of control*, not as cognitive
|
|
|
|
|
|
phases. The model's own plan→tool→plan loop lives entirely inside `acting`
|
|
|
|
|
|
(across turns); the machine models who holds control, not how the agent thinks.
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
┌─────────── escalated ──────────┐ (non-terminal; timeout → returned)
|
|
|
|
|
|
▼ │
|
|
|
|
|
|
offered → planned → reviewing ⇄ authorized → acting ──┤
|
|
|
|
|
|
│ │ (re-entrant: (fixes the │ ▼
|
|
|
|
|
|
│ │ partial allowlist + │ returned ← control ALWAYS returns
|
|
|
|
|
|
│ │ approvals) budget) │ (outcome-typed)
|
|
|
|
|
|
└─────────┴──── cancelled ────────────────────────┘
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
- **Authorization fixes scope, not vibes.** `authorized` derives from the plan
|
|
|
|
|
|
a **capability allowlist + budget**; an act outside that scope ⇒ automatic
|
|
|
|
|
|
`escalate` to re-review (never a silent failure, never teatro). This makes
|
|
|
|
|
|
`reviewing` re-entrant from `acting`.
|
|
|
|
|
|
- **`returned` is outcome-typed**: `completed | partial | rolled-back |
|
|
|
|
|
|
aborted | error`, with a `reason` (`superseded` — the premise changed under
|
|
|
|
|
|
the run; `budget-exhausted`; `killed`). Mid-sequence failure **rolls back to
|
|
|
|
|
|
run-start by default** (the user authorized the whole plan, not half); a
|
|
|
|
|
|
capability may declare it accepts partial close.
|
|
|
|
|
|
- **`escalated`** is non-terminal, carries a typed `reason` (`elicitation |
|
|
|
|
|
|
insufficient-scope | budget-exhausted | out-of-plan`), and **auto-returns on
|
|
|
|
|
|
timeout** (an abandoned escalation still needs an exit).
|
|
|
|
|
|
- **Pause needs no new verb**: pause = `return` with resumable context; resume
|
|
|
|
|
|
= a fresh Run chained in the session — which coincides with AG-UI's `resume`
|
|
|
|
|
|
mechanics. Our semantics and its wire converge without trying to.
|
|
|
|
|
|
- **User interruption = immediate `return`**, never an error. A **global kill
|
|
|
|
|
|
switch** on the motor (`disable()`) sends every run to `returned(aborted)`.
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 3. The participation contract
|
|
|
|
|
|
|
|
|
|
|
|
A component participates by declaring a **manifest** — the mirror of a sema
|
|
|
|
|
|
pack or a langs catalog, in its own tree (`src/uix/agent/components/{x}.ts`).
|
|
|
|
|
|
The manifest satisfies **structural contracts defined by the art**
|
|
|
|
|
|
(`AgentCapability` / `AgentRead`: string ids, Standard-Schema args via sium,
|
|
|
|
|
|
opaque handler) — the MotionDom / SceneDom port pattern — by typing against the
|
|
|
|
|
|
provider's public API on the uix side. Soma/uix types never cross into the art;
|
|
|
|
|
|
the opaque handler grants location-transparency for free (a reserved path to
|
|
|
|
|
|
distributed delegation).
|
|
|
|
|
|
|
|
|
|
|
|
- **Model-facing projection.** TypeScript never reaches the model. Every read
|
|
|
|
|
|
and act carries a natural-language `description`; args project as **JSON
|
|
|
|
|
|
Schema** (a sium→JSON-Schema emitter), with **size limits per arg** as part
|
|
|
|
|
|
of the contract. Traits annotate each act for the reasoner (cost, latency,
|
|
|
|
|
|
stability, staleness) — the MCP tool-annotations pattern.
|
|
|
|
|
|
- **Instances and context — push→pull.** An always-present **index** (stable id
|
|
|
|
|
|
+ type + human label + one-line summary, hierarchical) plus deep reads as a
|
|
|
|
|
|
**pull capability** (`read(instanceId)`), prioritized by **focus/viewport**;
|
|
|
|
|
|
addressing ambiguity ("the editor", with two mounted) ⇒ **elicitation, not a
|
|
|
|
|
|
heuristic**. `available` is a reactive predicate per act; a
|
|
|
|
|
|
`capabilities-changed` event refreshes the toolset between turns.
|
|
|
|
|
|
- **Results and failures** are sium-typed; a result carrying third-party
|
|
|
|
|
|
content is as untrusted as an imported document (same origin doctrine, §5).
|
|
|
|
|
|
`unknown-capability` (a hallucinated tool) returns as a tool-result for
|
|
|
|
|
|
self-correction, bounded by budget.
|
|
|
|
|
|
- **Altitude, not RPC.** Capabilities are **mechanical world-mutations**, few
|
|
|
|
|
|
and at the right altitude (`replaceRange`, not twelve micro-inserts).
|
|
|
|
|
|
Semantic operations (`summarize`, `translate`) are the *model's* cognition or
|
|
|
|
|
|
a reserved agent-side "skills" tier (the MCP-prompts analogue) — never lodged
|
|
|
|
|
|
in the component, which would invert the dependency direction.
|
|
|
|
|
|
- **Maturity tiers.** A manifest declares its tier — `reads-only` →
|
|
|
|
|
|
`reversible acts` → `full acts` — so the ~110 canon components adopt
|
|
|
|
|
|
incrementally without gating the axis; the guard audits the declared tier.
|
|
|
|
|
|
- **Reversibility is by effect, not by capability.** External effects
|
|
|
|
|
|
(send / publish / notify) are irreversible by definition; the reversion
|
|
|
|
|
|
authority is the component's **native history**, never orca compensation.
|
|
|
|
|
|
- **OCC.** Each read exports a `_version`; each act must carry it; a mismatch
|
|
|
|
|
|
is a recoverable `StateStaleError` (re-read → re-plan) — the answer to TOCTOU
|
|
|
|
|
|
(§5).
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 4. Minimum contracts (the §0 row) and degradation
|
|
|
|
|
|
|
|
|
|
|
|
Following the framework's rule that every change derive from the module
|
|
|
|
|
|
contract table:
|
|
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
|
Module Requires Optional When missing Error
|
|
|
|
|
|
agent AgentTransport port orca, perm, prefs, manifest registration is a NO-OP; only on invoking a
|
|
|
|
|
|
(app supplies it) connection, storage every component stays 100% functional capability with no transport
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
- The agent is an **app-level art** (factory `defineActiveAgent(...)`, the
|
|
|
|
|
|
auth/perm/cache pattern), not something `ActiveUix` builds in standalone.
|
|
|
|
|
|
Promotion to a read-only `uix.agent` accessor in attach mode arrives with the
|
|
|
|
|
|
canonical consumer (the scene-D4 precedent).
|
|
|
|
|
|
- **A component with a manifest MUST behave identically with the agent
|
|
|
|
|
|
absent.** The manifest is inert data until a running `ActiveAgent` reads it.
|
|
|
|
|
|
- Transport is **app-land by default** (the chat-family precedent: "the
|
|
|
|
|
|
transport stays app-land"); a server-authoritative `svrs/agent` is a
|
|
|
|
|
|
conditioned future initiative, never the v1 assumption. Adapters live in
|
|
|
|
|
|
`$agent/adapters/*` outside the main barrel; a **deterministic
|
|
|
|
|
|
`ScriptedAgentTransport`** is first-class, so static demos and component
|
|
|
|
|
|
tests run with **real instances, no mocks**.
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 5. The actor primitive (⚖️2) — causal attribution
|
|
|
|
|
|
|
|
|
|
|
|
The load-bearing decision of the axis. When the agent's act on component A
|
|
|
|
|
|
triggers events that cascade to mutate component B, **B's emission must carry
|
|
|
|
|
|
the correct actor** — or sema announces the agent's secondary effect as "user",
|
|
|
|
|
|
a11y and audit-trail catastrophe.
|
|
|
|
|
|
|
|
|
|
|
|
**The answer is the OTel-baggage unification, corrected by the browser caveat.**
|
|
|
|
|
|
The actor is an **opaque, engine-minted token** (`ActorToken`, minted and
|
|
|
|
|
|
resolved only by `EngineAgent`; a non-token `USER` sentinel everywhere else, so
|
|
|
|
|
|
absence can never be confused with a minted token) carried as **one reserved
|
|
|
|
|
|
slot on the causal envelope the framework already propagates** — `OrcaEventMeta`
|
|
|
|
|
|
on the orca path, the bus envelope's `context` bag on the bus path — inherited
|
|
|
|
|
|
depth-to-depth exactly as `traceId` is. It is read **synchronously** via
|
|
|
|
|
|
`actor?: ActorToken` on `TriggerOptions → SemanticSignal`, before the first
|
|
|
|
|
|
`await` in `EngineSemantic.emit`.
|
|
|
|
|
|
|
|
|
|
|
|
This **shares one propagation primitive** with the D-AG.9 trace port
|
|
|
|
|
|
(run = trace, CapabilityCall = span, **actor = baggage**) — distinct payloads,
|
|
|
|
|
|
distinct guarantees: the span export is async and loss-tolerant; the actor read
|
|
|
|
|
|
is synchronous and authoritative. Sharing the primitive avoids forking agency;
|
|
|
|
|
|
keeping the payloads distinct respects that sema cannot tolerate the
|
|
|
|
|
|
fall-to-root a tracer tolerates.
|
|
|
|
|
|
|
|
|
|
|
|
Why **explicit, not ambient**: native `AsyncContext`/ALS is the framework's own
|
|
|
|
|
|
orca mechanism, already adjudicated — in the browser (`als.ts` feature-detects
|
|
|
|
|
|
to `null`) it degrades to a root envelope with no actor, precisely the failure
|
|
|
|
|
|
this decision exists to avoid. A faithful zero-dep reimplementation is
|
|
|
|
|
|
impossible without Zone.js-style global monkey-patching (forbidden, and it
|
|
|
|
|
|
still cannot cover a bare `await`). So **ambient auto-fill is opportunistic
|
|
|
|
|
|
sugar; the explicit envelope is the guarantee** — which is exactly how
|
|
|
|
|
|
OpenTelemetry-JS actually works (baggage on a propagated context, synchronous
|
|
|
|
|
|
`StackContextManager` in browsers, `async_hooks` server-side only). This is the
|
|
|
|
|
|
industry consensus in one line: *explicit provenance bound to the message,
|
|
|
|
|
|
ambient as sugar* — OTel propagators inject/extract explicitly, CaMeL binds an
|
|
|
|
|
|
unforgeable capability tag to the value, Yjs attributes derived mutations by an
|
|
|
|
|
|
explicit per-transaction `origin`.
|
|
|
|
|
|
|
|
|
|
|
|
Scope and honesty:
|
|
|
|
|
|
|
|
|
|
|
|
- **Anti-forgery** (the reason the token is opaque): no site outside
|
|
|
|
|
|
`arts/agent` may construct an `ActorToken` or write the reserved actor key;
|
|
|
|
|
|
the token is never wire-serialized (the trace-export boundary emits a
|
|
|
|
|
|
non-authoritative `'agent'` label only). The `ActorToken` **type** lives in a
|
|
|
|
|
|
leaf below both orca and agent to avoid an orca→agent cycle; minting
|
|
|
|
|
|
authority stays in `EngineAgent`. On the bus path the actor rides the untyped
|
|
|
|
|
|
`context` bag, so its anti-forgery defense is the `agent-check` lint, not the
|
|
|
|
|
|
type system.
|
|
|
|
|
|
- **The guarantee is scoped.** It is delivered for the **explicitly-authored
|
|
|
|
|
|
A→B bridge** that threads `opts.actor`. An agent driving a stock component
|
|
|
|
|
|
through its public API has no call-site to thread it and, in the browser,
|
|
|
|
|
|
resolves to the `USER` sentinel — best-effort, out of v1. **In-scope
|
|
|
|
|
|
attribution rides the model-derived `data-actor`** paint (eidos reads the
|
|
|
|
|
|
reactive run state during `acting`), which needs no threading; the envelope
|
|
|
|
|
|
baggage is specifically for **out-of-scope secondary effects + audit**.
|
|
|
|
|
|
- **The primitive ships first, the propagation retrofit later.** The minimal
|
|
|
|
|
|
primitive (branded token + `USER` sentinel + private registry + anti-forgery
|
|
|
|
|
|
guard + synchronous `opts.actor` read) is built up front. The
|
|
|
|
|
|
~6-seam envelope-propagation retrofit (`OrcaEventMeta.actor`,
|
|
|
|
|
|
`OrcaALSContext.actor`, `ctx.emit` forwarding, `buildChildEnvelope` copy,
|
|
|
|
|
|
bus-subscription forwarding, `publishCausedBy` parent-merge) is **deferred to
|
|
|
|
|
|
the phase with a real out-of-scope async-cascade consumer**, gated by the
|
|
|
|
|
|
guard's drift check that ambient is never the sole carrier on a
|
|
|
|
|
|
cross-component bridge.
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 6. Authorization, consent and autonomy
|
|
|
|
|
|
|
|
|
|
|
|
Three levels — `suggest | review | auto` — resolved prefs-style (the app is the
|
|
|
|
|
|
ceiling; the user adjusts downward; a capability may demand *more* control,
|
|
|
|
|
|
never less; **deny-overrides**). Irreversible ⇒ `review` always.
|
|
|
|
|
|
|
|
|
|
|
|
- **Dynamic risk by payload**: the manifest declares a risk classifier over
|
|
|
|
|
|
args; `auto` escalates to `review` per invocation (same capability, different
|
|
|
|
|
|
blast radius).
|
|
|
|
|
|
- **Context origin lowers the ceiling** — the unification that dissolves
|
|
|
|
|
|
prompt-injection from an open threat into a policy row: each read carries an
|
|
|
|
|
|
origin tag (`authored-by-user | imported | third-party | other-participant`);
|
|
|
|
|
|
**any untrusted origin in the turn lowers the ceiling** (to `review`, or
|
|
|
|
|
|
`suggest` for sensitive capabilities). This is the industry pattern (forced
|
|
|
|
|
|
human approval when untrusted content is in context) expressed through
|
|
|
|
|
|
machinery already designed.
|
|
|
|
|
|
- **Initiative affects ceilings**: autonomous initiative (`system` /
|
|
|
|
|
|
`scheduled`) defaults stricter than user-requested.
|
|
|
|
|
|
- **Authorization is bound to state, not prose** (TOCTOU): review computes
|
|
|
|
|
|
against a fingerprint `F` of the relevant reads; authorization binds to `F`
|
|
|
|
|
|
**plus a TTL**; drift ⇒ recompute the diff (identical → optional
|
|
|
|
|
|
auto-re-approve; different → re-review). The user↔agent concurrency problem
|
|
|
|
|
|
is the OT/CRDT model (Yjs) — adopt the mental model, not the library.
|
|
|
|
|
|
- **Approval fatigue**: persistent grants ("always allow X") carry a TTL and an
|
|
|
|
|
|
explicit scope (session / component / act type); review shows the **computed
|
|
|
|
|
|
diff, not the plan's prose**. A `capabilities-changed` event re-gates grants.
|
|
|
|
|
|
- **perm** governs only server-touching scopes (enforced in the proxy /
|
|
|
|
|
|
server-side tool-loop); the base case is local consent with no perm
|
|
|
|
|
|
dependency. **`reads` are permission subjects symmetric to `acts`** —
|
|
|
|
|
|
sensitive components (credentials/passwords) never register reads.
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 7. Semantics, presence and accessibility
|
|
|
|
|
|
|
|
|
|
|
|
- The motor **emits nothing** (an art with no DOM); it exposes the run as
|
|
|
|
|
|
reactive state. **Surfaces** declare the cycle in their morfos (`delegate-*`);
|
|
|
|
|
|
`sustain-processing` belongs to **Aura** (state-bound persistence, cleared on
|
|
|
|
|
|
run close). **Actuated components** concrete `delegate.act` via
|
|
|
|
|
|
`allowedFamilies` with the actor context.
|
|
|
|
|
|
- **A run above `suggest` requires a mounted presence surface** (a minimal
|
|
|
|
|
|
Aura). A run in `acting` with nowhere to emit its cycle is perceptually
|
|
|
|
|
|
invisible — a direct contradiction of *"¿quién actúa?"*. The motor refuses
|
|
|
|
|
|
(or warns) on entering `acting` without one; this is mechanically verifiable.
|
|
|
|
|
|
- **Write-scope is declared**: a run declares its scope (component | part |
|
|
|
|
|
|
range); hold and paint apply only there.
|
|
|
|
|
|
|
|
|
|
|
|
The **a11y contract** — no framework has this; documenting it fixes the pattern
|
|
|
|
|
|
others will cite:
|
|
|
|
|
|
|
|
|
|
|
|
1. **One `polite` live region owned by Aura**; announcements **attributed**
|
|
|
|
|
|
("Agente: …") and **coalesced by plan/batch** — never per delta, never per
|
|
|
|
|
|
act (WCAG 4.1.3).
|
|
|
|
|
|
2. **No focus-theft — a motor invariant** (WCAG 3.2.1 / 3.2.2), not each
|
|
|
|
|
|
surface's courtesy.
|
|
|
|
|
|
3. `aria-busy` on the region being mutated during streaming; a completion
|
|
|
|
|
|
announcement on close.
|
|
|
|
|
|
4. Elicitations are **dismissible / postponable**, not modal by default
|
|
|
|
|
|
(WCAG 2.2.4).
|
|
|
|
|
|
5. **A global keyboard exit** (an Esc-like doctrine): cancel / return reachable
|
|
|
|
|
|
without a mouse. Aura uses `reduce: 'static-frame'`, never `hide`.
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 8. Threat model
|
|
|
|
|
|
|
|
|
|
|
|
The axis builds, by construction, the classic **"lethal trifecta"** (Willison):
|
|
|
|
|
|
private data + untrusted content + the ability to act. The doctrine treats it
|
|
|
|
|
|
head-on:
|
|
|
|
|
|
|
|
|
|
|
|
- **Prompt injection.** Reads carry an **origin tag** (per §6); untrusted
|
|
|
|
|
|
origin lowers the autonomy ceiling (the primary mitigation, folded into
|
|
|
|
|
|
policy). Adapters **spotlight** (delimit/mark) non-authored content so the
|
|
|
|
|
|
model treats it as data. Reserved for depth: dual-LLM (a privileged planner
|
|
|
|
|
|
that never sees untrusted content; a quarantined model that returns only
|
|
|
|
|
|
symbolic references) and CaMeL-style capability/data-flow tracking —
|
|
|
|
|
|
philosophically close to the framework's structural ports. Checklist anchors:
|
|
|
|
|
|
OpenAI instruction-hierarchy, OWASP LLM Top 10 (LLM01).
|
|
|
|
|
|
- **TOCTOU.** Authorization bound to a read fingerprint + TTL (§6).
|
|
|
|
|
|
- **Actor forgery.** The opaque engine-minted token + the `agent-check` guard
|
|
|
|
|
|
(§5).
|
|
|
|
|
|
- **Run recovery.** A minimal **write-ahead journal per run** via `$storage`
|
|
|
|
|
|
(sessionStorage suffices in v1) records authorizations + applied acts and
|
|
|
|
|
|
detects orphaned runs on reload. The audit-trail is defined **now** as an
|
|
|
|
|
|
OTel-shaped trace port (run = trace, CapabilityCall = span); the storage
|
|
|
|
|
|
vehicle arrives later. (orca cannot be a store — its own rule.)
|
|
|
|
|
|
- **Kill switch, multi-user, i18n.** A global disable (§2). User identity in
|
|
|
|
|
|
the actor vocabulary is reserved (multi-user arrives with `connection`). The
|
|
|
|
|
|
agent's `identity` / system-context carries the effective locale; the agent
|
|
|
|
|
|
announces in the langs-axis language like any surface.
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 9. What this axis is NOT
|
|
|
|
|
|
|
|
|
|
|
|
- **Not a chat.** Chat is one surface (a participant + a composer) that chains
|
|
|
|
|
|
runs; the axis works with no conversation at all.
|
|
|
|
|
|
- **Not an LLM integration.** It is a theory of delegation; a model is one kind
|
|
|
|
|
|
of actor. Nothing depends on a provider SDK (adapters are isolated and
|
|
|
|
|
|
optional).
|
|
|
|
|
|
- **Not a parallel "AI mode".** It preserves every framework invariant —
|
|
|
|
|
|
dependency direction, semantics, events, public API, undo, a11y — instead of
|
|
|
|
|
|
forking them. A component with a manifest is the same component.
|
|
|
|
|
|
- **Not a component that knows components.** It sees capabilities, never types.
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 10. To go deeper
|
|
|
|
|
|
|
|
|
|
|
|
- Vocabulary of `delegate` (families, verbs, intent policy): [`CANON.md`](../CANON.md).
|
|
|
|
|
|
- The whole-system layering the axis plugs into:
|
|
|
|
|
|
[`architecture/active-architecture.md`](./active-architecture.md).
|
|
|
|
|
|
- The arts pattern (`Engine*` / `Active*`, ports, degradation):
|
|
|
|
|
|
[`arts/README.md`](../../src/arts/README.md).
|
|
|
|
|
|
- Execution record, signed decisions, phases:
|
|
|
|
|
|
[`process/PLAN-agent.md`](../process/PLAN-agent.md).
|
|
|
|
|
|
- The external critique that hardened this doctrine:
|
|
|
|
|
|
[`process/TRIAGE-revision-externa-agente.md`](../process/TRIAGE-revision-externa-agente.md).
|