VIRGO · SPEC
Persona Capability Surface v1
Approved 2026-08-04. The contract that gives a persona its tools and permissions in one factory stamp.
# Persona capability surface v1 Status: approved by Henry on 2026-08-04 This contract defines the factory stamp that gives a persona its runtime tools and permissions. It deliberately replaces per-incident tool additions and per-tool prompt opening. ## One stamp, three consumers The factory writes one owner-private `CAPABILITY-STAMP.json` into each active persona generation. The stamp is immutable for that generation and is covered by its composition hash. Three runtime components consume the same records: 1. the MCP/channel server exposes exactly `tools[].name`; 2. the handler authorizes the matching `tools[].handler_action`, `access`, and `scope`; and 3. the launcher passes exactly `tools[].name` as its tool allowlist. No component keeps a second hand-written allowlist. Startup fails if the stamp is missing, malformed, has duplicate names/actions, or cannot be projected to all three consumers without loss. ## Policy shape The default is positive: ordinary, recoverable work inside the persona's own declared scope is allowed. A tool is present only when its class needs it. An exposed tool has `access: allow` or `access: confirm`; denied capabilities are not exposed. Only these global boundaries exist in v1: - confirm credential or permission changes; - confirm destructive or materially irreversible operations; - confirm consequential external publication or deployment outside standing delegation; - deny reading or exporting secret credential values; - deny exporting lease/fence/authority material; and - deny cross-workspace or cross-persona access outside an explicit binding. An exact blocked operation may be learned through the prompt registry. The stored choice is keyed by stamp hash, handler action, normalized target scope, and operation shape. It cannot broaden the class profile or survive a changed stamp without review. Confirmation is routed, not inferred. A global-boundary confirmation goes to the persona's bound human authority through `virgo-channel`; a deputy-scope confirmation goes to the owning lead. The decision record stores the requester, authority binding, normalized operation, stamp hash, decision, and correlation id before execution. A model cannot confirm its own request. Learned prompt fingerprints live in the persona experience layer. A prompt that is genuinely class-common may instead live in the shared class overlay. Both locations travel with the snapshot; machine-local session memory is not a prompt registry. ## Standard ordinary surface Every persona class receives: - workspace listing, metadata, hash, and paginated/ranged reads; - atomic writes to the mutable paths declared in its own workspace binding; - coordination inbox list/ack, broker send, wake reconciliation, presence summary/activity, peer listing, and redacted sender lookup; - decision list/raise and task list/get/report for work it owns; - read-only bounded graph context queries; and - read-only access to the persona's own conversation-archive lineage through the graph query service (other personas' archives remain out of scope); and - a delivery envelope containing registry-derived sender project, agent, peer id, and instance/fence provenance. Labels are attribution, not authority. Workspace writes are recoverable and confined by the materialization stamp. For a normal persona this includes `QUEUE.md`, `DECISIONS.md`, `FINDINGS.md`, and `memory/**`; class overlays may add project worktrees. Reads support byte offset and length and return continuation metadata, so a large operational file never becomes unreadable. Human-surface reactions return a definitive terminal result: `applied: true` or `applied: false` with a reason. `unknown` is not a terminal success and remains retryable under the same correlation id. ## Class matrix `R` means read/use, `W` means mutate within stamped scope, `C` means the tool is exposed but requires confirmation for the described boundary, and `-` means it is not exposed. | Capability bundle | secretary | team-coordinator | project-lead | coder-deputy | | --- | --- | --- | --- | --- | | standard workspace and coordination | R/W | R/W | R/W | R/W | | peer verification and presence | R/W | R/W | R/W | R/W | | bounded graph context query | R | R | R | R | | decisions: list / raise | R/W | R/W | R/W | R/W | | decisions: resolve | W¹ | W² | W | - | | tasks: list / get / report | R/W | R/W | R/W | R/W | | tasks: assign | W | W | W | - | | runs and artifacts | R | R | R/W | R/W (assigned task) | | human messages, replies, ack, typing | W (bound surfaces) | W (bound surfaces) | - | - | | reaction catalogue and apply | W | W | - | - | | cards, todo cards, file send | W | W | - | - | | human-surface/gateway status | R | R | R | R | | deployment/publication | C | C | C | C | Human-surface tools target the hub service through `virgo-channel`; persona stamps contain bindings, never channel credentials or gateway setup. ¹ A secretary resolves a decision only as a durable relay of the bound human authority's explicit decision. ² A team coordinator resolves only when the bound lane approver authorizes that decision. Neither class self-originates a resolution. ## Required tool inventory Tool names are transport-neutral public contracts. A v1 factory must resolve the following names for each class according to the matrix: - workspace: `workspace_list`, `workspace_stat`, `workspace_hash`, `workspace_read`, `workspace_write`; - identity/presence: `list_peers`, `lookup_sender`, `set_summary`, `set_activity`, `reconcile_wake`; - coordination: `send_broker_message`, `list_coordination_messages`, `ack_coordination_message`; - decisions: `list_decisions`, `raise_decision`, `resolve_decision`; - tasks: `list_tasks`, `get_task`, `report_task`, `assign_task`; - runs: `list_runs`, `get_run`, `create_run`, `advance_run`, `append_run_event`, `record_artifact`; - knowledge: `query_graph_context`; - human surface: `send_human_message`, `reply_human_message`, `ack_human_message`, `start_typing`, `stop_typing`, `list_reaction_ids`, `apply_human_reaction`, `send_human_card`, `send_human_todo`, `send_human_file`, `get_human_surface_status`. The stamp may add versioned tools later, but cannot silently omit a required tool for its class. Boot validation reports the exact missing tool and refuses to advertise the persona as standing. ## Factory and runtime acceptance The factory must: 1. resolve the class profile plus persona bindings into one stamp; when no workspace is supplied, bind the persona to the installation's implicit default workspace `home` (the control plane remains workspace-free); 2. validate it against the JSON Schema and semantic validator; 3. hash it into the persona composition; 4. derive all three consumer projections from that exact file; and 5. prove at boot that every handler and transitive runtime binding exists. The repository's first factory projection is `scripts/build-capability-stamp.mjs`. It takes persona identity, composition hash, workspace, graph namespace, and human-surface bindings as input and emits one private stamp for any of the four classes. The JSON Schema and semantic validator both run before the file is emitted; the runtime consumers remain the next integration step. Acceptance tests must prove projection equality, all required class tools, default-allow recoverable workspace work, ranged reads, strict scope binding, definitive reaction outcomes, prompt-registry exact matching, and loud refusal for each global boundary.