Company Navigator
One machine-readable interface over Company OS capabilities for agents. It is a projection plus a receipt-backed action lifecycle; it owns no table, no dashboard, and no execution path. Everything lands in the canonical ledger: tenant admission, SCOPE_TASKS authority, create_task_tx, and governance_events.
Source: src/company_os/company_navigator/ (mod.rs catalogue and router, context.rs entity resolver, lifecycle.rs action lifecycle and gaps, coverage.rs freshness map, tests.rs database-backed contracts). Outcome Radar integration lives in src/company_os/outcome_radar.rs; Capability Home embeds the coverage map in src/company_os/capability_home.rs.
All routes sit under /api/company/companies/{company_id}/navigator and require a company-bound principal token. POST routes additionally pass the standard mutation admission (SCOPE_TASKS).
Routes
| Method | Path | Purpose |
|---|---|---|
| GET | /capabilities | Catalogue: input/output schemas, effect, risk, approval, prerequisites, entity types, idempotency, examples, readiness, expected receipts, lowering. |
| GET | /capabilities/{id}/explain | explain step: what a capability does, what it needs, who approves, which receipts prove it ran. Records nothing. |
| GET | /context?ref=<domain>:<selector> or ?q=<text> | Cross-domain entity context with aliases, related entities, and store coverage. |
| GET | /coverage | Coverage and freshness map: domains, connectors, business sources, mail queue, open capability gaps, what cannot be performed and why. |
| GET | /actions | Recent actions with derived status and next action. |
| POST | /actions/plan | plan step. Body: {capability_id?, input, owner_persona?, priority?, due_at?, business_impact?}. |
| GET | /actions/{action_id} | Current envelope of one action. |
| POST | /actions/{action_id}/preview | preview step: the exact task that would be created. |
| POST | /actions/{action_id}/approve | approve step. Body: {decision: approve|reject, note?}. |
| POST | /actions/{action_id}/execute | execute step: one canonical task through create_task_tx. |
| POST | /actions/{action_id}/verify | verify step: proves task and receipts are bound. |
Action lifecycle
explain → plan → preview → approve → execute → verify
- The
action_idis the SHA-256 of the canonical plan input (company, capability, intent, sorted entity bindings, sorted evidence refs). Same input, same action; re-planning never writes a second receipt. - Every step is a
governance_eventsrow withsubject_type = navigator_actionandsubject_id = action_id. Receipt actions:company_navigator_action_planned,_previewed,_approvedor_rejected,_executed,_verified. Task creation addstask_created. - Approval requires an active owner/admin who is not the planning principal (separation of duties). Rejected actions cannot execute.
- Execute is idempotent: the executed receipt carries the task id, and the task is deduplicated by
navigator:<action_id>. Outcome Radar's acceptance of anavigator:proposal calls the sameexecute_action_tx. - Global safe mode returns the plan as a
blocked_safe_modeenvelope without writing anything.
Every step returns one envelope (hsm.company_os.navigator_action.v1): action_id, capability_id, step, status, entity_bindings, changed_state (task id, display number, state, task preview), evidence (evidence refs, receipts, verification checks), receipt_ids, approval, and next_action.
Entity references
<domain>:<selector>. Selectors: a UUID, #<display_number> for tasks, email:<address>, external:<id>, or a bare natural key.
Domains with a canonical store: client (company_customers), request (customer_requests), task (tasks), message and thread (company_email_operator_queue), order, ticket, invoice (company_*), action (navigator receipts). opportunity is computed by Outcome Radar.
Domains with no store in Company OS: property, unit, lease, resident, vendor, inspection, incident, compliance, deal, visit, document, case. These bind by reference. The lowered task carries {"kind":"label","ref":"entity:<domain>:<selector>"} in capability_refs, so /context?ref=property:velora-12 still joins to its tasks and actions through the ledger.
Capability gaps
When plan receives no capability id (or an unknown one), the navigator records company_navigator_capability_gap with subject_type = capability_gap and subject_id = fingerprint. The fingerprint hashes the requested capability, the entity kinds, and the normalized intent terms, so rewordings of the same ask collapse. Frequency is the receipt count per fingerprint. Each receipt keeps the attempted intent, the missing tool or data, business impact, DRI, and suggested catalogue capabilities.
Open gaps appear in /coverage and in Outcome Radar as gap:<first receipt id>. Accepting one creates the deduplicated missing-capability task (dedupe key capability-gap:<fingerprint>).
Outcome Radar sources added
Proposal ids keep the <prefix>:<uuid> convention:
| Prefix | Source | Proposal |
|---|---|---|
connector | company_connectors in error/degraded or failed after last success | Repair connector |
source | company_business_sources degraded/error or non-manual and stale over 7 days | Refresh source |
mail | company_email_operator_queue pending over 24 hours | Answer waiting email |
navigator | planned actions with an approval and no execution/rejection | Execute approved action (accept executes it) |
gap | capability gaps grouped by fingerprint | Close capability gap |
Property operations pack
Nine capabilities under company_os_property_operations_pack: property.portfolio.context, property.lease.renewal, property.resident.followup, property.maintenance.triage, property.vendor.coordinate, property.inspection.schedule, property.finance.review, property.compliance.deadline, property.incident.respond. Each lowers to one canonical task through the lifecycle with approval required; property entities bind by reference.
Verification
cargo test --lib -- company_navigator:: outcome_radar:: capability_home:: with DATABASE_URL set. The database-backed tests cover the read gate, the full lifecycle, the Radar hand-off, gap deduplication, safe mode, and the entity resolver.