VIRGO

Persona capability surface

Source
docs/design/PERSONA-CAPABILITY-SURFACE-V1.md
Pinned at
d62e85485903a5537ee2b73c14201597e29bdaa5
sha256
39151a737f91ef3d2f5cd4402e1d52813b12c436e372cbc74f3eda2f54a49ab2

This page is the specification itself, rendered from the pinned source above. Its text is reproduced exactly; only its presentation is added.

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, cross-project, 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 bundlesecretaryteam-coordinatorproject-leadcoder-deputy
standard workspace and coordinationR/WR/WR/WR/W
peer verification and presenceR/WR/WR/WR/W
bounded graph context queryRRRR
decisions: list / raiseR/WR/WR/WR/W
decisions: resolveW¹W²W-
tasks: list / get / reportR/WR/WR/WR/W
tasks: assignWWW-
runs and artifactsRRR/WR/W (assigned task)
human messages, replies, ack, typingW (bound surfaces)W (bound surfaces)--
reaction catalogue and applyWW--
cards, todo cards, file sendWW--
human-surface/gateway statusRRRR
deployment/publicationCCCC

Human-surface tools target the hub service through virgo-channel; persona stamps contain bindings, never Microsoft 365 tenant 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 role/class profile plus persona path into one stamp. The factory has NO address default of its own: it materializes the persona's canonical registered address, which is a two-segment path for reserved-root and scope-wide roles (root/secretary, work/coordinator) and carries the project segment only for project duties (work/core/lead). The first persona of an installation defaulting to root/secretary with the suggested first-persona name suggestion belongs to virgo persona add and to nothing else — a factory that carried its own default could stamp an address the registry never registered;
  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 root/workspace/project/role hierarchy is encoded by capability-stamp schema v3. The runtime remains an explicit reader for existing v1/v2 stamps and maps their capability class to a canonical role path. New factory output is always v3; old stamps are never rewritten in place.

The repository's first factory projection is scripts/build-capability-stamp.mjs. It takes persona identity, composition hash, scope/project/role path, 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.