{"workspace_constitutions":[{"workspace_id":"workspace_01KT7ADYDNY7NNB0W5XE39YB00","workspace_handle":"engineering","constitution":"This is a spec-driven development project. Capture the intent, decision, and specification behind a change before writing the code that implements it, and let the documented spec lead the work.\n\nFollow the policies of every Doco in this workspace. They are binding, not advisory: when two policies appear to conflict, surface the conflict rather than silently choosing one.\n\nDocument anything a future collaborator, whether a person or an agent, would need to gain context later: the reasoning behind decisions, the constraints that ruled out alternatives, and the rules that emerged along the way. If it would be hard to reconstruct later, write it down now."}],"principal":null,"canonical_instructions_url":"https://doco.to/protocol/canonical-instructions","canonical_instructions":"# Doco — agent protocol (slim)\n\n## What is Doco?\n\nYou're working on a project that uses **Doco** — institutional memory\nfor software projects. Doco is a structured, searchable, typed record\nof a project's intent, decisions, rules, actions, history, and the\nartifacts they touch, purpose-built for AI agents and humans to share\ncontext.\n\nGit records *what* changed in the code. Doco records the surrounding\ngraph the code can't hold: the **intents** behind work, the\n**decisions** taken and the alternatives weighed, the **rules** that\nemerged, the **actions** designed, the **logs** of what actually\nhappened (incidents, fixes, releases), the **evals** that pin\nload-bearing claims, the **references** to external artifacts (pull\nrequests, issues, docs), the **states** a process moves through, and\nthe **principals** who own it — as typed, linked nodes you can query\nacross the project's whole lifetime.\n\nFor you, the agent, this means:\n\n- Before answering substantive questions, search the doco. Prior\n  decisions and rules likely shape the right answer.\n- When you make a non-trivial choice or finish load-bearing work,\n  follow this doco's policies to decide what, if anything, to\n  capture. **Each doco sets its own capture rules — the universal\n  protocol does not mandate captures.**\n- Avoid contradicting Decisions and Rules already in the doco.\n\nUse Doco naturally as a verb when you talk with the project owner:\n\"Want me to doco it?\", \"Doco this decision\", \"Doco this ADR\", and\n\"Doco the flow\" are all normal client-facing phrases. When a project\nowner says \"doco it\", interpret that as a request to capture per\nthis doco's policies.\n\nThe **three invariants** below govern every reply, so they come first —\nthey're what you do on every turn. The connection and credential\nmechanics some runtimes need follow after: they're about how you\n*connect*, not how you *reply*, and the invariants hold whichever way\nyou connected.\n\n## 1. TOP OF EVERY REPLY — connection indicator\n\nRender indicators in **rendering order around tool calls**. Text\nbetween tool calls is shown to the user as those tool calls run, so\nuse that ordering to communicate \"what I'm about to do\" vs. \"what I\njust finished.\" Don't batch everything at the end.\n\n**On the first reply of a session that uses Doco**, render the\nLoading line as the very first text, BEFORE any MCP tool call:\n\n```\n[🔮 Doco] Loading <doco_handle>...\n```\n\nThe trailing `...` is required. If this turn doesn't touch Doco at\nall (greeting, one-word ack, off-topic), emit nothing.\n\n**When you call `doco_search`**, render the corky verb on its own\nline IMMEDIATELY BEFORE the tool call (so the user sees it as the\nquery is sent), then the N-found line AFTER the result returns:\n\n```\n[🔮 Doco] <querying-verb>\n\n   ← tool call here\n\n[🔮 Doco] <N> relevant nodes found (<X.X>s)\n```\n\n**Don't hand-build that N-found line — paste it.** Every `doco_search`\nresult carries a `display` object with the exact lines already\nformatted from your credential: `display.found` is the\n\"<N> relevant nodes found (<X.X>s)\" line above, and `display.tally`\nis the closing tally (§3). Emit `display.found` verbatim after the\nresult, and `display.tally` verbatim as your last line. The server\nowns the format so you can't drift from it; only fall back to\nconstructing the line by hand when a result lacks `display`.\n\n**Your Doco credential label.** Every `doco_search` response may carry\n`viewer.indicator_prefix`, and `doco_complete_authentication` returns\nan \"Authenticated as <credential>\" block. Once you know the prefix, use it\nverbatim for every Doco indicator line. For OAuth/API-key agents this\nlooks like `[🔮 Doco <token nickname> on behalf of @username]`, so the\nquery/count/tally lines become `[🔮 Doco <token nickname> on behalf of\n@username] <querying-verb>`, `[🔮 Doco <token nickname> on behalf of\n@username] <N> relevant nodes found …`, and the closing tally. If the\nresponse lacks `viewer.indicator_prefix` but has `viewer.username`,\nfall back to `[🔮 Doco @username]`. Before you know either (the very\nfirst line of a cold session, before any search returns), plain\n`[🔮 Doco]` is fine.\n\nPick `<querying-verb>` at random:\n\nQuerying... · Looking it up... · Asking around... · Reading the room... ·\nSniffing for hits... · Flipping through notes... · Scanning the graph... ·\nSearching the lore... · Peering into the orb... · Combing the archive... ·\nHunting for prior art... · Pinging the memory... · Cross-referencing... ·\nChecking what's known... · Tracing the trail... · Diving in... ·\nPolling the doco... · Skimming the index... · Asking the oracle... · Searching...\n\n**Only render the verb if you have DOCO_ACCESS, or a shared `.env`\nwith DOCO_REFRESH + DOCO_CLIENT_ID, and expect the search to succeed.**\nIf both DOCO_ACCESS and refresh credentials are missing, skip the\nsearch and go to the not-connected flow below — no verb. If your\ncredential turns out invalid (401) and local refresh cannot recover\nit, it's fine that the verb appeared; follow up with the not-connected\nflow.\n\nIf you didn't need to query (greeting, one-word ack), emit nothing\nat the top — no \"Not querying\" placeholder. Absence is the signal.\n\n**If Doco access isn't granted** (no usable DOCO_ACCESS and no usable\nDOCO_REFRESH/DOCO_CLIENT_ID after checking the shared repo-root\n`.env`, or `doco_search` returned 401/403 after refresh, or the\nbootstrap couldn't reach Doco):\n\n1. Call `doco_authenticate` to get the verification URL.\n2. Render the block returned by `doco_authenticate` at the top of\n   your reply:\n\n   ```\n   [🔮 Doco] <doco-or-workspace-name> access not granted yet\n\n   To let me read this project's prior decisions and rules, open\n   [<URL>](<URL>) and click Approve. I'll pause here until you do.\n   ```\n\n   The URL must be wrapped in markdown link syntax so it renders\n   clickable.\n3. **Immediately call `doco_complete_authentication` with\n   `wait_seconds: 120` in the same turn.** Do not wait for the user\n   to send another message saying they approved; the tool blocks while\n   polling so the agent can learn when approval lands.\n4. **If it succeeds**: `doco_complete_authentication` returns an\n   \"Authenticated as <credential>. I've got the following levels of\n   access:\" block — render it verbatim at the top of your reply, then\n   retry `doco_search` and continue with the substantive answer using\n   the now-available doco.\n5. **If it returns \"still pending\" or any error**: end your reply\n   with a short \"I'll wait — send any message when you've approved\"\n   plus the tally line. **Do NOT continue substantive work without\n   Doco access.** Doco contains prior decisions and rules; doing\n   work that hasn't checked them risks contradicting them.\n\n**The query has two jobs:**\n\n1. **Inform.** Let prior Decisions, Rules, and Intents shape what\n   you say and do. An answer that contradicts a documented Decision\n   because you didn't check is a defect.\n2. **Deduplicate.** Before suggesting a new node, scan for nodes\n   that already cover the same territory. Patch the existing one\n   rather than create a near-duplicate.\n\n## 2. AFTER EVERY WRITE — footer_lines verbatim\n\nWhen the project owner captures a node on your behalf (via the web\nUI), the host returns `footer_lines: string[]` from the capture\nendpoint. If they share those with you, paste them verbatim, one\nper line:\n\n```\n[🔮 Doco] <op-icon> <Type> <verb>: [<summary>](<url>) (✅ <n> authoring policies passed in <X.Xs>)\n```\n\nOp icons: ✍️ added · 📝 updated · 🧹 cleared · ➕ added/appended ·\n➖ removed · 🔁 replaced · 🏷️ renamed · 🗑️ deleted.\n\n## 3. CLOSING LINE OF THE TURN — tally (no exceptions, once per turn)\n\nRender one tally line per source the agent has potential access to\n(each doco or workspace listed in the project's connections).\n\n**Connected source** (you queried or wrote — even if N == 0):\n\n```\n[🔮 Doco <token nickname> on behalf of @username] <doco-or-workspace-name>: **<N>** nodes added/updated\n```\n\n(Use `viewer.indicator_prefix` once you know it — see \"Your Doco\ncredential label\" in section 1. Fall back to `[🔮 Doco @username]`\nonly when no credential-aware prefix is provided. Plain `[🔮 Doco]`\nonly before your first search of a cold session.)\n\n**Paste `display.tally`, don't rebuild it.** The `doco_search`\nresult hands you `display.tally` — this exact line, already formatted\nwith your credential and the source you queried, for a read-only turn\n(**0**). If the turn captured nothing, emit it verbatim as your last\nline. If you DID capture, bump **0** to the number of nodes you wrote\nthis turn — one per capture `footer_lines` line. This is the same\n\"echo the server-provided string\" contract as `footer_lines` (§2):\nthe host owns the format so the ritual can't drift.\n\n**Source whose access hasn't been granted yet**:\n\n```\n[🔮 Doco] ⚠️ <doco-or-workspace-name> not queried or updated as access hasn't been granted yet.\n```\n\nThe tally lines are the LAST lines of the LAST text output of the turn.\n\n- `<doco-or-workspace-name>` is the human-readable doco handle if access is\n  scoped to one doco, or the workspace name if access is granted\n  workspace-wide (covering multiple docos under that workspace).\n- `<N>` counts distinct entities the project owner captured on your\n  behalf this turn (patch-3-fields-of-1-Decision = 1).\n- `<N>` MUST be wrapped in markdown bold (`**N**`).\n- Singular form for `**1**`; plural otherwise (zero is plural).\n- The connected-source line renders EVEN when N == 0 — that's the\n  explicit no-op signal.\n- The not-granted-yet line replaces the normal tally for that source\n  until access is granted (then switch to the normal line).\n\n## Connecting and writing — the mechanics\n\nEverything below is reference: how to reach a doco, authenticate, and\nwrite to it. Read it when you need it — the three invariants above are\nthe part you apply on every turn, whichever way you connected.\n\nThere are two access channels — pick the one your runtime supports.\n\n**MCP** (preferred, MCP-aware runtimes). Doco-tracked repos ship\n`.mcp.json` registering an MCP server at\n`.agents/doco-mcp-server.mjs`. The server exposes these tools:\n\n  - `doco_search` — query the project's doco for relevant prior\n    context. Cheap; call before answering substantive questions. If\n    repo-root `.env` has `DOCO_REFRESH` + `DOCO_CLIENT_ID`,\n    it refreshes a missing or stale `DOCO_ACCESS` locally before\n    falling back to device flow.\n  - `doco_get` — read the authoring contract, capture policies,\n    status, a node by id, or a type listing (read) — the read\n    surface beyond search.\n  - `doco_capture` — record a decision/intent/rule/etc. as it\n    forms (write; needs writer).\n  - `doco_relate` — link two nodes with a typed edge (write).\n  - `doco_changeset` — create and wire many nodes in one atomic\n    batch (write; the efficient way to import a process or backfill\n    history without dozens of single calls).\n  - `doco_policy` — write or modify a Doco's authoring policies\n    (write; owner only). Omit `id` to create; pass an existing\n    policy `id` to modify (a draft supersedes it, `{lifecycle}`\n    retires or re-activates).\n  - `doco_authenticate` — start OAuth device flow when a call\n    returns 401/403. Returns a ready-to-render block with a\n    clickable verification URL.\n  - `doco_complete_authentication` — finalize after the user\n    approves. Writes DOCO_ACCESS to the repo-root ./.env and clears\n    state.\n\nMCP delivers tool descriptions and the `serverInfo.instructions`\nfield in clean framing (no claudeMd-style \"may not be relevant\"\nwrapper), so this is the channel that survives sandboxed agent\nruntimes where project-scope hooks are filtered.\n\nThe hosted remote MCP connector lives at `/mcp` — one connection whose\nreach comes from your token. An \"act as me\" (`actor`) token reaches\n**every** workspace you belong to; a workspace-scoped token pins you to a\nsingle one. Authentication belongs to the MCP client transport: do not\nhand-drive OAuth or ask the user to paste localhost callback URLs back\ninto chat; if the callback listener fails, restart the client MCP auth\nflow. Use the direct OAuth recipes only when you are not connected\nthrough remote MCP.\n\n**Know your reach, and use all of it.** Call `doco_whoami` — and\n`list_workspaces` — to see what your credential covers: one workspace,\nseveral, or specific docos, exactly as the user granted. That grant is\nyour scope and the user chose it deliberately, so work across whatever\nworkspaces and docos the task needs — never cap yourself at one. Each\ntool call names a doco by its `<handle>`, in any workspace you reach.\nHonor each workspace's constitution and policies as you go.\n\n**Direct HTTP** (any runtime, or when MCP isn't available). You\ndrive OAuth directly. Two recipes, full step-by-step at:\n\n    https://doco.to/protocol/agent-oauth-recipe\n\n  **Recipe A — Localhost loopback** (shell-capable agents: Claude\n    Code, Cursor, Codex CLI, anything that can bind a port and\n    `open` a browser). Standard PKCE + authorize URL + a tiny local\n    listener catches the redirect. Same shape as `gh auth login`.\n\n  **Recipe B — Device Authorization Grant, RFC 8628** (chat-only or\n    sandboxed agents: claude.ai chat, ChatGPT, runtimes without\n    port binding). You POST to /oauth/device_authorization, get\n    back a short user_code like `WXYZ-1234`, show it to the user,\n    they approve at /device, you poll /oauth/token until you get\n    the token. The MCP tool `doco_authenticate` automates this.\n\nBoth recipes end with you holding a `doco_at_…` Bearer token. After\nthat, every API call is:\n\n    GET https://doco.to/<handle>/<endpoint>\n    Authorization: Bearer doco_at_<token>\n\nThe `<handle>` is a **doco** — the unit every endpoint addresses.\nAccess is granted to you at one of two levels: a **Workspace** (covers\nevery doco in it — the common case when an owner invites an agent) or a\n**single doco**. `GET /api/v1/whoami.json` returns both — the\nWorkspaces you can reach and the docos inside them, each with your role\n— so you find a project's handle without guessing instead of asking.\n\n### Repo-local credential sharing\n\nIf you are operating inside a Doco-tracked repository, the repository\nroot `.env` is the shared credential store for agents running in\nthat **same local checkout**:\n\n- Read `DOCO_ACCESS`, `DOCO_REFRESH`, `DOCO_CLIENT_ID`, and\n  `DOCO_HOST` from repo-root `.env` before asking the user to\n  authorize.\n- When OAuth succeeds, write the tokens back to that same `.env`\n  with private permissions (0600 where your runtime supports it).\n- Prefer the repo-root `.env` value over stale inherited\n  `process.env` values, and reread it before each Doco call if your\n  process is long-lived. Another local agent may have refreshed or\n  created the credential moments ago.\n- If `DOCO_ACCESS` is missing or expired but `.env` has\n  `DOCO_REFRESH` and `DOCO_CLIENT_ID`, exchange the refresh token\n  at `/oauth/token`, write the new access token back to `.env`,\n  and retry the Doco call before asking the user to authorize again.\n- Never commit `.env` or token values. Separate clones, worktrees,\n  machines, and remote sandboxes need their own local `.env` because\n  credentials are secret; they share only the committed Doco bootstrap\n  files.\n\nDo not ask the user to approve a new device/browser authorization\njust because this agent process did not start with credentials. First\ncheck the shared repo-root `.env`; if another same-checkout agent\nalready authorized, reuse that token and continue. If the same-checkout\n`.env` holds a refresh credential, mint a fresh access token locally\nand continue.\n\n### Persisting credentials across containers, clones, machines\n\nAfter a successful OAuth completion, **surface to the user once** that\nthe auth dance repeats on every fresh container or new clone unless\nthey persist the credential — the repo-root `.env` is per-checkout and\ndoes not travel to a fresh cloud container. Pick by what the agent\nneeds:\n\n1. **Pin the credential as env vars (recommended for ephemeral\n   runtimes).** Mint a token at `/tokens`, scope it, and set the\n   revealed `DOCO_REFRESH` + `DOCO_CLIENT_ID` (and optionally\n   `DOCO_ACCESS`) as environment variables on the runtime (Claude Code\n   on the Web env vars, Codespaces / Replit secrets, etc.). Refresh\n   tokens are non-rotating, so every fresh instance mints its own\n   short-lived access token from the same pinned refresh token — no\n   re-approving, and the pinned value never goes stale. Private to the\n   user; never commit. Revoke from the same page.\n\n2. **Read-only, shareable with the repo.** The doco owner mints a\n   read-only token at `/<handle>/project-tokens` (owner-only) and\n   commits it to `.doco/project-tokens.json` as\n   `{\"<handle>\": \"doco_pt_<token>\"}`. The MCP server reads this file\n   automatically as a fallback for `DOCO_ACCESS`. Only suitable when\n   the doco's contents are OK to be readable by anyone with read access\n   to the repo — minting requires an explicit confirmation to that\n   effect. Reader-only, indefinite TTL, revoke from the same page.\n\n3. **Quick and low-stakes: DOCO_ACCESS as a runtime env var.** Set the\n   access token alone on the runtime. Simplest, but it expires at the\n   access-token TTL and then falls back to device flow — fine for\n   short-lived or read-mostly use, not for long-running cloud agents.\n\nAll optional. Surface them once, immediately after each successful\nauth, then continue with the substantive answer. Do not re-prompt on\nevery turn.\n\nIf the doco is **public**, you can skip OAuth entirely. Either way,\nthe endpoint shapes are:\n\n    GET   https://doco.to/<handle>/status.json              # counts + freshness\n    GET   https://doco.to/<handle>/api/<type>.json          # list nodes\n    POST  https://doco.to/<handle>/api/<type>.json          # capture (needs write access)\n    GET   https://doco.to/<handle>/api/<type>/<id>.json     # one node\n    PATCH https://doco.to/<handle>/api/<type>/<id>.json     # patch (needs write access)\n    GET   https://doco.to/<handle>/api/<type>.txt           # plain-text spec for capture-capable types\n    GET   https://doco.to/<handle>/api/policies.json      # list policies\n    POST  https://doco.to/<handle>/api/policies.json      # capture a policy (needs write access)\n\nNode types: intents, ideas, rules, decisions, actions, logs, evals,\nreferences, states, principals.\n\nCapture body specs exist for decisions, intents, actions, logs, rules,\nevals, references, states, ideas, policies, settings, and principals.\nPrincipals expose a smaller surface (create + retire only) — read the\n`principals.txt` spec rather than assuming the generic capture body.\nInvites and audit have dedicated route behavior; don't infer write\nbodies for them from the generic capture pattern.\n\nPolicies are NOT nodes. Policies (a single `policy` entity type)\nlive on the dedicated `/api/policies.json` endpoint and inside the\nbootstrap payload — never on the generic `/api/<type>.json` route.\n\n### Capture body structure\n\nBefore POST/PATCH, read `GET /<handle>/api/<type>.txt` for the\nexact per-type body when that spec exists. Node request bodies contain\nprose and scalar metadata only. Put relationships in first-class edges\nwith `POST /<handle>/api/changesets.json` or\n`POST /<handle>/api/edges.json`.\n\n`created_by` / `updated_by` are user/API-key provenance derived from\nthe authenticated session or token. Never send `created_by` in request\nbodies.\n\nIntent capture example:\n\n    POST https://doco.to/<handle>/api/intents.json\n    {\n      \"intent\": \"Checkout can be completed without support.\"\n    }\n\nAction capture example:\n\n    POST https://doco.to/<handle>/api/actions.json\n    {\n      \"action\": \"Implemented edge-only relationship capture.\",\n      \"verb\": \"implemented\",\n      \"outputs\": { \"commit\": \"abc123\" }\n    }\n\nPublic docos return 200 for unauthenticated reads; private docos\nreturn 403 until you finish the OAuth recipe.\n\n### Bootstrap: read the policies\n\nEvery doco has a set of **policies** — short, project-owner-authored\nstatements that govern how you, the agent, author nodes inside it.\nThere is one `policy` entity type; each carries a standalone\n`kind`, all surfaced at bootstrap:\n\n  - **suggestion** — a single natural-language `agent_instruction`\n    for context. No automated check. Read it and let it shape your\n    judgement.\n  - **deterministic** — a `predicate` evaluated when you capture a\n    node (\"every Decision cites at least one Intent\"). `on_violation:\n    block` means the host will reject your capture.\n  - **probabilistic** — an `agent_instruction` the host evaluates\n    with an LLM when you capture a node. `on_violation: block` means\n    the host will reject your capture.\n\nPolicies apply only to their doco. Treat them as binding on your\nauthoring at all times.\n\nThe project owner can **add, edit, or remove policies any time**,\nat `/<handle>/policies`. Re-bootstrap if you suspect they've\nchanged mid-session.\n\nEach policy also has its own stable, linkable page at\n`https://doco.to/<handle>/policies/<policy_id>`. You already hold the\n`<handle>` (per doco) and every policy's `id` from the bootstrap\npayload below, so you can always build this URL. **Whenever you refer\nto, cite, or quote a policy — in chat, a PR comment, a commit message,\nanywhere — link to it at that URL** so the reader can open the exact\npolicy you mean.\n\nOnce you hold a Bearer token, hit:\n\n    GET https://doco.to/api/v1/agent-bootstrap.json\n    Authorization: Bearer doco_at_<token>\n\nThe response carries the policies for every doco you have\nread-or-above access to, exposed as a single `policies[]` array,\neach entry carrying its `kind`.\n\n## Doco is the memory — your private memory isn't\n\nProject-shaped knowledge lives **in this doco**, not in your private\nagent memory (Claude memory files, ChatGPT system notes, scratch\nfiles). Other contributors on this doco can't read your private\nmemory; the next session of *you* can't either, reliably. The doco\nis the shared source of truth — that's the whole point.\n","oauth_grant":null,"project_token_grant":null,"doco_policies":[{"doco_id":"doco_01KT7AGRT22C0VBRDYG5NABTP1","doco_handle":"engineering-glossary","goal":"Document domain terminology — canonical terms, definitions, aliases, replacement links, sources, and consistency checks.","owner_id":"workspace_01KT7ADYDNY7NNB0W5XE39YB00","policies":[{"id":"policy_8e02a96ed5b3a0b6de783e5e64","kind":"deterministic","agent_instruction":null,"predicate":{"sub_kind":"requires_edge_type","edge_types":["relates_to","derived_from","replaces","supports"]},"lifecycle":"active"},{"id":"policy_01KT7AGRTEXS69R109EQFD1P9V","kind":"deterministic","agent_instruction":null,"predicate":{"sub_kind":"requires_node_type","node_types":["decision","rule","reference","eval"]},"lifecycle":"active"},{"id":"policy_01KT7AGRTJKDCYEJWCNPN7CQJJ","kind":"deterministic","agent_instruction":null,"predicate":{"fields":["question","chosen"],"sub_kind":"requires_field","when_node_type":["decision"]},"lifecycle":"active"},{"id":"policy_01KT7AGRTASFMG5PXHPTXGQPZ8","kind":"probabilistic","agent_instruction":"A node belongs in glossaries when it defines product or domain terminology, records a terminology choice, cites an authoritative source, states a terminology usage rule, or checks terminology consistency. PASS for term entries, terminology usage rules, references to source glossaries/specs/docs, and evals that scan terminology consistency. FAIL for glossary scope statements, feature implementation work, process flows, org charts, runtime incidents, or state-machine stages.","predicate":{"when_node_type":["decision","rule","reference","eval"],"agent_instruction":"A node belongs in glossaries when it defines product or domain terminology, records a terminology choice, cites an authoritative source, states a terminology usage rule, or checks terminology consistency. PASS for term entries, terminology usage rules, references to source glossaries/specs/docs, and evals that scan terminology consistency. FAIL for glossary scope statements, feature implementation work, process flows, org charts, runtime incidents, or state-machine stages."},"lifecycle":"active"},{"id":"policy_01KT7AGRTTFR8ABXH9JQX39RPG","kind":"probabilistic","agent_instruction":"Judge a glossary term-entry Decision on three aspects; report each failing aspect with a reason, but treat them as warnings, not hard errors. (a) ONE CONCEPT: PASS when the entry defines one concept or one canonical term; FAIL when it defines multiple independent terms, bundles a term with an unrelated policy, or is a catch-all for several concepts. (b) USABLE DEFINITION: PASS when the `decision` prose gives a concise definition AND the product or domain scope where the term applies AND at least one concrete example OR non-example — EITHER an example or a non-example is sufficient, do not require both; FAIL when one of those three is genuinely absent, or when the prose merely restates the headword instead of explaining it (a circular definition such as `a workspace is a workspace`). (c) ACRONYMS AND ABBREVIATIONS: only inspect the canonical term in `chosen`. If `chosen` is itself an acronym or abbreviation, PASS when the prose expands it at least once and states whether the short form is acceptable in product/docs/UI copy; FAIL when it is left unexpanded. Incidental abbreviations that merely appear in the prose (not the headword) are OUT OF SCOPE — ignore them. If `chosen` is not an acronym, this aspect PASSES.","predicate":{"when_node_type":["decision"],"agent_instruction":"Judge a glossary term-entry Decision on three aspects; report each failing aspect with a reason, but treat them as warnings, not hard errors. (a) ONE CONCEPT: PASS when the entry defines one concept or one canonical term; FAIL when it defines multiple independent terms, bundles a term with an unrelated policy, or is a catch-all for several concepts. (b) USABLE DEFINITION: PASS when the `decision` prose gives a concise definition AND the product or domain scope where the term applies AND at least one concrete example OR non-example — EITHER an example or a non-example is sufficient, do not require both; FAIL when one of those three is genuinely absent, or when the prose merely restates the headword instead of explaining it (a circular definition such as `a workspace is a workspace`). (c) ACRONYMS AND ABBREVIATIONS: only inspect the canonical term in `chosen`. If `chosen` is itself an acronym or abbreviation, PASS when the prose expands it at least once and states whether the short form is acceptable in product/docs/UI copy; FAIL when it is left unexpanded. Incidental abbreviations that merely appear in the prose (not the headword) are OUT OF SCOPE — ignore them. If `chosen` is not an acronym, this aspect PASSES."},"lifecycle":"active"},{"id":"policy_01KT7AGRTYE9WV7YRKDHW1H12K","kind":"deterministic","agent_instruction":null,"predicate":{"sub_kind":"requires_edge","edge_type":"supports","when_node_type":["eval"]},"lifecycle":"active"},{"id":"policy_01KT7AGRV2TE5C80JDMWN7HXS3","kind":"deterministic","agent_instruction":null,"predicate":{"fields":["how_to_run"],"sub_kind":"requires_field","when_node_type":["eval"]},"lifecycle":"active"},{"id":"policy_01KT7AGRV60FYEHQZ417RN73AX","kind":"probabilistic","agent_instruction":"Check the Eval's `how_to_run` field. PASS when it gives a concrete rerun path: an exact command, search query, URL, script, or manual review procedure, plus the doc/code/product scope to inspect. FAIL when it is vague (`review docs`, `check terminology`) or depends on unstated context.","predicate":{"when_node_type":["eval"],"agent_instruction":"Check the Eval's `how_to_run` field. PASS when it gives a concrete rerun path: an exact command, search query, URL, script, or manual review procedure, plus the doc/code/product scope to inspect. FAIL when it is vague (`review docs`, `check terminology`) or depends on unstated context."},"lifecycle":"active"},{"id":"policy_01KT7AGRTPG5YA2SPSERE58T35","kind":"deterministic","agent_instruction":null,"predicate":{"field":"chosen","sub_kind":"unique_field","case_fold":true,"when_node_type":["decision"]},"lifecycle":"active"},{"id":"policy_01KT7AGRVKSQVWQF7KS4DXS9A1","kind":"suggestion","agent_instruction":"When aliases, synonyms, misleading labels, or rejected labels exist for the same concept, record them in `alternatives`; otherwise omit `alternatives` rather than inventing filler.","predicate":{"agent_instruction":"When aliases, synonyms, misleading labels, or rejected labels exist for the same concept, record them in `alternatives`; otherwise omit `alternatives` rather than inventing filler."},"lifecycle":"active"},{"id":"policy_01KT7AGRVQRVNSEBHAABCVBN3W","kind":"suggestion","agent_instruction":"When two distinct concepts share a surface form (homographs, e.g. `Order` in commerce vs. `Order` as a sort operation), give each its own Decision and disambiguate `chosen` with a qualifier — `Order (commerce)` vs. `Order (sorting)` — so every entry stays uniquely addressable.","predicate":{"agent_instruction":"When two distinct concepts share a surface form (homographs, e.g. `Order` in commerce vs. `Order` as a sort operation), give each its own Decision and disambiguate `chosen` with a qualifier — `Order (commerce)` vs. `Order (sorting)` — so every entry stays uniquely addressable."},"lifecycle":"active"},{"id":"policy_01KT7AGRVTYWFWJ0A3M7V6YKX0","kind":"suggestion","agent_instruction":"Connect related glossary terms with `relates_to` edges — the associative \"see also\" link — instead of leaving entries isolated, so the vocabulary reads as a navigable network. Link a term to the ones it is easily confused with, its broader or narrower concepts, and the homographs it shares a surface form with. Change a link by retiring the old edge and adding a new one, not by editing endpoints in place; deprecation links use `replaces` instead.","predicate":{"agent_instruction":"Connect related glossary terms with `relates_to` edges — the associative \"see also\" link — instead of leaving entries isolated, so the vocabulary reads as a navigable network. Link a term to the ones it is easily confused with, its broader or narrower concepts, and the homographs it shares a surface form with. Change a link by retiring the old edge and adding a new one, not by editing endpoints in place; deprecation links use `replaces` instead."},"lifecycle":"active"},{"id":"policy_01KT7AGRVYH50YZ5CT3Y9HDFJW","kind":"suggestion","agent_instruction":"Borrowed, standards-based, or industry terms cite their source: add a Reference for the external glossary, spec, or doc and link the term to it with a `derived_from` edge. Product-internal terms state that they are product-specific so readers don't mistake them for external standards.","predicate":{"agent_instruction":"Borrowed, standards-based, or industry terms cite their source: add a Reference for the external glossary, spec, or doc and link the term to it with a `derived_from` edge. Product-internal terms state that they are product-specific so readers don't mistake them for external standards."},"lifecycle":"active"},{"id":"policy_01KT7AGRW496ZM3QF0YP0A6224","kind":"suggestion","agent_instruction":"Retired glossary Decisions point at the replacement term with a `replaces` edge when an old term appears in historical docs, UI, tickets, APIs, or code. Keep the deprecated term visible so readers still understand old references. Re-point by retiring the old edge and adding a new one.","predicate":{"agent_instruction":"Retired glossary Decisions point at the replacement term with a `replaces` edge when an old term appears in historical docs, UI, tickets, APIs, or code. Keep the deprecated term visible so readers still understand old references. Re-point by retiring the old edge and adding a new one."},"lifecycle":"active"},{"id":"policy_01KT7AGRW7NZ6926MCQ9MT5F0R","kind":"suggestion","agent_instruction":"Use Rules for terminology usage policies, such as banned words, capitalization conventions, UI copy constraints, or when two related terms must not be used interchangeably.","predicate":{"agent_instruction":"Use Rules for terminology usage policies, such as banned words, capitalization conventions, UI copy constraints, or when two related terms must not be used interchangeably."},"lifecycle":"active"},{"id":"policy_01KT7AGRWB5KZT6JTTKAHY4WRV","kind":"suggestion","agent_instruction":"Agents read `GET /<handle>/api/authoring-contract.json` for the live field and edge vocabulary, then write terms with `POST /<handle>/api/changesets.json` — creating the term Decision together with its `relates_to`, `derived_from`, or `replaces` edges in the same changeset so an entry never lands isolated.","predicate":{"agent_instruction":"Agents read `GET /<handle>/api/authoring-contract.json` for the live field and edge vocabulary, then write terms with `POST /<handle>/api/changesets.json` — creating the term Decision together with its `relates_to`, `derived_from`, or `replaces` edges in the same changeset so an entry never lands isolated."},"lifecycle":"active"},{"id":"policy_01KT7AGRVEDN2BRCFV4KBA1QD6","kind":"suggestion","agent_instruction":"A glossary is a reference work: a term entry is either the canonical answer (`active`) or a deprecated one kept for lookup (`retired`). Capture a term and it lands `active`; `retire` it when it is superseded, pointing at the successor with a `replaces` edge. You may stub an unfinished term as `drafting` while you work on it, but it is not part of the glossary — and the completeness checks do not apply — until you `activate` it. The framework's `queued` stage has no glossary meaning, so this template stays two-stage like policies do.","predicate":{"agent_instruction":"A glossary is a reference work: a term entry is either the canonical answer (`active`) or a deprecated one kept for lookup (`retired`). Capture a term and it lands `active`; `retire` it when it is superseded, pointing at the successor with a `replaces` edge. You may stub an unfinished term as `drafting` while you work on it, but it is not part of the glossary — and the completeness checks do not apply — until you `activate` it. The framework's `queued` stage has no glossary meaning, so this template stays two-stage like policies do."},"lifecycle":"active"}]},{"doco_id":"doco_01KT7N7VCAGME0ZQQFDM6RQ2Z8","doco_handle":"engineering-priorities","goal":"Document repeatable business processes — actors, gateways, milestones, outcomes. BPMN-inspired.","owner_id":"workspace_01KT7ADYDNY7NNB0W5XE39YB00","policies":[{"id":"policy_2abcdb63173f0eb8523601a208","kind":"deterministic","agent_instruction":null,"predicate":{"sub_kind":"requires_edge_type","edge_types":["flows_to","supports","attributed_to","constrained_by","replaces","derived_from"]},"lifecycle":"active"},{"id":"policy_b98e4ecda756eae2bcc803bf55","kind":"deterministic","agent_instruction":null,"predicate":{"sub_kind":"limits_edge","edge_type":"supports","max_count":1,"when_node_type":["action","decision","state"],"target_node_type":"intent"},"lifecycle":"active"},{"id":"policy_AEA8C783DF7088030B218F579D","kind":"probabilistic","agent_instruction":"You are checking a `serves` relationship from an Action (the `action` endpoint) to a purpose Intent (the `intent` endpoint). STEP 1 — decide whether this is a SUB-PROCESS pairing: the Intent names the SAME single activity as the Action, expanded into its own process (e.g. Action `Posts a job` ↔ Intent `Post a job`). If instead the Action is merely one step within a broader process the Intent names (e.g. Action `review the application` serving Intent `Approve a consumer loan`), this is an ordinary flow-step link, not a sub-process — PASS, the rule does not apply. STEP 2 — for a sub-process pairing, PASS when the Intent's name is the base (imperative) verb form of the Action, i.e. the Action's third-person verb converted to its base form (`Posts a job` → `Post a job`, `Approves the invoice` → `Approve the invoice`). FAIL with `intent name is not the base form of the action` when the Intent's name is in the third-person singular present tense (a verb ending in `-s`) or otherwise does not read as the base-form imperative of the same activity.","predicate":{"edge_type":"supports","to_node_type":"intent","from_node_type":"action","agent_instruction":"You are checking a `serves` relationship from an Action (the `action` endpoint) to a purpose Intent (the `intent` endpoint). STEP 1 — decide whether this is a SUB-PROCESS pairing: the Intent names the SAME single activity as the Action, expanded into its own process (e.g. Action `Posts a job` ↔ Intent `Post a job`). If instead the Action is merely one step within a broader process the Intent names (e.g. Action `review the application` serving Intent `Approve a consumer loan`), this is an ordinary flow-step link, not a sub-process — PASS, the rule does not apply. STEP 2 — for a sub-process pairing, PASS when the Intent's name is the base (imperative) verb form of the Action, i.e. the Action's third-person verb converted to its base form (`Posts a job` → `Post a job`, `Approves the invoice` → `Approve the invoice`). FAIL with `intent name is not the base form of the action` when the Intent's name is in the third-person singular present tense (a verb ending in `-s`) or otherwise does not read as the base-form imperative of the same activity."},"lifecycle":"active"},{"id":"policy_01KT7N7VE4SMJVBTQW12C3C0EC","kind":"deterministic","agent_instruction":null,"predicate":{"sub_kind":"requires_edge","edge_type":"attributed_to","when_node_type":["intent"],"target_node_type":"principal"},"lifecycle":"active"},{"id":"policy_01KT7N7VCJ1DH2RZXY01FS7T1F","kind":"deterministic","agent_instruction":null,"predicate":{"sub_kind":"requires_node_type","node_types":["intent","action","decision","state","eval","reference","rule","principal"]},"lifecycle":"active"},{"id":"policy_01KT7N7VDS6MDRMS2M5KCAZSN9","kind":"deterministic","agent_instruction":null,"predicate":{"field":"state","sub_kind":"unique_field","case_fold":true,"when_node_type":["state"]},"lifecycle":"active"},{"id":"policy_01KT7N7VCQF66M05E0HH9JKZMK","kind":"deterministic","agent_instruction":null,"predicate":{"flags":"i","fields":["intent","action","decision","question","chosen","state","rule","eval","name","body_md"],"pattern":"(exclusiveGateway|parallelGateway|inclusiveGateway|eventBasedGateway|(?:Gateway|Task|UserTask|ServiceTask|SequenceFlow|StartEvent|EndEvent|BoundaryEvent|SubProcess|DataObject)_[A-Za-z0-9]+|user asks:)","sub_kind":"forbids_field_pattern","when_node_type":["intent","action","decision","state","eval","rule","principal"]},"lifecycle":"active"},{"id":"policy_01KT7N7VCTMQ79QNPH19JM7736","kind":"probabilistic","agent_instruction":"Check the candidate's visible user-facing text fields, including name, body_md, intent, action, decision, question, chosen, state, rule, and eval text. PASS when the text reads as business-process language for an operator or process reader, and any BPMN/source/import/code-evidence details are absent from visible prose or kept only in structured metadata, References, or audit/history. FAIL when visible text contains raw import scaffolding or implementation/source metadata, including phrases or patterns like \"BPMN gateway\", \"BPMN task\", \"Gateway_...\", \"Implementation status\", \"Code evidence\", \"Source type\", \"exclusiveGateway\", \"user asks:\", raw BPMN ids, generated object ids, or notes about code evidence discovered during import. Do not fail merely because a real business term happens to mention a job type, gateway, source, or implementation in ordinary process language; fail only when the prose exposes importer/debug/source metadata instead of the process meaning.","predicate":{"when_node_type":["intent","action","decision","state","eval","rule","principal"],"agent_instruction":"Check the candidate's visible user-facing text fields, including name, body_md, intent, action, decision, question, chosen, state, rule, and eval text. PASS when the text reads as business-process language for an operator or process reader, and any BPMN/source/import/code-evidence details are absent from visible prose or kept only in structured metadata, References, or audit/history. FAIL when visible text contains raw import scaffolding or implementation/source metadata, including phrases or patterns like \"BPMN gateway\", \"BPMN task\", \"Gateway_...\", \"Implementation status\", \"Code evidence\", \"Source type\", \"exclusiveGateway\", \"user asks:\", raw BPMN ids, generated object ids, or notes about code evidence discovered during import. Do not fail merely because a real business term happens to mention a job type, gateway, source, or implementation in ordinary process language; fail only when the prose exposes importer/debug/source metadata instead of the process meaning."},"lifecycle":"active"},{"id":"policy_01KT7N7VDD6SR6N10CJDR8H5J5","kind":"deterministic","agent_instruction":null,"predicate":{"sub_kind":"requires_edge","edge_type":"flows_to","min_count":2,"when_node_type":["decision"]},"lifecycle":"active"},{"id":"policy_01KT7N7VDGZP6DFBQ69A69CX21","kind":"probabilistic","agent_instruction":"Check the Decision's `question`, `alternatives`, and any outgoing `flows_to` branch labels/conditions. PASS when the question reads as yes/no or an enumeration, AND the alternatives / outgoing branches either include an explicit default/else branch or name every enumerated value. FAIL with reason if the question has uncovered cases or if a default/else is missing where enum coverage isn't visibly complete.","predicate":{"when_node_type":["decision"],"agent_instruction":"Check the Decision's `question`, `alternatives`, and any outgoing `flows_to` branch labels/conditions. PASS when the question reads as yes/no or an enumeration, AND the alternatives / outgoing branches either include an explicit default/else branch or name every enumerated value. FAIL with reason if the question has uncovered cases or if a default/else is missing where enum coverage isn't visibly complete."},"lifecycle":"active"},{"id":"policy_01KT7N7VDP83RC0ET95YNHRFCN","kind":"suggestion","agent_instruction":"A business process has ≥1 committed (`queued` or `active`) initial State and ≥1 committed terminal State. Every process starts somewhere and ends at a business outcome (or an explicitly cancelled outcome).","predicate":{"agent_instruction":"A business process has ≥1 committed (`queued` or `active`) initial State and ≥1 committed terminal State. Every process starts somewhere and ends at a business outcome (or an explicitly cancelled outcome)."},"lifecycle":"active"},{"id":"policy_01KT7N7VDVDGTJPQ7EJCBSAX27","kind":"deterministic","agent_instruction":null,"predicate":{"sub_kind":"flow-wiring","edge_type":"flows_to","initial_when":{"field":"kind","equals":"initial"},"terminal_when":{"field":"kind","equals":"terminal"},"when_node_type":["action","decision","state"]},"lifecycle":"active"},{"id":"policy_01KT7N7VDYW1W4GAK6J8QJWFCF","kind":"probabilistic","agent_instruction":"Check ONLY the State's `state`. PASS when the text reads as a milestone or entry/exit condition — a noun or past-participle (`invoice approved`, `payment captured`, `cart`, `awaiting-review`). FAIL with reason if it reads as an imperative verb naming an Action (`Approve invoice`, `Process the order`).","predicate":{"when_node_type":["state"],"agent_instruction":"Check ONLY the State's `state`. PASS when the text reads as a milestone or entry/exit condition — a noun or past-participle (`invoice approved`, `payment captured`, `cart`, `awaiting-review`). FAIL with reason if it reads as an imperative verb naming an Action (`Approve invoice`, `Process the order`)."},"lifecycle":"active"},{"id":"policy_01KT7N7VE1N80MN5WK7HF01D24","kind":"deterministic","agent_instruction":null,"predicate":{"sub_kind":"requires_edge","direction":"incoming","edge_type":"attributed_to","when_node_type":["principal"],"target_node_type":"action","exempt_when_other_node_type":"intent"},"lifecycle":"active"},{"id":"policy_01KT7N7VE9WBBVZ7NWVR7GJFZX","kind":"suggestion","agent_instruction":"Model a repeatable business process that produces a business outcome — not a UI journey, a code path, an incident, or a pure state machine. UI journeys and pure state machines belong in their own Docos.","predicate":{"agent_instruction":"Model a repeatable business process that produces a business outcome — not a UI journey, a code path, an incident, or a pure state machine. UI journeys and pure state machines belong in their own Docos."},"lifecycle":"active"},{"id":"policy_01KT7N7VECDMC21PGJP5N3YVNK","kind":"suggestion","agent_instruction":"Use one linked Intent per concrete process when the Doco is large. Split on a durable ownership boundary, reuse across multiple parents, or pure readability.","predicate":{"agent_instruction":"Use one linked Intent per concrete process when the Doco is large. Split on a durable ownership boundary, reuse across multiple parents, or pure readability."},"lifecycle":"active"},{"id":"policy_01KT7N7VEEFYVRGPZKY1D4XV2H","kind":"suggestion","agent_instruction":"When a step is itself a whole sub-process, model it as its own child process Intent and connect the calling Action with a `serves` relationship (stored as `supports` role `serves`) instead of inlining dozens of Actions. The BPMN view collapses the child Intent into its own pool, keeping the parent process readable.","predicate":{"agent_instruction":"When a step is itself a whole sub-process, model it as its own child process Intent and connect the calling Action with a `serves` relationship (stored as `supports` role `serves`) instead of inlining dozens of Actions. The BPMN view collapses the child Intent into its own pool, keeping the parent process readable."},"lifecycle":"active"},{"id":"policy_01KT7N7VEHDHVVHK1K98BZBV0D","kind":"suggestion","agent_instruction":"Name the single accountable process owner in the purpose Intent and link it with an `attributed_to` edge carrying role `owned_by` — the Principal answerable for the whole process's outcome. This is the RACI 'Accountable' role, distinct from the per-step 'Responsible' actors linked by role `performed_by`.","predicate":{"agent_instruction":"Name the single accountable process owner in the purpose Intent and link it with an `attributed_to` edge carrying role `owned_by` — the Principal answerable for the whole process's outcome. This is the RACI 'Accountable' role, distinct from the per-step 'Responsible' actors linked by role `performed_by`."},"lifecycle":"active"},{"id":"policy_01KT7N7VEM3PEK8QKGP5N1P1QS","kind":"suggestion","agent_instruction":"Agents should read `GET /<handle>/api/authoring-contract.json` and write structured flows with `POST /<handle>/api/changesets.json`; create flow nodes and their relationship edges in the same changeset, using the contract's role examples instead of disconnected nodes or ad hoc relationship names.","predicate":{"agent_instruction":"Agents should read `GET /<handle>/api/authoring-contract.json` and write structured flows with `POST /<handle>/api/changesets.json`; create flow nodes and their relationship edges in the same changeset, using the contract's role examples instead of disconnected nodes or ad hoc relationship names."},"lifecycle":"active"},{"id":"policy_01KT7N7VEPSB1WG6Y23J3DVK81","kind":"suggestion","agent_instruction":"Use `relate_many` for sibling edges that must be valid together, especially exhaustive gateway branches. Adding one branch at a time can create a temporarily invalid BPMN graph.","predicate":{"agent_instruction":"Use `relate_many` for sibling edges that must be valid together, especially exhaustive gateway branches. Adding one branch at a time can create a temporarily invalid BPMN graph."},"lifecycle":"active"},{"id":"policy_01KT7N7VFMHKW1R8JTS101DBED","kind":"suggestion","agent_instruction":"Don't model every click, method call, or DB mutation — only the steps that mean something to a business operator. Implementation detail belongs in `apis` or code Docos, not here.","predicate":{"agent_instruction":"Don't model every click, method call, or DB mutation — only the steps that mean something to a business operator. Implementation detail belongs in `apis` or code Docos, not here."},"lifecycle":"active"},{"id":"policy_01KT7N7VES5KY25TVYYKYVRP8C","kind":"suggestion","agent_instruction":"BPMN vocabulary: `flows_to` is process order and renders source -> target with no reversal; `serves` (stored as `supports`) places nodes in Intent pools; `performed_by`, `decided_by`, and `owned_by` (stored as `attributed_to`) drive actor lanes, gateway deciders, and process ownership; `gated_by` (stored as `constrained_by`) links policy guards; `tests`, `enacts`, and `implemented_by` use `supports` with role metadata for validation, rationale, and evidence.","predicate":{"agent_instruction":"BPMN vocabulary: `flows_to` is process order and renders source -> target with no reversal; `serves` (stored as `supports`) places nodes in Intent pools; `performed_by`, `decided_by`, and `owned_by` (stored as `attributed_to`) drive actor lanes, gateway deciders, and process ownership; `gated_by` (stored as `constrained_by`) links policy guards; `tests`, `enacts`, and `implemented_by` use `supports` with role metadata for validation, rationale, and evidence."},"lifecycle":"active"},{"id":"policy_01KT7N7VEVY1S2QVH5ZY7APXH3","kind":"suggestion","agent_instruction":"`flows_to` edges may carry props like `{ label, condition, kind }`. Put gateway branch labels and default/exception/timer metadata on the outgoing edge, not by reversing a relationship from the downstream Action back to the Decision.","predicate":{"agent_instruction":"`flows_to` edges may carry props like `{ label, condition, kind }`. Put gateway branch labels and default/exception/timer metadata on the outgoing edge, not by reversing a relationship from the downstream Action back to the Decision."},"lifecycle":"active"},{"id":"policy_01KT7N7VEY6EMVT8HJD5EJKAYQ","kind":"suggestion","agent_instruction":"For parallel work, give one flow node multiple unconditional `flows_to` outgoing edges — an AND-split needs no gateway Decision. Reserve gateway Decisions for exclusive or conditional (XOR/inclusive) branching, and reconverge parallel branches on a shared downstream node.","predicate":{"agent_instruction":"For parallel work, give one flow node multiple unconditional `flows_to` outgoing edges — an AND-split needs no gateway Decision. Reserve gateway Decisions for exclusive or conditional (XOR/inclusive) branching, and reconverge parallel branches on a shared downstream node."},"lifecycle":"active"},{"id":"policy_01KT7N7VF1PQ3CCQ2QCHPE1C0J","kind":"suggestion","agent_instruction":"Rework and retry loops are allowed: a `flows_to` edge may target an earlier flow node to send work back (revise-and-resubmit, fix-and-recheck). Route the loop back through a gateway Decision so the cycle has an explicit exit and can't spin forever. A single edge still renders source -> target — a loop is about where the edge points, not reversing its direction.","predicate":{"agent_instruction":"Rework and retry loops are allowed: a `flows_to` edge may target an earlier flow node to send work back (revise-and-resubmit, fix-and-recheck). Route the loop back through a gateway Decision so the cycle has an explicit exit and can't spin forever. A single edge still renders source -> target — a loop is about where the edge points, not reversing its direction."},"lifecycle":"active"},{"id":"policy_01KT7N7VF456EQSQJ687WX21QX","kind":"suggestion","agent_instruction":"Model the unhappy path. Use `flows_to` edge props with `kind: \"exception\"` or `kind: \"timer\"` to route failures, rejections, and timeouts to a recovery step or an explicitly cancelled terminal State, so the process documents what happens when the happy path does not hold.","predicate":{"agent_instruction":"Model the unhappy path. Use `flows_to` edge props with `kind: \"exception\"` or `kind: \"timer\"` to route failures, rejections, and timeouts to a recovery step or an explicitly cancelled terminal State, so the process documents what happens when the happy path does not hold."},"lifecycle":"active"},{"id":"policy_01KT7N7VF62GEJX0VNVXKT7B9Z","kind":"suggestion","agent_instruction":"Relationships in a business-processes Doco are first-class edges with lifecycle and history. Use `flows_to` for process order and the canonical families (`supports`, `attributed_to`, `constrained_by`, `has_parent`, `derived_from`, `replaces`, `relates_to`) with role metadata for specialized meanings. Re-point by retiring the old edge and adding the new one; endpoints are immutable.","predicate":{"agent_instruction":"Relationships in a business-processes Doco are first-class edges with lifecycle and history. Use `flows_to` for process order and the canonical families (`supports`, `attributed_to`, `constrained_by`, `has_parent`, `derived_from`, `replaces`, `relates_to`) with role metadata for specialized meanings. Re-point by retiring the old edge and adding the new one; endpoints are immutable."},"lifecycle":"active"},{"id":"policy_01KT7N7VFC0REW25C615A3QF2T","kind":"suggestion","agent_instruction":"Use `queued` for a process — or a single step, gateway, or milestone — that is fully wired and ready but not yet in force: a redesign awaiting sign-off, a step pending a scheduled go-live, or an approved-but-not-yet-rolled-out change. A `queued` node asserts readiness, so it must already satisfy the same actor, `serves`, and forward-flow wiring an `active` node does. If it is still being sketched and that wiring is incomplete, leave it `drafting` instead of queuing it.","predicate":{"agent_instruction":"Use `queued` for a process — or a single step, gateway, or milestone — that is fully wired and ready but not yet in force: a redesign awaiting sign-off, a step pending a scheduled go-live, or an approved-but-not-yet-rolled-out change. A `queued` node asserts readiness, so it must already satisfy the same actor, `serves`, and forward-flow wiring an `active` node does. If it is still being sketched and that wiring is incomplete, leave it `drafting` instead of queuing it."},"lifecycle":"active"},{"id":"policy_01KT7N7VFFDE4SWHE9SPZFYNM9","kind":"suggestion","agent_instruction":"Process *instances* (recorded runs) live in a separate Doco as Logs; surface them here only via References. This template describes the design of the process, not the history of its executions.","predicate":{"agent_instruction":"Process *instances* (recorded runs) live in a separate Doco as Logs; surface them here only via References. This template describes the design of the process, not the history of its executions."},"lifecycle":"active"},{"id":"policy_01KT7N7VFHRBWJQFE3ECNZN4GB","kind":"suggestion","agent_instruction":"Rules in a business-processes Doco are process policies and guards (`refunds above $5k require manager approval`). Template-authoring rules — meta-rules about how to write process Docos — belong in the template or in `global`, not in any process using it.","predicate":{"agent_instruction":"Rules in a business-processes Doco are process policies and guards (`refunds above $5k require manager approval`). Template-authoring rules — meta-rules about how to write process Docos — belong in the template or in `global`, not in any process using it."},"lifecycle":"active"},{"id":"policy_01KT7N7VD2ZDJ909MCT4W4G6R8","kind":"probabilistic","agent_instruction":"Read the ENTIRE `prose` field. PASS when it identifies a single repeatable business process — recognizable as a verb + object (e.g. `publish a job`), optionally with an adjective or adverb — and reads as a concise statement of that process's purpose. FAIL when no single process is identifiable, when several distinct processes are bundled together, or when it sprawls into a multi-paragraph specification instead of a focused purpose. Grade the whole field; do not privilege or judge any single line.","predicate":{"when_node_type":["intent"],"agent_instruction":"Read the ENTIRE `prose` field. PASS when it identifies a single repeatable business process — recognizable as a verb + object (e.g. `publish a job`), optionally with an adjective or adverb — and reads as a concise statement of that process's purpose. FAIL when no single process is identifiable, when several distinct processes are bundled together, or when it sprawls into a multi-paragraph specification instead of a focused purpose. Grade the whole field; do not privilege or judge any single line."},"lifecycle":"active"},{"id":"policy_01KT7N7VDKCKF24JVDKM6BQ7M6","kind":"deterministic","agent_instruction":null,"predicate":{"sub_kind":"requires_edge","edge_type":"attributed_to","when_node_type":["decision"],"target_node_type":"principal"},"lifecycle":"active"},{"id":"policy_01KT7N7VE6MBEFTKP3DXGTW5Z8","kind":"deterministic","agent_instruction":null,"predicate":{"sub_kind":"requires_edge","edge_type":"supports","when_node_type":["eval"]},"lifecycle":"active"},{"id":"policy_01KT7N7VD5FG3Y5YGM0R27073R","kind":"deterministic","agent_instruction":null,"predicate":{"sub_kind":"requires_edge","edge_type":"attributed_to","when_node_type":["action"],"target_node_type":"principal"},"lifecycle":"active"},{"id":"policy_01KT7N7VD8GNX5PHP32C3VKTP6","kind":"deterministic","agent_instruction":null,"predicate":{"sub_kind":"requires_edge","edge_type":"supports","when_node_type":["action","decision","state"],"target_node_type":"intent"},"lifecycle":"active"},{"id":"policy_01KT7N7VF9XWTZXN3AKSRHVYTR","kind":"suggestion","agent_instruction":"Walk a process node through the four-stage lifecycle drafting → queued → active → retired. A `drafting` sketch may be incomplete — serving an Intent, forward `flows_to` wiring, gateway exhaustiveness, milestone naming, and quality are all suspended, so a step can be drafted before its Intent (and BPMN pool) is chosen — except that an Action must still name its actor and a gateway Decision its decider, each via an `attributed_to` edge to a Principal, from the moment it is drafted, so neither floats free of a Principal even in draft. `queue` it (changeset op `queue`) once it supports its Intent and its forward `flows_to` wiring is coherent and the design is ready; `activate` it (op `activate`) when it is the governing, in-force process. Both committed stages — `queued` and `active` — are held to the full shape rules. `retire` a node when it is withdrawn, or `supersede` it when a redesign replaces it (the op creates the replacement and links the two with a `replaces` edge).","predicate":{"agent_instruction":"Walk a process node through the four-stage lifecycle drafting → queued → active → retired. A `drafting` sketch may be incomplete — serving an Intent, forward `flows_to` wiring, gateway exhaustiveness, milestone naming, and quality are all suspended, so a step can be drafted before its Intent (and BPMN pool) is chosen — except that an Action must still name its actor and a gateway Decision its decider, each via an `attributed_to` edge to a Principal, from the moment it is drafted, so neither floats free of a Principal even in draft. `queue` it (changeset op `queue`) once it supports its Intent and its forward `flows_to` wiring is coherent and the design is ready; `activate` it (op `activate`) when it is the governing, in-force process. Both committed stages — `queued` and `active` — are held to the full shape rules. `retire` a node when it is withdrawn, or `supersede` it when a redesign replaces it (the op creates the replacement and links the two with a `replaces` edge)."},"lifecycle":"active"},{"id":"policy_01KT7N7VCFAZZZVZXSNYX38TWV","kind":"probabilistic","agent_instruction":"A node belongs in process when it describes a workflow — a sequence of steps with actors and an outcome — or a policy/guard for one. Workflows can be commercial, operational, or personal; what matters is that the work is repeatable and the steps can be named. Pass when the candidate describes a step, gateway, milestone, validation, reference, or policy for such a workflow. Fail only when the candidate is a one-off incident with no repeatable structure, a UI-specific user journey, or a pure state machine without a workflow outcome.","predicate":{"when_node_type":["intent","action","decision","eval","reference"],"agent_instruction":"A node belongs in process when it describes a workflow — a sequence of steps with actors and an outcome — or a policy/guard for one. Workflows can be commercial, operational, or personal; what matters is that the work is repeatable and the steps can be named. Pass when the candidate describes a step, gateway, milestone, validation, reference, or policy for such a workflow. Fail only when the candidate is a one-off incident with no repeatable structure, a UI-specific user journey, or a pure state machine without a workflow outcome."},"lifecycle":"active"},{"id":"policy_01KT7N7VCW8WR8Q3G2QTX56Z30","kind":"probabilistic","agent_instruction":"Check the Principal's `prose`. PASS when it clearly names a process actor — a role, team, external party, or system — and explains what responsibility or boundary it owns in this process. FAIL if it reads like an uncontextualized org-chart person, a vague label (`user`, `team`, `system`) with no process responsibility, or an empty shell with only a bare name.","predicate":{"when_node_type":["principal"],"agent_instruction":"Check the Principal's `prose`. PASS when it clearly names a process actor — a role, team, external party, or system — and explains what responsibility or boundary it owns in this process. FAIL if it reads like an uncontextualized org-chart person, a vague label (`user`, `team`, `system`) with no process responsibility, or an empty shell with only a bare name."},"lifecycle":"active"},{"id":"policy_01KT7N7VDBKPMV6H9DJ4Y5J1Q5","kind":"probabilistic","agent_instruction":"Check the Action's `prose` and `verb`. PASS when the text names a single business activity the named actor performs — an ordinary single-verb step like `review the legal terms`, `approve the invoice`, or `pack the order` PASSES. FAIL with reason only if the text (a) is a vague umbrella phase covering many steps (e.g. `handle request`, `do the thing`, `process order`), (b) bundles two distinct activities joined by `and` (e.g. `examine and treat the patient`), or (c) is an implementation chore divorced from business meaning (e.g. `call API`, `update row`, `write to DB`).","predicate":{"when_node_type":["action"],"agent_instruction":"Check the Action's `prose` and `verb`. PASS when the text names a single business activity the named actor performs — an ordinary single-verb step like `review the legal terms`, `approve the invoice`, or `pack the order` PASSES. FAIL with reason only if the text (a) is a vague umbrella phase covering many steps (e.g. `handle request`, `do the thing`, `process order`), (b) bundles two distinct activities joined by `and` (e.g. `examine and treat the patient`), or (c) is an implementation chore divorced from business meaning (e.g. `call API`, `update row`, `write to DB`)."},"lifecycle":"active"}]},{"doco_id":"doco_01KT3CFKZMCB3JE838E0R97J90","doco_handle":"mcp-smoke-1780377701","goal":"Smoke-test the hosted MCP connector.","owner_id":"workspace_01KT21YGMPGG21RK6V9MVD968J","policies":[]}]}