Mira does not get a new "save" path. Its command lands on the same
proposed → accept/reject rail Vega ambient builds already use: one
appended source='agent' version whose changed field the app
shows as proposed, and counsel Confirms (the existing
accept_field) or Rejects (reject_field). No new
ratify surface. The broker is the interactive one โ the clerk worker
(pramaan-docs ADR-110 T6) โ so the landing hangs off the run's terminal
turn.completed, exactly where Vega's ambient landing hangs off
the framer worker's completion.
Think of every frame version as a commit. Mira builds its command against
version v5 (its base). By the time the command comes
back, a Vega build may have committed v6. The broker does not
force-push Mira's v5+edit over v6. It
rebases: it takes only the one field the command changed
and replays it on top of v6, producing v7.
v6's other fields survive; the command's scoped edit still
applies. base == current is just the trivial rebase (a fast-forward).
v5 โโ (Vega) โโโถ v6 command built on v5, scope = "issues"
โ โ
base โโโโโโ โโโโโ current (re-base target)
โ
changed = {issues} (broker-owned diff: proposed vs v5)
โผ
v7 = v6 with issues replaced by the command's issues
(v6.core_dispute preserved โ never a silent overwrite)
All of it runs under one FOR UPDATE lock on the matter row
(allocate_next_frame_version), so two writers queue instead of
racing max(version).
MatterFrameService.ingest_command_frame(matter_id, req):
proposed = validate(req.envelope.frame) # the FrameOutput Mira produced
if matter fully locked -> skipped_locked
version = allocate_next_frame_version(...) # FOR UPDATE on the matter row
current = latest frame # the re-base target
base = frame at req.base_frame_version # what the command SAW
changed = { f in EDITABLE_FIELDS : proposed[f] != base[f] } # broker owns the diff
verify changed โ scope # ยง5.1 invariant; drift -> typed reject
landed = { ...current, **{ f: proposed[f] for f in changed } } # re-base overlay
landed = restore field locks (locked value wins; drop from changed)
if not changed -> no_change # nothing to propose
append source='agent' version(landed) + resolution.command{scope,changed,base,rebased}
emit audit (actor=agent) + domain event matter_frame.updated
| Surface | Change |
|---|---|
MatterFrameService.ingest_command_frame |
New landing. Broker-owned canonical diff (proposed vs the base version), scope verification, stale-base re-base onto the current frame, field-lock overlay, append as a proposed source='agent' version. Reuses the Vega rail's canonical resolution, audit, and event. |
MatterFrameCommandIngestRequest |
The landing DTO: agent_run_id, base_frame_version (the generation-CAS token, not the matter_frame_jobs lease), scope, command_text, envelope. |
clerk_worker/mira_command.py |
The broker seam: opens the firm-scoped transaction and adapts a launch command + turn.completed into the landing request. Injected as ClerkDeps.land_command_frame (default no-op keeps the loop unit-testable). |
clerk_worker/runner.py |
On a kind='mira_command' terminal turn the frame is landed before it is pushed, so counsel never sees a proposal that failed to persist; a landing error fails the run closed. Per-route cost cap: _effective_cost_cap gives the command route command_cost_cap_usd (default $1.50) while every other route keeps the global $0.50. _invoke_brain builds the command envelope (input passthrough, no atlas coercion). |
agent_contracts/invoke.py |
TurnKind gains mira_command so the broker's agent_invoke.v1 accepts and routes the command turn (requires input, forbids dock_chat โ the existing validators already fit). |
| Criterion | Where it is proven |
|---|---|
| Command proposal appears as a frame version for Confirm/Reject | test_command_lands_as_proposed_version_and_reject_discards โ lands a version, then reject_field (the existing rail) discards it. |
| Confirm promotes; Reject discards | Same test + the existing Story-1998 accept_field/reject_field rail (unchanged; the landed version is shaped like a Vega proposal). |
| Stale base re-based, never silently overwrites | test_stale_base_command_rebases_and_never_overwrites_newer_version โ command on v1 re-bases onto v2; v2's newer field survives. |
| Per-route cost cap enforced | test_command_route_uses_its_own_cost_cap_not_the_global โ the same cost aborts under a tight command cap and succeeds under a generous one even when the global cap is tiny. |
| Empty first-run state | test_command_on_empty_first_run_lands_v1 โ a matter with no frame yet lands v1. |
| Scope drift rejected | test_command_out_of_scope_is_rejected_never_landed โ a change outside scope raises; nothing lands. |
The landing reuses the registry-approved ManualSpanName.MATTER_FRAME_INGEST
span (the same domain op as Vega's ambient ingest) parented to the command's
trace carrier โ no new span name, no raw tracer call. Cost/usage stay on the
broker's existing stream instrumentation.
The Mira runtime that produces the command turn is
pramaan-agents Story-C; the CCB that fires the command and the
WS agent-key→rail routing are Story-F. This Story is the broker landing:
once a mira_command run streams through the clerk worker, its
proposed frame is persisted on the existing rail.
uv run ruff check src tests set -a; . ./.env.test-db; set +a uv run pytest tests/integration/test_mira_command_landing.py -q uv run pytest tests/unit/clerk_worker/test_runner_mira_command.py -q uv run pytest tests/unit/agent_contracts tests/unit/clerk_worker tests/contract -q make openapi # app-api.json: WS kind enum gains "mira_command"
Recall in one sentence: a Mira command is a proposal that the broker rebases โ one scoped field replayed onto the current frame and appended for Confirm/Reject โ so counsel's edit and a concurrent Vega build never overwrite each other.