{"documentation":"# Orient working guide\n\nOrient is a mind-map project management system: work lives as nodes on shared maps, every node carries state, and progress rolls up the tree. People and their AI agents plan and work on the same maps. You are reading this without a credential: it is the guide every enrolled agent works from, with the way in first. Once you hold a key, `GET /api/guide` answers the same guide minted for the areas you reach. The Orient skill needs no credential either: with your person's consent, `orient skill install` writes it now, before they approve you, and `orient skill update` refreshes it any time.\n\n## Getting access\n\nYou work in Orient for a person who has an account (free to start at https://app.orient.day). Ask them for access in one step; they approve with one tap of their passkey and choose the areas you reach and for how long:\n\n- With the CLI: install it with `curl -fsSL https://app.orient.day/api/cli/install.sh | sh` (Windows: `irm https://app.orient.day/api/cli/install.ps1 | iex`), then run `orient auth request --name \"\u003cyour name\u003e\"`. It prints a link: give it to your person. Run the same command again to wait for their approval; it stores your key and proves it.\n- Over HTTP: `POST /api/agent-requests` `{\"name\": \"\u003cyour name\u003e\"}` with no credential answers `claimUrl` (give it to your person), `pollToken` and `pollUrl`. Poll `GET /api/agent-enrollment/\u003cpollToken\u003e` every few seconds: `awaiting-person`, then `pending-approval`, then `active` with your `key`, delivered exactly once. The answer's `documentation` says how to store it.\n- If your person already gave you an enrollment or invite link, use that instead: `echo \"\u003cthe link\u003e\" | orient auth login` (an invite also needs `--name \"\u003cyour name\u003e\"`).\n\n## How to plan here\n\nOrient encodes a planning method — follow it, and explain the plan in these terms when your owner asks:\n\n- Titles are labels of 1–4 words, never sentences, and never numbered — no `1 - ` or `2 · ` prefixes; sibling order IS the sequence, and a dependency edge says what must finish first. Everything longer belongs in notes. The server answers a title of five or more words with a warning, and refuses an agent's title past 8 words or 60 characters: keep the label short and put the sentence in the notes (`orient node add \"\u003clabel\u003e\" --area \u003careaId\u003e --notes \"\u003ctext\u003e\"`).\n- A task is one concrete, doable action whose completion can be explicitly declared done and verified. A bucket of work is not work: if a node reads like a workstream, define the actual tasks beneath it — you cannot do a branch, you can only do tasks, and a plan left as high-level branches cannot be tracked.\n- Effort is `durationMinutes`: the working time of whoever does the task, at their speed. Grade each task by its assignee — an agent's task at agent speed, a person's task at a person's speed — and never grade an agent's task by how long a person would take, nor a person's by how fast an agent would do it. A task a person and an agent share is two tasks: split it, one for each. Set it with `orient task schedule \u003ctaskId\u003e --area \u003careaId\u003e --duration \u003cminutes\u003e`.\n- Effort must be gradeable, and the band follows the doer. A person's task is gradeable from 15 minutes up to a few hours; 12 hours is the rare ceiling. An agent's task is gradeable from a minute or two up to about an hour; two hours is the rare ceiling. If you cannot grade a task inside its doer's band, it is too big — split it into child tasks until every leaf is gradeable. A task shorter than its band is graded at what it takes, but the floor is not a target: a leaf is never smaller than something that can be declared done and verified on its own. The band is the method, not a refusal: the server accepts any whole number of minutes up to a year.\n- Effort counts working time only. Waiting is not effort: when the plan tracks a review, it is the reviewer's task, graded at the reviewer's speed, and anything else the work waits for is a dependency edge, or a block with its reason when the work cannot proceed now, not minutes on the task; a date known ahead belongs in the milestone's window. When a task changes hands between a person and an agent, grade it again. Until you have measured, start an agent's grades here: a page of text or a small change is minutes, a change with its checks is tens of minutes. Then grade from what you have measured: when a task of yours is done, compare the time it took with its grade and correct the open tasks like it.\n- Tasks on an area carry no dates. When work must land by a date, the date lives on a project's ladder — the project, each of its phases and each milestone carry a start→due window (the delivery section below). Never write a date from your host clock: resolve it first — `orient task resolve today` (or `POST /api/schedule/resolve`) answers the account's day in their time zone.\n- Every task carries an assignee, and a PBI exactly one (the planning standard below). Unowned work is not planned work.\n- Effort and doing live only on terminal tasks — the leaves. A branch is not worked by anyone: it encompasses its children, and its progress and effort are computed from them. There is no separate subtask concept — structure is nesting, and a task under a task is just the plan getting more precise.\n- Not knowing how to approach something IS the signal to split it further.\n- Group one coherent piece of work as a branch, then split it into child tasks until every leaf is gradeable and its done state is verifiable. Attach the documents that carry its intent — the why, the constraints, what done looks like — to the branch and the leaves they cover (`orient doc create \u003cnodeId\u003e --title \"\u003ctitle\u003e\"` / `POST /api/nodes/{id}/documents {title}`), so the intent travels with the work.\n- Notes carry the context: one on-point paragraph in the plan's own terms — terse and complete, no filler.\n\n## The planning standard\n\nEvery area plan follows one standard; the server checks four of its rules (below):\n\n- Outcome: the area's root names what the whole plan delivers; read it first and plan only work that serves it.\n- Epics: the nodes straight under the root, each one part of the outcome: `orient node add \"\u003ctitle\u003e\" --area \u003careaId\u003e --kind reference`; a deployable part may be a component.\n- Features: the nodes between an epic and its PBIs, added the same way with `--parent \u003cepicId\u003e`. An epic or feature holds features or PBIs, never both.\n- PBIs: a task whose parent is not a task: a piece of its epic or feature that can be declared done and verified. Its acceptance criteria are a field of their own, short checks that prove it done: `orient node add \"\u003ctitle\u003e\" --area \u003careaId\u003e --parent \u003cparentId\u003e --criteria \"\u003ccheck\u003e\"` (repeat it); notes hold context only. Where the workflow has a Defined stage, a PBI is ready from Defined on. Tasks beneath a PBI are its steps.\n- The 100% rule: each level holds all of its parent's work and nothing else: the epics are the whole outcome, an epic's features or PBIs the whole epic. At every level ask whether the parent is done once each child is.\n- One assignment per PBI: each PBI has exactly one assignee, the doer who answers for its acceptance criteria. `orient task assign \u003ctaskId\u003e \u003caccountId\u003e --area \u003careaId\u003e` makes that doer the only one; `--me` adds you beside others, so use it on an unassigned PBI. Shared work is two PBIs.\n\nEach rule has an id the API, the CLI and the MCP tools name, and its message begins `WBS rule,`. `orient node tree \u003careaId\u003e` and `orient node show \u003cnodeId\u003e --area \u003careaId\u003e` print the flags beside the nodes; `GET /api/maps/{id}/wbs` answers `{wbs: {mapId, flags: [{nodeId, rule, message}]}}`, and `?node=\u003cnodeId\u003e` reads one node's. Project maps carry none, and a flag never stops a map from reading. Read the flags before you hand a plan over: it meets the standard when there are none.\n\n- `rootHoldsEpics`: a task never goes straight under an area's root. Your create, move or retype that puts one there is refused; one put there from the web app is kept and flagged. Fix: put it inside an epic, `orient node move \u003ctaskId\u003e --area \u003careaId\u003e --parent \u003cepicId\u003e`.\n- `oneKindPerLevel`: a node whose children mix epics or features (a component, or any node with children that is not a task) with items (tasks, and notes with nothing under them) is flagged, the root included; an epic or feature with nothing in it yet counts as a note. Fix: give the loose items an epic or feature of their own and move them into it, and fill or remove empty ones.\n- `acceptanceCriteria`: an open PBI that is not ready is flagged, and starting it (`orient task start \u003ctaskId\u003e --area \u003careaId\u003e`) answers a warning while the start still lands. Where the area's workflow has a stage keyed `defined`, ready is the stage: Defined or later. Elsewhere ready is the field: its acceptance criteria hold a check. Notes carry no rule. A PBI that reads done (`rolledCompletion` 100) is never flagged or warned for it. Fix: `orient task criteria \u003ctaskId\u003e --area \u003careaId\u003e --check \"\u003ccheck\u003e\"` sets the criteria, and `--defined` moves it to Defined in the same write.\n- `doneRollsUp`: a task with tasks beneath it is done when they are. Marking it done is refused while a task beneath it is open, its `rolledCompletion` and the done counts follow its tasks, and one marked done before the rule is flagged. Fix: finish the open tasks beneath it, or move out the ones that belong elsewhere.\n\n## Practice gates\n\nAn owner may switch practices on for a node of an area or a project, and Orient then enforces them for everyone, you included. Each is off until switched on; an area with none works as before. `orient node gate show \u003cnodeId\u003e --area \u003careaId\u003e` (`GET /api/nodes/{id}/gates`) lists the five at a node — off, on here, or inherited from the node above that holds it — and the stage each holds at. Read it before you start work under a node.\n\n- `charter` — Charter approved: work under the node starts only once its charter is approved. The charter's owner or sponsor approves it: `orient doc charter approve \u003cdocumentId\u003e`.\n- `ready` — Ready to start: where the area's workflow has a Defined stage, a PBI enters the gate's stage only from Defined on, and enters Defined itself only with acceptance criteria; elsewhere it starts only once its acceptance criteria hold a check (`orient task criteria \u003ctaskId\u003e --area \u003careaId\u003e --check \"\u003ccheck\u003e\"`).\n- `proof` — Proof at done: a PBI is done only when it asks for proof and each proof is attached: `orient task needs \u003ctaskId\u003e --area \u003careaId\u003e --needs \"text: …\"`, then `orient task prove \u003ctaskId\u003e p1 --area \u003careaId\u003e --text \"\u003ctext\u003e\"`.\n- `scope` — Scope changes recorded: a change to an approved charter goes in as a scope change with its reason, made by its owner or sponsor: `orient doc blocks put \u003cdocumentId\u003e --scope-change \"\u003creason\u003e\" --json '{\"ops\":[{\"op\":\"update\",\"id\":\"\u003cblockId\u003e\",\"block\":{\"kind\":\"paragraph\",\"text\":\"\u003ctext\u003e\"}}]}'`. `orient doc charter history \u003cdocumentId\u003e` lists every approval and scope change with who approved it.\n- `mov` — MOV measured at close: a project closes only with its charter's MOV target and the measured result beside it: `orient project close \u003cprojectId\u003e --measured \"\u003ctext\u003e\"`; `orient project closure \u003cprojectId\u003e` reads the target first.\n\nIn an area with a workflow, `charter` and `ready` hold at a stage the owner names from that area's own list: moving an item into that stage or a later one, or starting work on it before then, is what they guard. Without a workflow they hold at the start of work. A refusal is 409 `practiceGate`: its message names the gate and the node holding it, `gate` carries the key, and the hint says what would satisfy it — do that, then repeat the move. Owners and admins switch gates with `orient node gate on \u003cnodeId\u003e ready --stage delegated --area \u003careaId\u003e` (`--stage` only in a workflow area, naming one of its stages; `PUT /api/nodes/{id}/gates/{gate}`) and `orient node gate off \u003cnodeId\u003e ready --area \u003careaId\u003e`; an agent may switch a gate on, never off.\n\n## When the work is a delivery — projects, phases, milestones, components\n\nRead this section when your owner runs a delivery here: a product, a release, a programme with dated milestones. On a personal or everyday area the method above is the whole of it — do not mint projects or components your owner did not ask for.\n\n- Delivery lives in standalone projects, each its own map: mint one from an area you hold with `orient project create \u003careaId\u003e \"\u003cname\u003e\"` (`POST /api/maps/{areaId}/projects` `{name}`) — your owner owns it and your key gets admin — and it rides `orient project list` / `GET /api/maps` with kind `project`. On a project map the root holds phases (a new root child births as a phase) and a phase groups milestones; milestones do not nest, and a phase is the only grouping above them. Never add children to a milestone on the project map: attach area work to it instead — a bare child there births a project-side component that no work can ever ride, and components are marked on the area map. The project root, each phase and each MILESTONE carries the window (a start and a due date) — the due is the commitment — and a milestone's progress is computed from the attached work, never written. `orient project show \u003cprojectId\u003e` renders the whole ladder; `orient project milestones \u003cprojectId\u003e` lists the windows. When the plan changes and a project you minted is no longer wanted, detach its work and park it with `orient project archive \u003cprojectId\u003e` (`PATCH /api/maps/{projectId}` `{\"archived\": true}`): it leaves the shelf and turns read-only — it refuses attach, moves and edits, while detach still lets work leave — and `orient project unarchive \u003cprojectId\u003e` brings it back. You may archive only a project you minted and still administer, and only while no work is attached to its milestones — the refusal says so; your owner can archive any project.\n- The work itself stays on the area maps and ATTACHES to milestones: `orient project attach \u003cnodeId\u003e --project \u003cprojectId\u003e --milestone \u003cmilestoneId\u003e --area \u003careaId\u003e` (`POST /api/nodes/{id}/milestone-binding` `{projectMapId, milestoneId}`) attaches an area node AND the branch beneath it — descendants ride along and new area-side children keep riding, though a nested area inside the branch does not ride, while a descendant's own binding outranks the inherited ride (one milestone per project — re-window with `orient project move \u003cnodeId\u003e --project \u003cprojectId\u003e --to \u003cmilestoneId\u003e`, not a second attach, which is refused until you detach; a node may attach to several projects); `orient project detach \u003cnodeId\u003e --project \u003cprojectId\u003e --area \u003careaId\u003e` (`DELETE` with `{projectMapId}`) releases the branch. The project view composes attached work read-time — attached rows carry their `areaMapId` and group under the nearest COMPONENT ancestor from their area; work with no component ancestor rides under a synthetic `No component` holder: it counts toward the milestone's progress like a component (its tasks count as work and it lists as unrun until done), and the web app offers no edits on it while the API and CLI still accept them — give it a component in its area (`orient node move \u003cnodeId\u003e --parent \u003ccomponentId\u003e --area \u003careaId\u003e`, or `orient project move \u003cnodeId\u003e --project \u003cprojectId\u003e --to \u003ccomponentId\u003e`). Attaching a reference node turns it into a task (its notes stay), so attach work, or the branch above a note. A component drawn under a second milestone appears there as an echo row (`echoOf`) — act on the real component id. Attach refuses a component (mark the work inside it), the area root, a node of a project map, a linked area, work in another workspace and a milestone of another project, each in its own words. When the project view must display a branch's hierarchy, bind the branches as well as the leaves — a descendant's own milestone binding stays explicit and outranks the inherited ride.\n- Size a window from the work attached to it and from who does it: add up the efforts, each at its doer's speed, then add the waits that are real — the time until a person can take their turn, a date someone outside fixed. Work an agent runs that adds up to a few hours fits one day, so the start and the due may be the same day, and a delivery that is all an agent's can be due the day it starts; a person's work takes the days that person has for it: use what your owner told you, and where they have not said, allow one day for each hand-off to a person and say in the milestone's notes that the day is assumed. Unless your owner gave the date, a window starts the day its first task can start and is due the day its last task can be done, so windows may overlap, and a milestone is never due before the milestones its attached work depends on. Never pad a window to the length a team of people would need. A date your owner gave is the commitment: keep it, and say so when the work will be ready sooner.\n- A component is a deployable or delivery boundary — an app, a service, the infrastructure, an environment, or an enduring product module that ships as one unit under one owner — and nothing else.\n- A feature, a capability or an experience that runs across several components is not a component, however large or lasting. The classic mistake is Voice beside Desktop app and Mobile app: the apps are components; Voice is a capability both of them ship. Its work goes inside each app — a Voice branch under Desktop app and another under Mobile app — and when Voice needs a plan of its own, it gets a milestone on the project (`Voice beta`, say) that both branches attach to. Never mark it `kind: component`.\n- A component is independently deployable or ships as one unit, and it is a stable, named part of the product or system that the delivery returns to across many releases. A component is not a phase, a sprint, a milestone, a temporary work bucket, an individual task, or a one-off feature request. Two deployable apps are two components; a command-line tool and the MCP server built from it are one component, not two. If a capability has a part that deploys on its own — a speech service behind Voice — that service is a component under its own name; the capability still is not. Keep a capability's branches inside components: a branch outside every component rides under `No component` on the project and counts toward its milestone's progress.\n- Keep a component's identity and history on the area map across projects: finishing or archiving a project does not delete or recreate its components — inspect the area first and reuse the existing component before minting another. The general examples your owner may recognise: a marketing website, an authentication service, the infrastructure, a mobile application.\n- Components are area nodes: `PATCH /api/nodes/{id}` `{\"kind\": \"component\"}` marks a branch (or the area root itself) as one; the same title may exist in several areas as distinct components; each carries owners — `orient project own \u003ccomponentId\u003e \u003caccountId\u003e --area \u003careaId\u003e` writes the list (name every owner, one id after another), `orient project components \u003cmapId\u003e` reads it. On the project view, move attached work between milestones or onto a same-area component with `orient project move \u003cnodeId\u003e --project \u003cprojectId\u003e --to \u003ctargetId\u003e` (`POST /api/nodes/{id}/plan-move` `{projectMapId, targetId}`, where the target is a milestone or a component) — moving a component re-attaches every task riding it, and dropping a task on a component also reparents it inside its area. Reference nodes and routines are refused on a project map, and planning kinds other than `component` are refused on the area map — the area map stays the description. Kinds change only within their level: the project root keeps its kind (an area root may become a component), and branches never move between an area and a project.\n\nStructure a delivery in this order, and the map stays honest:\n\n1. Describe the work on the AREA map first: mark the lasting parts as components (`kind: component`) and give each an owner (`orient project own \u003ccomponentId\u003e \u003caccountId\u003e --area \u003careaId\u003e` — your owner's account id, or your own agent id when you run it; `orient profile show` gives your own id and `orient workspace people \u003cworkspaceId\u003e` your owner's), then define gradeable tasks beneath them.\n2. Mint the project (`orient project create \u003careaId\u003e \"\u003cname\u003e\"`) and lay its ladder — phases for the delivery's main parts (`orient node add \"\u003ctitle\u003e\" --area \u003cprojectId\u003e --kind phase`), milestones inside each phase with real start→due windows sized from the attached work's efforts (`orient node add \"\u003ctitle\u003e\" --area \u003cprojectId\u003e --parent \u003cphaseId\u003e --kind milestone`, then `orient task schedule \u003cmilestoneId\u003e --area \u003cprojectId\u003e --start \u003cYYYY-MM-DD\u003e --due \u003cYYYY-MM-DD\u003e`).\n3. Attach the area work to milestones (`orient project attach \u003cnodeId\u003e --project \u003cprojectId\u003e --milestone \u003cmilestoneId\u003e --area \u003careaId\u003e`) — attach the branch root and the branches whose hierarchy the project view must display, not every leaf; the branch rides as one.\n4. Track by reading, never by writing roll-ups: `orient project show \u003cprojectId\u003e` answers where the delivery is because task completions roll up through milestones — a branch's progress is the floor of the mean of its contributing children, and a leaf contributes its own completion when it is a task — so replan by moving work (`orient project move \u003cnodeId\u003e --project \u003cprojectId\u003e --to \u003cmilestoneId\u003e`) or re-windowing milestones, not by editing progress. Roll-ups are computed for the reader: a branch you cannot see is not in your numbers, so you and your owner can read different progress on one node. A task with tasks beneath it reads done only when they are (`doneRollsUp` above) — read `rolledCompletion` on anything with children.\n5. Deliver in bounded increments: when a piece passes review, release it the way your owner's release policy says, check that the release actually landed, and update the map at once — do not wait for unrelated roadmap work.\n\n## The orientation loop\n\nThe map is your memory between turns — work the loop and you never start amnesiac, and your owner never has to re-explain the context:\n\n- ORIENT: run `orient orient` (`POST /api/orient`) before your first write of a turn, after you finish a task, when you switch area, and whenever your owner says orient. It answers where you are (your working marks with the ancestor chain and its notes — ancestors' notes carry the intent and constraints your task inherits), what is yours (open assignments and what they wait on), what moved on your branch since you last oriented, and who else is working nearby. On a project you hold with read and write, its `project` block names the milestones overdue and due within a week against your owner's today (`today`, `timeZone`) and the open tasks no registered run is on (`unrun`, first ten, `unrunTotal`); a person's working mark is not a run, so read the task's `working` list before taking one. Reading it stamps your cursor, so the next answer is a delta. On Claude Code, `orient skill hook` installs a prompt hook that runs it for you every turn.\n- READ A LINK: people hand you work as an Orient node link — `\u003cappHost\u003e/#/map/\u003careaId\u003e/node/\u003cnodeId\u003e`. Pass it as it is to any command that takes a node id: `orient node show '\u003clink\u003e'` prints the node's title, notes and state, the path from the root and the children, with read access alone, and an area link works wherever an area is taken. Over MCP, call node_show with the link as its id. Fetching the link over HTTP gets only instructions, never the node.\n- PLAN IN THE OPEN: before executing, externalize your plan as child tasks of your assignment — the plan on the map is your working memory, and your owner steers by editing it.\n- REGISTER YOUR RUN: one enrollment can run many concurrent executions — a pane, a session, a worker on another machine — and without registration they collapse into one indistinguishable worker. Start a turn with `orient execution start --label \"\u003ca label a collaborator can read\u003e\" --executor \u003cmodel\u003e` (`POST /api/executions`), which answers your own execution id and session epoch and keeps its proof privately on this machine; never print that proof, never put it on the map, and never put a hostname, a local path or a secret in the label. Keep the run visible with `orient execution beat --node \u003cleafId\u003e --area \u003careaId\u003e` (`POST /api/executions/beat`) while you work: server time rules the lease, and once it lapses you read as stale rather than working. After a crash or a long pause use `orient execution beat --reconnect`, which takes a fresh session epoch; a resumed process carrying the old epoch is refused so it cannot overwrite the session that replaced it. Close explicitly with `orient execution stop` at the end of the run, and read `orient execution list` to see every execution under the enrollment. Capabilities and labels describe a worker; they never widen what it may read or write, and a proof alone can do nothing without the enrollment credential.\n- CLAIM: plainly mark the actual leaf before starting work — `orient task start \u003cleafId\u003e --area \u003careaId\u003e` (`POST /api/nodes/{id}/working`); release it with `orient task stop \u003cleafId\u003e --area \u003careaId\u003e` at hand-off (`DELETE /api/nodes/{id}/working`). Read the nearby marks first and never take a node another agent or person is on; coordination between agents happens on the map, never in a side channel. The mark is advisory — no atomic exclusive lease exists yet, so a node may carry marks from several workers at once. Delegation your owner authorized within your grants is valid even when the task's assignee is your owner. To say the work is yours, assign yourself (`orient task assign \u003cleafId\u003e --me --area \u003careaId\u003e`), or give it to one of your operators (`orient task assign \u003cleafId\u003e --operator \"\u003cname\u003e\" --area \u003careaId\u003e`); take yourself off with `orient task unassign \u003cleafId\u003e --me --area \u003careaId\u003e`. You never add another agent or its operators, or take them off work — that is that agent's or its owner's call.\n- KEEP OPERATORS: you may hold operators — identities of your own that take work beside you, one per worker you run. Make one with `orient operator add --name \"\u003cname\u003e\"` (`POST /api/agents/{yourAgentId}/operators` `{name}`; 1 to 60 characters, unique among your live operators in any case, at most 50): it needs no approval, it never holds more than you, it ends when you are revoked, and your owner sees each one and can revoke it. List them with `orient operator list` (`GET /api/agents/{yourAgentId}/operators`), give one a task with `orient task assign \u003cleafId\u003e --operator \"\u003cname\u003e\" --area \u003careaId\u003e` (an operator takes work only where you hold member access), clear it with `orient task unassign \u003cleafId\u003e --operator \"\u003cname\u003e\" --area \u003careaId\u003e`, take yourself off with `orient task unassign \u003cleafId\u003e --me --area \u003careaId\u003e`, and revoke one with `orient operator revoke \"\u003cname\u003e\"` (`POST /api/agents/{yourAgentId}/operators/{operatorId}/revoke`); a revoked operator takes no work. `orient node history \u003cleafId\u003e --area \u003careaId\u003e` lists who assigned or unassigned whom, and when. Over MCP: operator_list, operator_add, operator_revoke, task_assign with `operator`, and task_unassign.\n- NAME YOUR CONTEXT: keep a list of the contexts you work in — one per area or client you serve — with `orient context add --name OneRoof --code OR --colour teal` (a code of one to three letters, a colour from red, orange, amber, green, teal, blue, indigo, violet, pink or slate), and read it with `orient context list`. Name one whenever you mark a node: `orient task start \u003cleafId\u003e --area \u003careaId\u003e --context OR` (`POST /api/nodes/{id}/working` `{contextId}`). Your tag then reads `Plex [OR]` in the context's colour, but only your owner sees the context — everyone else sees your plain name, and the server never sends them the context. Rename, recolour or retire a context with `orient context rename OR --name \"\u003cname\u003e\"`, `orient context recolour OR --colour blue` and `orient context retire OR`; marks made in a retired context keep its code.\n- RECORD as you go: mark progress the moment it is true, and put discoveries where they belong — a new task where work appeared, a dependency edge where an order emerged, a note where context grew. Never save your findings only in your own scratch space.\n- PROVE IT DONE: when you mark work done, say how you verified it and where to see it — `orient task done \u003ctaskId\u003e --area \u003careaId\u003e --verified \"\u003chow you verified it\u003e\" --see \"\u003chttps link\u003e\"` (a proof can also be `--see build:\u003cbuildName\u003e` or `--see device:\u003cdeviceName\u003e`; repeat `--see`; `--see` takes the URL `orient node link \u003cnodeId\u003e --area \u003careaId\u003e` prints or its `-o json` answer as it is; over MCP the same `verified` and `see` arguments on task_done, where `see` takes the JSON `node_link` answers, as a string). Your owner reads the proof on the node instead of hunting through notes, and reopening the task clears it. Where the area has a workflow, `orient task stage \u003ctaskId\u003e verified --area \u003careaId\u003e --verified \"\u003chow you verified it\u003e\" --see \"\u003chttps link\u003e\"` records it with the move to Verified, so proof never passes the work through the last stage, the sponsor's acceptance.\n- PROOF REQUIRED: a task that asks for proof says so before you start — `orient node show \u003ctaskId\u003e --area \u003careaId\u003e` lists each proof under Proof required, and `orient task proofs \u003ctaskId\u003e --area \u003careaId\u003e` lists them alone with their keys (p1, p2, …). Plan to produce each one. Attach every proof before you mark the task done, one per call, under its key: `orient task prove \u003ctaskId\u003e p1 --area \u003careaId\u003e --text \"\u003ctext\u003e\"` for a metric or a text account, and in its place `--file` with the path of an image (uploaded onto the task), `--link` with an https link, `--build` with a build name or `--device` with a device name. Until each is attached, `orient task done \u003ctaskId\u003e --area \u003careaId\u003e` is refused with `proofRequired` naming what is missing. Say what a task asks for when you set it: `orient node add \"\u003ctitle\u003e\" --area \u003careaId\u003e --kind actionable --needs \"image: the settings page with the toggle on\"`, or later `orient task needs \u003ctaskId\u003e --area \u003careaId\u003e --add --needs \"metric: p95 under 200 ms\"` (repeat `--needs`; kinds are image, metric, link, build, device and text); `--add` keeps what the task already asks for. You may add proofs a task asks for, with `--add`, never remove or change one: that, and `--clear`, is a person's call. Over MCP: task_proofs, task_prove, task_needs and the `needs` argument on node_add.\n- ACCEPTANCE CRITERIA: every item carries its acceptance criteria as a field of its own: one to twenty one-line checks that prove it done. `orient node show \u003cnodeId\u003e --area \u003careaId\u003e` prints them under Acceptance criteria and its JSON carries `criteria`, as every node answer does; set them at creation with `orient node add \"\u003ctitle\u003e\" --area \u003careaId\u003e --parent \u003cepicId\u003e --criteria \"\u003ccheck\u003e\"` (repeat it), and later with `orient task criteria \u003ctaskId\u003e --area \u003careaId\u003e --check \"\u003ccheck\u003e\"` (repeat `--check`; it replaces them, `--add` keeps the held ones, `--clear` removes them, and alone it prints them). The routes are `PUT /api/nodes/{id}/criteria` `{checks, stage?}` and `DELETE /api/nodes/{id}/criteria`. In an area whose workflow has a stage keyed `defined` (Defined under the preset), readiness is the stage: an item is ready from Defined on, and `--defined` (`stage` on the route) moves it there in the same write. Elsewhere an item is ready once its criteria hold a check. Notes carry no rule: a line in them beginning `Done when:` is only text. Over MCP: task_criteria and node_add.\n- WORKFLOWS: an area may hold a workflow — an ordered list of stages, each with a key, a title, a colour and the progress it stands for; a range stage (In progress, 15 to 80 under the preset) follows the node's children. Read it with `orient area workflow \u003careaId\u003e` (`GET /api/maps/{id}/workflow`); adopt the default preset with `orient area workflow adopt \u003careaId\u003e`, copy another area's with `orient area workflow copy \u003careaId\u003e --from \u003cotherAreaId\u003e`, or set your own with `orient area workflow set \u003careaId\u003e --json '{\"stages\": [{\"key\": \"todo\", \"title\": \"To do\", \"colour\": \"slate\", \"weight\": 0}, {\"key\": \"done\", \"title\": \"Done\", \"colour\": \"green\", \"weight\": 100}]}'` (the same document on stdin without `--json`; `PUT /api/maps/{id}/workflow`); `orient area workflow clear \u003careaId\u003e` removes it (`DELETE`). Adopting, copying or setting a workflow gives every item of the area a stage in the same write, so nothing that was ready reads as not ready: done work takes the last stage; an item with acceptance criteria takes the stage keyed `defined` (Defined under the preset), or a later stage its progress already reads; work under way takes the stage its progress reads — a task's own completion, or its children's when they are further on, so a PBI whose steps are half done is In progress and one whose steps are all done waits at the stage before the last (an adoption finishes nothing); the rest take the first stage. A task's completion rises to its stage's weight (a task with criteria at 0% is Defined at 10%) and never drops. An item already at a stage of the new list keeps it, so adopting or copying again moves no stage someone set. Only items you can read and change are given a stage; one behind a wall you cannot pass is left for someone who can to stage by adopting again. A workflow with no stage keyed `defined`, or whose `defined` is its last stage, takes nothing there and leaves readiness to the criteria field. Name an item's stage instead with `--stage \u003citemId\u003e=\u003cstage\u003e` (repeat it; `itemStages`: `{\"\u003citemId\u003e\": \"\u003cstage\u003e\"}` beside `preset`, `copyFrom` or `stages` on the route; `stage` on the MCP tools): it moves a task's completion as a stage write does, passes the area's gates, and is refused when it would finish or reopen work. An item the adoption takes to the execution stage or past it leaves the backlog in the same write. The answer lists each item given a stage under `items` (`{id, stageMark, completion}`, `completion` only where it moved). A node's stage comes from its area's list: `orient task stage \u003ctaskId\u003e delivered --area \u003careaId\u003e` (`PUT /api/nodes/{id}/stage` `{stage}`; the key in any case, with a space or an underscore in place of the hyphen) sets it and the task's completion with it — Delivered is 80%, Accepted 100% and done, under the same rules as marking it done, proof required among them — and a completion write sets the matching stage, so `orient task done \u003ctaskId\u003e --area \u003careaId\u003e` lands on the last stage; reopening a done task steps it back one stage; a stage outside the list is refused naming the list, and a node whose area holds no workflow carries no stage. `orient node show \u003ctaskId\u003e --area \u003careaId\u003e` names the stage with who set it or that it was read from completion, `orient task stage \u003ctaskId\u003e --area \u003careaId\u003e` prints it alone, and `orient node history \u003ctaskId\u003e --area \u003careaId\u003e` (`GET /api/nodes/{id}/history`) lists who changed it, when, from and to. `orient task sponsor \u003ctaskId\u003e \u003cprincipalId\u003e --area \u003careaId\u003e` names the sponsor who signs the work off (`me` for yourself, `--clear` to remove, neither to read it); while a node's set stage is the last of its workflow, its answer carries `acceptance` with who set it and when. Blocked and waiting on a person sit beside the stage, never instead of it: `--waiting-on \u003cprincipalId\u003e` on the block command names the person the work waits on. Over MCP: area_workflow_show, area_workflow_adopt, area_workflow_copy, area_workflow_set, area_workflow_clear, task_stage, node_history, task_sponsor and the `waiting-on` argument on task_block.\n- BACKLOG: each area (and each project map) has a backlog — the refined work not yet started, in the order it will be taken. It holds the map's own items, never copies. Read it in order with `orient backlog show \u003careaId\u003e` (`GET /api/maps/{id}/backlog?stage=\u0026limit=\u0026after=`): each item's place, priority, stage, owners and its acceptance criteria, 100 to a page. Put an item on with `orient backlog add \u003cnodeId\u003e --area \u003careaId\u003e`, or an epic or feature with everything beneath it with `--branch`; take it off with `orient backlog remove \u003cnodeId\u003e --area \u003careaId\u003e` (`--branch` too). Reorder with `orient backlog move \u003cnodeId\u003e --before \u003cotherId\u003e --area \u003careaId\u003e` (or `--after`, `--top`, `--bottom`): the order is priority first, then the backlog's rank within each priority, one list across stages, and a move never changes a stage — placed beside an item of another priority, it takes that priority, which the map shows. The routes are `PUT /api/nodes/{id}/backlog` (`{}`, `{branch: true}`, `{beforeId}`, `{afterId}` or `{place: \"top\"|\"bottom\"}`) and `DELETE /api/nodes/{id}/backlog` (`?branch=true`). An item leaves on its own when its stage reaches the area's execution stage, or when it is done in an area that names none, and an item already there cannot be put on. The default preset names In progress when an area adopts it, so Delegated is the backlog's last stage: a delegated item, its criteria written and no agent on it yet, waits on the backlog in order and leaves it when it moves to In progress. An area that adopted the preset earlier, or keeps its own workflow, keeps the stage it names; name one with `orient area workflow execution \u003careaId\u003e in-progress` (`orient area workflow \u003careaId\u003e` prints the one named). You place only what your key may change, and see only what it may read; each change is attributed to you, shows in `orient node history \u003cnodeId\u003e --area \u003careaId\u003e`, and reaches the change feed. Over MCP: backlog_show, backlog_add, backlog_move, backlog_remove and area_workflow_execution.\n- BLOCK LOUDLY: when you cannot proceed, mark the task blocked with the reason — `orient task block \u003ctaskId\u003e --area \u003careaId\u003e --reason \"\u003creason\u003e\"` (`POST /api/nodes/{id}/blocked` `{reason, waitingOnId}`; add `--waiting-on \u003cprincipalId\u003e`, or `me`, when the work waits on a person) — rather than going silent; the block shows on the node, where your owner reads the map, and `orient task unblock \u003ctaskId\u003e --area \u003careaId\u003e` clears it once you can move again. Your owner reads the map, not your transcript.\n- HAND OFF: when you need a decision, a review, or you are done, release your working mark, leave the summary on the node, and hand your owner the link — `orient node link \u003cnodeId\u003e --area \u003careaId\u003e` prints the URL alone, also when piped, and that is the URL they open (`-o json` answers `{url, mapId, nodeId}`). Leave the map telling the truth without you: completions marked, blockers named, anything half-done split so the remainder is a task someone else could pick up.\n\n## Working with the CLI (preferred)\n\nThe `orient` command line is the fastest way to work here. Install it in one command from the release channel on this same API host: macOS/Linux `curl -fsSL \u003capiHost\u003e/api/cli/install.sh | sh` (substitute your API host, e.g. https://app.orient.day; Windows runs `irm \u003capiHost\u003e/api/cli/install.ps1 | iex`). The installer remembers the channel it came from, so a plain `orient update` keeps the binary current from then on. Discover every verb with `orient commands -o json` — the machine-readable catalog of the full surface: areas, nodes, tasks, views, changes, watch, search, tags. To learn when anything you read changes, run `orient changes` instead of polling: it holds one WebSocket for every workspace your key reads, prints each change notice as a JSON line, and reconnects by itself (see Staying current). Verbs that take `-o` answer JSONL when piped, except `orient node link \u003cnodeId\u003e --area \u003careaId\u003e`, which prints the URL alone; refusals answer `Error (\u003ccode\u003e): \u003cmessage\u003e` plus a `Hint:` line telling you what to do next, and a destructive verb (`node delete`, `doc archive`, `file rm`, …) asks to confirm on a terminal and needs `--yes` when it runs unattended.\n\nSeveral agents can share one machine user, each with its own key in `~/.orient/credentials/\u003cagentId\u003e`. A session that names no profile acts as the machine's default agent: the first agent enrolled holds it, enrolling another never moves it, and the person who runs the machine changes it in one command, `orient auth default \u003cagentId\u003e`. `orient auth status` shows the default and every agent enrolled here. A session acts as another enrolled agent with `--profile \u003cagentId\u003e` or `ORIENT_PROFILE=\u003cagentId\u003e`.\n\n## Working over MCP\n\nThe CLI is also a Model Context Protocol server: `orient mcp serve` speaks MCP over stdio, and every unattended command becomes a tool with the same credential chain (`ORIENT_API_KEY` env, or the stored profile). If you are a Claude Code session, wire it with `claude mcp add orient -- orient mcp serve`. Any other MCP client uses the standard config shape:\n\n```json\n{\n  \"mcpServers\": {\n    \"orient\": {\n      \"command\": \"orient\",\n      \"args\": [\"mcp\", \"serve\"]\n    }\n  }\n}\n```\n\nSet `ORIENT_API_KEY` (or `ORIENT_PROFILE`) and, off production, `ORIENT_API_URL` in the server's `env` block. Without either, the server acts as the machine's default agent. The connection's initialize answer carries working instructions; destructive tools refuse until the call carries `\"yes\": true`. The tools are generated from the CLI's own command registry at startup — `tools/list` is always the complete, current surface, so never fall back to raw HTTP because you suspect the tools are stale.\n\n## Working with the API\n\nSend the key on every request: `Authorization: Bearer odk_...`. Write requests that name a node also carry the header `X-Orient-Map: {mapId}`.\n\n### Maps and nodes\n\n- `GET /api/maps` — the maps you can reach\n- `GET /api/maps/{id}` — a map snapshot: every node with `id`, `title`, `parentId`, `completion`, `kind`, dates\n- `POST /api/maps/{id}/nodes` `{parentId, title, kind}` — add work; `kind` is `actionable` (a task — omitting kind births a task on an area, and a plain node, an epic, straight under an area's root), `reference` (inert notes — state it explicitly) or `component`; on a project map the kind follows the parent — a phase under the root, a milestone under a phase — and may be named explicitly; routines are retired and refused\n- `PATCH /api/nodes/{id}` — revise `title`, `notes`, `completion` (0–100), `kind`, `assigneeIds` (a list; the single `assigneeId` still works), `durationMinutes`, `tags`, `colour`, `collapsed`, or `mode`; `startDate`/`dueDate` are accepted only on a project's ladder — the project root, its phases and its milestones — because tasks and components carry no dates on either map; unknown fields refuse rather than silently dropping\n\nWhat the node fields mean:\n\n- `completion` is writable on leaves you do; done IS completion 100. The `rolled*` fields (`rolledCompletion`, `rolledDoneCount`, …) are the computed roll-up a branch shows — never write a branch's progress, it is derived from its leaves\n- `mode` is the access ladder of a branch, not a work state: `open` (everyone in the area) → `managed` (roster-run) → `restricted`/`confidential` (walled; invisible to non-members). Agents never change mode\n- `designated: true` marks a node that is also an anchor — an area root or a saved focus area with views of its own\n- A view is a named lens rooted at a branch; a focus view is your personal one-level dive minted by the focus verb — bookmarking it names it for everyone\n\nA node has no writable side: sides belong to top-level branches of a view and shape only your own layout, never your owner's — `PATCH /api/views/{viewId}/state` `{\"sides\":{\"\u003cbranchId\u003e\":\"left\"|\"right\"}}`.\n\n### Documents\n\n- `POST /api/nodes/{id}/documents` `{title}` — create a document anchored to a node you can write; it starts with one empty paragraph, so update that block or chain your first `afterId` from it (the create answer and `orient doc show \u003cdocumentId\u003e -o json` carry its id)\n- `POST /api/documents/{id}/links` `{nodeId}` — link the document to more nodes it covers, the branch and its leaves (`orient doc link add \u003cdocumentId\u003e \u003cnodeId\u003e`)\n- `POST /api/nodes/{id}/charter` — give a node its charter, the one document that defines its work (the project root, a branch or a leaf). It starts from Marchewka's (the default): identification, stakeholders, the measurable organizational value (measure, target, by when), scope, schedule, budget, quality, risks, administration and approval. Pass `templateId` to start from another template instead (`orient doc charter create \u003cnodeId\u003e --template \u003ctemplateId\u003e`). A node holds one charter; a second is refused with the reason. `GET /api/nodes/{id}/charter` names it; write it like any document (`orient doc charter create \u003cnodeId\u003e`, `orient doc charter show \u003cnodeId\u003e`, then `orient doc show \u003cdocumentId\u003e`)\n- Document templates — `GET /api/workspaces/{id}/document-templates` lists what a new charter or document can start from (`orient doc template list`): two built-in charters that are always there, Marchewka's (the default) and Schwalbe's traditional charter (title and date of authorization, start and projected finish, milestones, budget, project manager, objectives, success criteria, approach, a roles and responsibilities table, sign-off, comments), then the workspace's own. Built-ins cannot be changed or retired; copy one to change it (`orient doc template create \"\u003cname\u003e\" --from \u003ctemplateId\u003e`, or leave out `--from` to start empty). Rename a workspace template with `orient doc template edit \u003ctemplateId\u003e --name \"\u003cname\u003e\"`, and replace every block with `orient doc template blocks put \u003ctemplateId\u003e --json '{\"blocks\":[{\"kind\":\"heading\",\"level\":2,\"text\":\"Wins\"}]}'` (or the same object on stdin), in the block shapes a document block op takes. Retire it with `orient doc template retire \u003ctemplateId\u003e --yes`. `orient doc create \u003cnodeId\u003e --template \u003ctemplateId\u003e` (`templateId` on `POST /api/nodes/{id}/documents`) starts a document from a template; the new document records the template it came from and its version, and `orient doc show \u003cdocumentId\u003e` names it\n- `POST /api/documents/{id}/blocks` `{ops:[{op:\"create\", tempId, afterId?, block:{kind, text, level?}}]}` — write the body; ops are `create`, `update`, `move`, or `remove`; an op without `afterId` lands at the top, so chain `afterId` (a real block id or an earlier op's `tempId`) to write in reading order; the answer maps your temp ids to real ones: `{\"ids\":{\"t1\":\"\u003cblockId\u003e\"}}`\n- Block kinds: `paragraph`, `heading` (with `level` 1–3), `bullet`, `numbered`, `todo`, `quote`, `callout`, `code`, `divider`, `table`\n- `GET /api/nodes/{id}/documents`, `GET /api/documents/{id}`, `GET /api/documents/{id}/history` — read them back\n\n### Tasks, scheduling, and dependencies\n\n- Progress is `completion` 0–100 on an `actionable` node; it rolls up the tree by itself\n- Assign work with `assigneeIds` on the node PATCH — tasks carry one or more assignees, and components carry the same field presented as the component's owner (the label reads Owners when several people hold it); every added person needs member access at the node (their id is in the map snapshot's `members`). You add and remove YOURSELF on work you can write (`orient task assign \u003ctaskId\u003e --me --area \u003careaId\u003e` keeps the other assignees; `orient task unassign \u003ctaskId\u003e --me --area \u003careaId\u003e` takes you off alone), and you add and remove your own operators the same way (`orient task assign \u003ctaskId\u003e --operator \"\u003cname\u003e\" --area \u003careaId\u003e`, `orient task unassign \u003ctaskId\u003e --operator \"\u003cname\u003e\" --area \u003careaId\u003e`; an operator takes work only where you hold member access, and a revoked one takes none). Adding another agent or one of its operators, or taking either off work, is that agent's or its owner's call. `orient task assign \u003ctaskId\u003e \u003caccountId\u003e --area \u003careaId\u003e` replaces a task's assignees with that one account (several assignees go through the node PATCH `assigneeIds`), and `orient project own \u003ccomponentId\u003e \u003caccountId\u003e --area \u003careaId\u003e` replaces a component's owners — name every owner you mean to keep, one id after another, since a replace that drops another agent or its operators is refused unless you are that agent's owner. The rule binds people too: only an agent itself or its owner adds or removes that agent and its operators, on tasks and components alike; `orient node history \u003ctaskId\u003e --area \u003careaId\u003e` lists every assignment and unassignment with who made it. Reference nodes take assignees as well, and the server never requires one — keeping every task owned is the method's rule, yours to keep\n- Dates live on a project's ladder: the project root, its phases and its milestones each carry `startDate` and `dueDate` (YYYY-MM-DD) — set them with `PATCH /api/nodes/{id}` or `orient task schedule \u003cmilestoneId\u003e --area \u003cprojectId\u003e --start \u003cYYYY-MM-DD\u003e --due \u003cYYYY-MM-DD\u003e`, and batch-reschedule with `POST /api/maps/{id}/reschedule` `{moves:[{nodeId, startDate, dueDate}]}`. A task's effort is `durationMinutes` on the task itself\n- Done with proof: `PATCH /api/nodes/{id}` `{\"completion\": 100, \"verification\": ...}` where `verification` is `{how, evidence: [{kind: link|build|device, ref}]}` records how you verified the work and where to see it; `GET /api/nodes/{id}/verification` reads it back (`state` is `verified` or `unverified`). Proof alone may be added to a task already done or, where the area's workflow has a Delivered stage, to one at Delivered or a later stage; `PUT /api/nodes/{id}/stage` `{\"stage\": \"verified\", \"verification\": ...}` records it with the move. It stays through those stages (Verified, In review, Accepted); moving the task before Delivered, or reopening it, clears it\n- Proof required: a task may ask for proof before it is done. The map snapshot marks such a task `asksProof: true`; `GET /api/nodes/{id}/proofs` (read access is enough) answers `proofs`, one entry per requirement with its `key` (p1, p2, …), `kind` (image, metric, link, build, device or text), what it `shows`, and `state` `missing` or `attached` with the `proof`. Set the spec at creation with `proofSpec` `{required: [{kind, shows}]}` on `POST /api/maps/{id}/nodes`, or later with `PUT /api/nodes/{id}/proof-spec` `{basis, required}`: `basis` is the list you read, as `{key, kind, shows}` (a stale one is refused 409), and `required` the whole new list, each held requirement sent back with its `key` to keep it and its proof; a changed kind or wording gets a new key and drops the proof, and an empty list removes them all. An agent may add requirements but never removes or changes one (403). Attach each with `PUT /api/nodes/{id}/proofs/{key}` and exactly one of `{attachmentId}` (an image file already attached to the task), `{text}` (metric or text), `{url}` (link) or `{ref}` (build or device). While one is missing, taking the task to 100 is refused with 409 `proofRequired` naming every missing proof; a task already done stays done when a spec is added, and reopening keeps the proofs\n- Say what you are doing: `POST /api/nodes/{id}/working` marks you as actively working on a node right now (anyone may hold the mark, each worker is captured with a since-time), `DELETE` releases your mark; the node's `working` list carries who is on it\n- Dependencies: `POST /api/nodes/{id}/dependencies` `{targetId}` makes the node wait on the target; `DELETE /api/nodes/{id}/dependencies/{targetId}` releases it\n- `GET /api/workspaces/{id}/agenda` — the whole due-and-doable task agenda: a task attached to a milestone carries its milestone's window there, and unattached tasks list without dates. An optional `from`/`to` pair must be YYYY-MM-DD and at most 62 days apart, but the list is not cut to it — read each item's dates (`orient task list --from \u003cYYYY-MM-DD\u003e --to \u003cYYYY-MM-DD\u003e` filters them for you); `POST /api/schedule/resolve` `{phrase, today}` turns phrases like \"next tuesday\" into dates\n\n### Allowances you can hit\n\n- Agents do not create areas; your owner does.\n- A project you mint does not count against your owner's areas: the plan's map allowance counts areas only.\n- Your owner's plan sets how many of your owner's active agents one area holds (`agentKeys` in `GET /api/billing/plans`, which lists every plan's allowances); past it, your owner's approval of you, or opening another area to you, is refused naming the area.\n- On every plan: a title is at most 500 characters, a reschedule moves at most 500 nodes per call, an agenda window given with `from`/`to` spans at most 62 days, and `durationMinutes` runs 0 to 527040.\n- A plan allowance answers 409 with a hint naming the upgrade — tell your owner rather than working around it; the fixed limits answer 400 and name the limit.\n\nWorkspace-scoped reads need a workspace id: `GET /api/workspaces` answers the workspaces your credential reaches, including the one carrying your granted areas.\n\n### Time and time zones\n\nTwo time currencies, never mixed:\n\n- **Instants** are epoch milliseconds UTC — every `*AtMs`/`*Ms` number. They are absolute; convert to a wall clock only for display.\n- **Civil dates** (`startDate`, `dueDate`, `occurrenceDate` — `YYYY-MM-DD`) and wall-clock times (`HH:MM`) carry NO zone. They mean that date on the reader's clock; \"today\" is judged in the account's effective time zone, never your host's.\n\n`GET /api/me` answers `region` with the effective `timeZone` (IANA), `weekStart`, `timeFormat`, and per-value sources (`profile` when the person chose it, `detected` from the network edge, else defaults). Read `region.timeZone` before deriving \"today\" or scheduling relative dates: compute the civil date in that zone. The CLI already does this — `orient task resolve \"next tuesday\"` defaults its anchor to today in the profile time zone. Never let your host machine's local zone leak into a date you write.\n\n### Views, focus areas, and perspectives\n\nA focus area is a saved branch that works as a perspective: it carries its own view, and work done through that view is judged from that vantage. When your owner asks you to work \"from\" a focus area, adopt its lens:\n\n- `GET /api/maps/{id}/views` lists every named view with its `rootNodeId` — the view rooted at your granted anchor IS that focus area's perspective; open `GET /api/views/{viewId}` and treat that snapshot as your working frame\n- `POST /api/nodes/{id}/views` `{name}` mints a view rooted at a branch; `GET|POST /api/nodes/{id}/focus-view` reaches the one-level focus dive\n- Any node's priority is set with `orient node edit \u003cnodeId\u003e --area \u003careaId\u003e --priority 2` (1 to 5) and cleared with `orient node edit \u003cnodeId\u003e --area \u003careaId\u003e --priority none` (over MCP, node_edit's `priority`; over HTTP, `PUT /api/nodes/{id}/priority` `{priority: 1..5}` and `DELETE /api/nodes/{id}/priority`); the map read (`GET /api/maps/{mapId}`) and `orient node show \u003cnodeId\u003e --area \u003careaId\u003e` carry it as `priority` on the node, absent when it has none. Work attached to a project milestone is prioritised in that project, so the area map and the project map read the same value; the answer and each node name the holder as `priorityScopeId`; a map's main view refuses a node another map or project holds and points you to this route\n- A focus view may keep its own ordering beside that: `GET /api/views/{viewId}/priorities` reads them, `PUT /api/views/{viewId}/priorities` with `{set:{nodeId:1..5}, clear:[nodeId]}` changes some of them; PUT the document GET prints, `{scopeRootId, assignments, revision}`, to replace them whole — the revision is required, and if another writer changed the scope's priorities since you read them the write is refused with 409 `stale` and the current `revision`, so read again and reapply your change (a `{set, clear}` change may carry `revision` too); and only branches inside that scope may be prioritised — set them through the view your owner asked you to work from, never from a wider vantage\n\n### Finding things\n\n- `GET /api/search?workspaceId={id}\u0026q={query}\u0026limit=20` — search nodes across a workspace\n- `GET /api/tags` — every tag in use; write a node's `tags` through the node PATCH\n- `GET /api/nodes/{id}/notes` — the long text behind a node; `GET /api/nodes/{id}/audit` — the access and mode trail of a node whose mode is managed, restricted or confidential, or once was (a map's own root and a plain node carry none)\n\n### Files and attachments\n\n- `GET /api/nodes/{id}/attachments` — what a node carries; upload in two steps: `POST /api/nodes/{id}/attachments` `{filename, mimeType, sizeBytes}` answers an upload plan, then `POST /api/attachments/{id}/confirm` seals it\n- `GET /api/nodes/{id}/attachments/{attachmentId}/download` — fetch the bytes back; `GET /api/workspaces/{id}/files` and `/files/search` browse the workspace library\n- Storage URLs are presigned and complete: never send your API key to storage. The upload plan's URL, the download URL, and the release channel's redirects each refuse a request that also carries an Authorization header — storage answers InvalidRequest or AccessDenied, which looks like an outage but is your session header. Follow them with a bare client, not the session that talks to the API\n\n### Reporting problems\n\nYou may raise and read support tickets for your owner's account — a ticket you raise belongs to the account and is attributed to you by name:\n\n- `POST /api/support/tickets` `{kind: \"bug\"|\"billing\"|\"question\", title, body}` — raise a report; `question` is the catch-all kind\n- `GET /api/support/tickets` — the account's reports; `GET /api/support/tickets/{id}` — one report with its full thread\n- `POST /api/support/tickets/{id}/messages` `{body}` — reply on the reporter side\n- States: `open` means the team owes the next move, `answered` means the reporter does, `resolved` closes the loop; any reporter message reopens an answered or resolved ticket\n- Report what you observe and never fabricate a ticket outcome — the team's answer arrives in the thread, and until it does the state IS the truth\n- The CLI drives the same loop: `orient support create \"\u003ctitle\u003e\" --kind bug --body \"\u003ctext\u003e\"` (the kind is bug, billing or question), `orient support list`, `orient support show \u003cticketId\u003e`, and `orient support reply \u003cticketId\u003e \"\u003cbody\u003e\"`\n\n### Architecture diagrams\n\nDiagrams are authored through the studio verbs, never by hand-writing model JSON — the model's shape is private and reverse-engineering it from a stored diagram will break. Never render an image yourself and attach it as a stand-in; a picture of a diagram is not a diagram, and a stand-in artifact counts as a failure, not a workaround. If you cannot draw yet, say so plainly and leave the diagram empty. The loop, entirely through the CLI or its MCP tools:\n\nOver raw HTTP alone you can create, attach, list, read, and export diagrams as images — authoring them needs the CLI or MCP; install the CLI before promising a finished diagram.\n\n1. Find or make the diagram: `GET /api/workspaces/{id}/archboards` lists every diagram you can reach (`orient diagram list`); `POST /api/nodes/{id}/archboards` `{name}` creates one anchored to a node in your area (`orient diagram create \"\u003cname\u003e\" --node \u003cnodeId\u003e`). Anchor it where its subject lives — a diagram of the whole system on the area root and on each component it draws (`orient diagram anchor add \u003cnodeId\u003e \u003cdiagramId\u003e`), one component's internals on that component\n2. Learn the rules once: `orient diagram guide read engineers` (the engineers' part of the guide; `orient diagram guide list` names every part) and `orient diagram vocabulary elements`\n3. Author: `orient diagram element add \u003cdiagramId\u003e applicationComponent --name \"\u003cname\u003e\"` (any type `orient diagram vocabulary elements` lists), `orient diagram relationship add \u003cdiagramId\u003e \u003csourceElementId\u003e \u003ctargetElementId\u003e` (leave the type unset to accept the grammar's suggestion); place related elements close, providers below their consumers, flows reading left to right — or run `orient diagram element arrange \u003cdiagramId\u003e` to derive exactly that layout from the relationships when the board tangles (never over a board that already checks clean)\n4. Prove it: `orient diagram check \u003cdiagramId\u003e` measures the drawn wires — crossings, wandering detours, pierced boxes, clashing labels — beside every grammar and naming problem; fix until it answers none, and gate on `--strict` (exit 0) when a workflow needs the proof. A board of more than nine elements needs frames: group each part's elements with `orient diagram element group \u003cdiagramId\u003e \u003celementId\u003e --also \u003cotherElementId\u003e --name \"\u003cname\u003e\"` so no cluster holds more than seven or so\n5. Ship it: `orient diagram export \u003cdiagramId\u003e --format png` (or `--format svg`); `orient diagram example list` carries whole worked diagrams to learn from\n6. Put it on a screen: `orient diagram export \u003cdiagramId\u003e --format svg --theme dark --presentation` draws it for a 4K screen read across a room — framed to `--aspect 16:9` unless you name another ratio, its text sized for the room and wrapped inside its boxes, a drawing wider or taller than the screen spread toward it; a label too small for its box at that size is named on stderr, so give that box more room. `GET /api/archboards/{id}/export?format=svg\u0026theme=dark\u0026presentation=true\u0026aspect=16:9` answers the same image over HTTP (`format` png or svg, `theme` light or dark; without `presentation` it is the studio's own export, `scale` sizing a png)\n\n### Keeping the library tidy\n\n- Documents and diagrams belong to the nodes they anchor to — the anchor says where the work lives, so anchor them there first\n- The workspace library additionally shelves them into folders, independent of the anchor: `orient file folder add \"\u003cname\u003e\"` makes a folder; `orient diagram move \u003cdiagramId\u003e --folder \u003cfolderId\u003e` files a diagram, `orient doc move \u003cdocumentId\u003e --folder \u003cfolderId\u003e` files a document, and `orient file edit \u003cfileId\u003e --folder \u003cfolderId\u003e` files an uploaded file; omit the folder flag on the move verbs to shelve a document or diagram back at the root\n- Read the shelved library the way the owner sees it with `GET /api/workspaces/{id}/assets` — documents, diagrams, presentations, and files with their folder placements\n- The anchor id in your grants IS your area's root node; every granted anchor is listed in `GET /api/maps` (your grants are your bookmarks). Projects are separate maps of kind `project` in the same listing, and holding an area includes its projects automatically: the home project of every area you hold, plus any project with work attached from it, answers your reads and structure writes without a grant of its own\n- Point a person at any node with its link: `orient node link \u003cnodeId\u003e --area \u003careaId\u003e` prints the URL alone, also when piped (shape `\u003cappHost\u003e/#/map/\u003careaId\u003e/node/\u003cnodeId\u003e`; `-o json` answers `{url, mapId, nodeId}`) — print it in your terminal or a chat message and the owner lands on the map with that node selected and centered\n\n### Staying current\n\nNever poll reads to learn what changed. Hold the change feed: one WebSocket that tells you when anything your key reads changes, in every workspace you reach.\n\n- `GET /api/changes` — a WebSocket upgrade; send your key in the header, `Authorization: Bearer \u003ckey\u003e`, never in the URL, and add `?cursor=\u003ccursor\u003e` to resume from the newest cursor you received. The CLI verb is `orient changes`: it prints every frame as one JSON line, reconnects by itself, and `--from \u003ccursor\u003e` resumes an earlier run\n- Every frame is one JSON text message, a union on `type`: `{\"type\":\"ready\",\"cursor\":\"…\",\"workspaceIds\":[\"…\"],\"pingSeconds\":20,\"pongWithinSeconds\":10}` once per connection, naming the workspaces watched; `{\"type\":\"changes\",\"workspaceId\":\"…\",\"cursor\":\"…\",\"changes\":[…]}` with the notices of one workspace in commit order; `{\"type\":\"resync\",\"workspaceId\":\"…\",\"cursor\":\"…\",\"reason\":\"…\"}` (`pointTooOld`, `workspaceRestored`, `workspaceJoined`, `pointUnknown`); `{\"type\":\"progress\",\"cursor\":\"…\"}` when the cursor moved past changes you may not read. Keep the newest `cursor` of any frame; a cursor is issued to your credential and works for no other\n- A notice names what changed, never its content, so re-read what it names: `node` `{kind, id, mapIds}` → the node's row in `GET /api/maps/{id}` for a map in `mapIds` (the CLI: `orient node show \u003cnodeId\u003e --area \u003cmapId\u003e`), and its `GET /api/nodes/{id}/notes`, `/documents` or `/archboards` if you hold those; each map in `mapIds` is announced as a `map` too, and a move names the map it left as well as the one it entered; `map` → `GET /api/maps/{id}`; `diagram` → `GET /api/archboards/{id}`; `document` → `GET /api/documents/{id}`; `priorities` `{kind, id, viewIds}` → `GET /api/views/{viewId}/priorities` for each view, where `id` is the `scopeRootId`. Notices are dirty flags: your own writes are announced too\n- `resync` means the feed cannot tell you what changed in that workspace since your cursor: re-read what you hold from that workspace, then carry on with the frame's cursor\n- On any disconnect, reconnect with the newest `cursor` you received and nothing is lost: a server roll closes with 1001, a client that falls behind its frames is closed with 1008, and 1011 means the server could not list your workspaces; reconnect after any of those. 4401 means your key was revoked: do not reconnect with it. The server pings every 20 seconds and drops a client that does not pong within 10; standard WebSocket clients answer pings while they read, so keep reading\n- One key holds at most 30 open change-feed connections; the next is refused with 429 `tooManyRequests`, the reason in words and a `Retry-After` to wait out. A 401 means the key is unknown or revoked; a 400 means the cursor cannot be read, so open without it and re-read what you hold\n- Cannot hold a socket? `GET /api/workspaces/{id}/changes?point=\u003cpoint\u003e\u0026waitSeconds=25` is one workspace's feed as a held request: without `point` it answers the current `point` at once; with one it holds until a change lands or the wait runs out, answering `{state: changes, workspaceId, point, changes}` or `{state: resync, workspaceId, point, reason}`; pass the answered `point` to the next request\n- `GET /api/maps/{id}/events?cursor={cursor}\u0026waitSeconds=25` — one map's event feed, each event with its operation and content; every snapshot and write answers a `cursor` to resume from (the CLI verb is `orient watch \u003careaId\u003e`)\n- `POST /api/maps/{id}/undo` and `/redo` — your own last actions on a map\n\n### What agents may and may not do\n\nReads answer everything inside your granted areas; writes need the read-and-write strength. You may create and revise work, assign people, grade effort, set per-scope priorities, and write documents and diagrams. Closed to agents, always: sharing and granting, roster and member management, billing, enrollment verbs, a branch's `mode` and wall altitude, and assigning work to another agent or its operators, or taking them off work (that is that agent's or its owner's call; you assign and unassign yourself and your own operators). Requests over plain HTTP must carry a descriptive `User-Agent` — the edge blocks default library agents. Refusals carry a `code`, a plain `error`, and often a `hint` naming your next step — read the hint before retrying. A read of a node that was deleted answers 410 `gone` with a `departure` `{state: deleted, deletedWith, atMs, by}` naming who deleted it, when, and the deleted node above it that took it along; a node read on a map it no longer sits on answers 404 with a `departure` `{state: moved, mapId}`, and `GET /api/nodes/{id}/location` names the map that holds a node — fix the id or the area you hold rather than retrying. Never guess at routes: this whole guide stays readable at `GET /api/guide` with your key (or `orient guide`) whenever you need it again. To carry this knowledge across sessions, install the Orient skill into your harness: `orient skill install` writes it (Claude Code layout by default), `orient skill update` refreshes it, and `GET /api/skill` answers the same file as JSON under `skill`.\n"}
