{"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 operator 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` and it must be gradeable: from 15 minutes up to a few hours; 12 hours is the rare ceiling. If you cannot grade a task inside that range, it is too big — split it into child tasks until every leaf is gradeable. The band is the method, not a refusal: the server accepts any whole number of minutes up to a year.\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 chapter 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 at least one assignee. 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## When the work is a delivery — projects, phases, milestones, components\n\nRead this chapter when your operator 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 operator 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 operator 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 operator 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- 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 operator 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 operator'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 operator'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 chapters (`orient node add \"\u003ctitle\u003e\" --area \u003cprojectId\u003e --kind phase`), milestones inside each phase with real start→due windows (`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 operator can read different progress on one node. A `completion` written on a task that has child tasks is accepted, but the rolled percentage ignores it (done counts still include it) — read `rolledCompletion` on anything with children.\n5. Deliver in bounded increments: when a piece passes review, release it the way your operator'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 operator 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 operator 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 operator'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 operator 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 operator authorized within your grants is valid even when the task's assignee is your human owner. To say the work is yours, assign yourself (`orient task assign \u003cleafId\u003e --me --area \u003careaId\u003e`); you never add another agent or take an agent off work — that is its operator's call.\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 operator 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`; over MCP the same `verified` and `see` arguments on task_done). Your operator reads the proof on the node instead of hunting through notes, and reopening the task clears it.\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}`) — rather than going silent; the block shows on the node, where your operator reads the map, and `orient task unblock \u003ctaskId\u003e --area \u003careaId\u003e` clears it once you can move again. Your operator 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 operator the link — `orient node link \u003cnodeId\u003e --area \u003careaId\u003e` prints the URL they open. 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, watch, search, tags. Piped output is JSONL; 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\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. 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), `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 operator'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/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 may add YOURSELF to work you can write (`orient task assign \u003ctaskId\u003e --me --area \u003careaId\u003e` keeps the other assignees), but adding any other agent, or taking an agent off work (you included), is that agent's operator'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 an agent is refused unless you are its operator. The rule binds people too: only an agent's operator adds or removes that agent, on tasks and components alike. 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, and moving the task below 100 clears it\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 operator does.\n- A project you mint does not count against your operator's areas: the plan's map allowance counts areas only.\n- Your operator's plan sets how many of your operator's active agents one area holds (`agentKeys` in `GET /api/billing/plans`, which lists every plan's allowances); past it, your operator'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 operator 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 operator 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- Priorities are a property of the scope, not the whole map: `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 operator 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 operator'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, and read diagrams — drawing 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 chapter; `orient diagram guide list` names every chapter) 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\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 operator 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 clickable app URL (shape `\u003cappHost\u003e/#/map/\u003careaId\u003e/node/\u003cnodeId\u003e`) — print it in your terminal or a chat message and the operator lands on the map with that node selected and centered\n\n### Staying current\n\n- `GET /api/maps/{id}/events?cursor={cursor}\u0026waitSeconds=25` — the map's change feed; 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 taking an agent off work (that is its operator's call; you may assign yourself). 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. 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"}
