pub const PROTOCOL: &str = "# The seat protocol\n\nOne seat, five stores, five questions. Ask the store that owns the question.\n`ljos` is the one command in front of them; `ljos-mcp` serves the same verbs\nover the Model Context Protocol (MCP). Every verb below has a tool of the same\nname with the prefix `ljos_`.\n\n| question | store | verbs |\n|---|---|---|\n| what did the human freeze | cards | `cards` (read-only; never extract-on-write) |\n| what is the work, what blocks it, who agrees | tracker (vissue) | `recall`, `vote`, `consensus`, `deed`; `vissue create`, `vissue note`, `vissue update` |\n| what does this seat know, standing | pack (packset) | `search`, `island`, `remember`, `prefer`, `forget`, `due`, `graded` |\n| what did the work produce | deed store (deedar) | `evidence`, `current`; `deedar create` |\n| which work is claimable right now | claim graph (claimdag) | `claim`, `release`, `complete` |\n| how do the voters weigh each other | pack, trust rows | `trust`, `learn`, `calibrate` |\n| who votes with a view of its own | pack, persona atoms | `persona`, `vote --as` |\n| which recipe this sitting copies | pack, playbook atoms | `playbook`, `playbooks`; `sitting --playbook` |\n\nA failure is a store not answering. It is never an empty answer. When a verb\nfails, run `doctor` before drawing any conclusion.\n\n## Before the work: a sitting\n\nOne verb runs the whole opening in order and stops at the first store that\ndoes not answer:\n\n ljos sitting ISSUE --assignee NAME [--playbook NAME]\n\nIt prints nine sections, and each one is a step you would otherwise run by\nhand. Each answers something the next one needs. Between the island and the\nrecall it reads the issue\'s blockers from the tracker: an issue whose\nblockers are still open is refused before anything is claimed, because the\ngraph says it is not workable; `--anyway` sits on it regardless and says so.\nThen it copies one playbook into `== playbook` before recall: `--playbook`\nnames it, else a name already bound on the issue, else a closed-set token\nin the title, else `sit`. Sitting always binds one of the five before\nclaim. A panel is refused until one is bound. The name lives on the\ntracker as a `playbook:` note until `finish` or `release`.\n\n1. `ljos doctor`. A `no` on `tracker`, `deed store` or `pack` is the answer;\n `packsetd` on a scratch port starts a pack writer. Do not proceed on a `no`.\n2. `ljos cards`. What the human froze. Read, never write.\n3. `ljos due`. What is due for review: the soonest eight and the total.\n The verb prints a page; it does not grade. After the sitting, check a\n shown claim against the work and `ljos graded ID` (`--lapsed` when it\n no longer holds). `graded` takes only a claim a due page showed in the\n last hour, so a saved list cannot be graded unread; `ljos due --all`\n lists everything to read and puts none of it up. The review clock\n moves only when you grade, and a backlog is left due, not drained.\n4. `ljos island` on the issue\'s title. The sitting takes the strongest\n eight. The number on a row is spread along links, not a rank.\n `--as NAME` walks that persona\'s weights. `--fire` after the island\n was used rewrites those weights, and the next walk follows them. A\n weak island does not fire. `ljos search TOPIC` and a full\n `ljos island TASK` are during the work, not this opening.\n5. `ljos playbook ISSUE NAME`, or `--playbook NAME` on the sitting. The\n five shipped recipes are `sit`, `arena`, `land`, `company-panel`,\n `overnight`. Kind `playbook`, weighed not recalled. Pack latest per\n name is the copy; shipped bodies seed only when the pack has no live\n atom of that name. Write, list, bind, and copy refuse any other name.\n `ljos playbooks` lists the five. Absent a name, the sitting matches\n the title or binds `sit`. Mid-sitting turns re-read the same note; a\n new task is a new sitting. Finish and release write `playbook:` so\n the next sitting does not reprint the previous recipe.\n6. `ljos recall ISSUE`. The plan, the inputs\' deeds, and what the issue has\n cited so far.\n7. `ljos timeline ISSUE`. The last twelve dated events across the three\n stores; `ljos timeline` without a sitting prints them all.\n8. `ljos claim ISSUE --assignee NAME`. Occupancy is `{name}:{issue}`:\n two conversations hold two tickets. The same issue is still one\n holder. `busy` on a named worker means that name still holds another\n node (`ljos complete` or `ljos release`). The tracker moves to STARTED under the same name, so\n `vissue claims` answers who holds it; a tracker that refuses the name\n refuses the sitting, and `ljos release` frees the claim graph.\n\nA decision is handed to the panel by the sitting. An issue tagged\n`decision`, typed `decision`, or with a body line opening `Options:`\nbinds the `company-panel` recipe, and the sitting writes one brief per\npersona the issue speaks to under `== panel`. Start one subagent per\nbrief; each ends with `ljos vote ISSUE --for OPTION --as NAME`, then\n`ljos consensus ISSUE`. `ljos finish ISSUE --close` refuses a decision\nwith fewer than two ballots. Put any choice with more than one defensible\nanswer on an issue this way before building it.\n\nMemory crosses machines through the tracker repository. A repository\nwhose `.ljos/sync.toml` names a scope and its age recipients carries one\nsealed log per machine under `.ljos/atoms/`. The sitting pulls and takes\nthe other machines\' logs before the island is walked; finish writes and\npushes this machine\'s. `ljos sync --key` prints this machine\'s public key\nfor a scope\'s recipients, and `ljos sync` runs the pull and the push by hand. An\natom goes to the scope its `scope:NAME` entity names, else the machine\'s\n`default_scope` in `~/.config/ljos/sync.toml`. A lesson from `finish`\ntakes the scope of the repository its issue lives in, and a\n`[projects]` table in that repository\'s `sync.toml` sends one project\'s\nlessons to another scope (`tools = \"shared\"`).\n\nNo issue yet? `vissue q -p PROJECT \"TITLE\"` mints one and prints its id.\nEvery piece of work has an issue before it has a claim.\n\n## During the work\n\n- Every artefact the work produces is a deed, then a citation:\n `deedar create file --name NAME --path PATH --agent NAME` prints an\n accession; `ljos deed ISSUE --add ACCESSION` cites it on the issue.\n Citing a deed names it; the bytes stay in deedar.\n- A lesson is one `ljos remember` of two short sentences at most. It is\n stored as an episode and is not a refresher until `ljos graded ID`\n recalls it, or until consolidation finds it replaced an earlier claim.\n `ljos remember --standing` writes a rule now. A standing choice between\n two ways is one `ljos prefer`. Never a transcript, never a summary of the session. A\n correction from the person (\"you should have\", \"do you not remember\")\n is a preference the pack does not hold: write it with `ljos prefer`\n before the work it corrects, not after. A\n lesson that rewrites an earlier one closes the earlier one\'s window; the\n verb says `revises N earlier memories` when it did. `ljos consolidate`\n reports the pairs the rule would close across what is held, and\n `--apply` closes them; run it after a handover is imported.\n `ljos conflicts` lists the likeliest contradictions by distance rather\n than by words, when the `landscape` habitat is installed.\n- Every number the seat keeps measuring is a habit: `ljos habit NAME VALUE\n [--unit U] [--every 7d] [--source JOB]` takes a reading, closes the one\n before it (kept as what it was), and puts the next reading on the review\n clock one cadence on, so `ljos due` and the hook say when it is late.\n `ljos habit` lists the habits as they stand with the change since the\n last reading; `ljos search --as-of` answers what one stood at then. A\n benchmark score, a latency, a count of open tickets: readings, not\n lessons.\n- Every decision with more than one defensible answer is a ballot:\n `ljos vote ISSUE --for OPTION --confidence P --used DEED` once per\n identity (`VISSUE_AGENT`). `P` in `(0, 1]` is the probability the voter\n gives that its choice is the outcome (DeGroot 1974,\n doi:10.1080/01621459.1974.10480137). Omit it and the ballot is not a\n forecast. `--used` is the deeds the ballot drew on, or `none`\n (Buneman, Khanna and Tan 2001, doi:10.1007/3-540-44503-X_20). The\n line it prints is a count, not the settle. When an outcome is named,\n a stated probability is scored by the quadratic score `(p - o)^2`\n (Brier 1950; Gneiting and Raftery 2007,\n doi:10.1198/016214506000001437). The logarithmic score is `-ln` of the\n probability put on what happened (Good 1952,\n doi:10.1111/j.2517-6161.1952.tb00104.x); it is unbounded when that\n probability is 0. Across a voter\'s forecasts, mean probability against\n the event rate is calibration in the large (Dawid 1982,\n doi:10.1080/01621459.1982.10477856). From the second forecast, Murphy\'s\n partition splits the Brier score into reliability, resolution, and\n uncertainty (1973,\n doi:10.1175/1520-0450(1973)012<0595:ANVPOT>2.0.CO;2). None of these\n scores is a trust weight. Then\n `ljos consensus ISSUE`. The first lines are the reading. Polarization is\n how far voters still sit from the mean after listening, disagreement how\n far neighbors still sit from each other. Both zero with one option means\n there was one option. Act on the shares when polarization is about zero\n and two or more options were named. When polarization is away from zero,\n the mean is not a position the group reached. A tally printed later is\n who voted. On a hard question the ballot carries the private forecast\n of the others, `ljos vote ISSUE --for OPTION --expect OPTION`; `ljos predict`\n still records one on its own. With two or more forecasts\n the settle also names the surprisingly popular answer, the option whose\n actual share most exceeds its forecast, and shows each voter\'s standing.\n When the world says which option was right, `ljos finish ISSUE\n --outcome OPTION` (or `ljos learn`) writes every voter\'s record of\n outcomes as its weight, so the next settle weighs a voter by what it\n got right.\n- When the work has shown that a kind of command must never run, or must\n be asked about first, write the law: `ljos rule \'PATTERN\' --verdict\n deny|ask --why \"...\"`. The hook stops or asks at the point of action and\n `ljos policy` says the same; the rule is memory and travels in handovers.\n- When the work wants readers with views of their own, such as a reviewer\n for a broad audience beside a domain expert, write each once:\n `ljos persona NAME --anchor A --view \"...\" --about DOMAIN...`, and\n `ljos personas` prints the roster the pack holds. Then\n `ljos vote ISSUE --for OPTION --as NAME` casts as it. The anchor in\n `[0, 1]` is how far it moves off its ballot in the settle; 0 never moves.\n A trust row scoped with `--about DOMAIN` applies when the issue\'s title\n carries that word; `learn` writes its rows scoped to what the issue\'s\n island is about, so being wrong on one topic costs nothing elsewhere.\n A panel is one subagent per persona, each started from\n `ljos brief NAME ISSUE` (the view, the bound playbook\'s full recipe,\n the five named principles, the arena rubric, what the seat knows on its\n domains, the working set), each casting one ballot as itself, then\n `ljos consensus`; over MCP the `run_a_panel` prompt orders it, and\n without MCP `ljos panel ISSUE --out DIR` writes one brief per persona.\n A panel is refused until a playbook is bound (`ljos playbook ISSUE NAME`\n or `ljos sitting ISSUE --playbook NAME`). Both seat only the personas\n whose `--about` domains the issue\'s title or island names. A persona\n with no domains sits only when no domain matches. When the pack holds\n only specialists and none matches, the five whose views use the\n issue\'s words most sit, and a panel with nobody to seat says so and\n stops. A panel that seats everyone is a count. Model names on a\n playbook are optional spawn hints; every member still ends with\n `ljos vote --as` then `ljos consensus`. One playbook step per\n subagent; no resume across phases. Each brief is a file to start a\n subagent from. A panel\n member\'s own lesson goes in with `ljos remember --as NAME \"...\"` and\n comes back to it first in its next brief; the seat still reads it. The kind of work sets the dynamics: tag\n the issue `broad` when the panel is a broad audience, and the settle runs\n bounded confidence, so clusters are allowed and reported instead of being\n averaged into one position.\n Writing a persona also writes one unscoped inbound trust row (the seat\n weighs it at 1, everywhere); `--about` on a later trust row only adds\n weight.\n- Progress goes on the issue, dated: `vissue note ISSUE \"...\"`.\n\n### A bump, and a build campaign\n\nA toolchain or version bump with eb-stack is one sitting on the ticket\nand one island per recipe. Before a recipe is touched, `ljos island\n\"<name> <version> <toolchain>\"` (the MCP `ljos_island` with that cue):\nwhat the last bump of it taught, the patch it needed, the step it failed\nin. Then the ladder in order, each rung its own claim with its own\nartifact: `eb_recipe_check`, `eb_package_bump` (the lock under\n`out/locks` is `resolves`), `eb_recipe_lint`, `eb_target_doctor`,\n`eb_campaign_run` and `eb_campaign_status` (`builds`,\n`binary-verified`). Say a rung only when its artifact exists.\n\nA generation bump is many modules under one ticket, and the tracker\'s\ngraph is how a herd shares them: `ljos bump-plan out --project P\n--parent TICKET` (over MCP, the tool `bump_plan`) puts every module the\nbundle\'s lock builds on the tracker as a child issue, blocked by the\nmodules built before it along the SBOM\'s edges, with the same ids on\nevery run. `vissue ready -p P` is then the buildable frontier, each seat\nsits on one module, and a sitting on a module whose blockers are open\nis refused. Resolve each finding through eb-stack\'s `campaign finding\nresolve` with the action and the files it changed, so the lesson below\ncarries the fix.\n\nEvery typed finding the campaign records is a lesson once somebody\nresolved it: `ljos findings out/campaign.json --remember --issue ISSUE`\n(the MCP `ljos_findings`) writes one lesson per resolved finding under\nthe recipe\'s name, the package and the failure class, and cites the\nstate file on the issue. A finding a later attempt merely got past is\nnot a lesson; `--all` takes those too. A lesson the seat writes by hand\nnames the recipe, the step, the error line and the fix: \"GCCcore-15.2.0\non terra: compile failed in the build step with linux/scc.h missing.\nFix: the GCC 14 libsanitizer kernel headers patch.\" Not \"verify the\nlock exists before proceeding\": the next seat cannot act on that.\n\n- A subagent works under its parent\'s sitting and opens none of its\n own. What it finds joins the parent\'s issue. A judgement between\n options is `ljos vote ISSUE --for OPTION --as NAME`. A lesson still\n true next time is `ljos remember \"...\" --as NAME`, and a finding is\n `vissue note ISSUE \"...\"`. NAME is its persona, else its subagent\n type. On a runner that fires subagent events, the hook names the\n parent\'s issue on the subagent\'s first tool result. It keeps the\n subagent working once at its stop while that issue is open.\n\n- Tracker and sync commits queue under `ljos-commit.lock` in the git\n directory, and a commit waits out another git process\'s `index.lock`.\n Never wrap a verb in a lock of your own, and never stash, reset or\n check out files another seat is editing to get a commit through.\n\n## After the work\n\nOne verb closes the sitting:\n\n ljos finish ISSUE --status done --lesson \"...\" [--outcome OPTION] [--close]\n\nIt remembers the lesson, fires the island, completes the session node, and\nlearns from the outcome when one is named. Without `--lesson` it says so;\na sitting that taught nothing worth two sentences is rare. By hand, the\nsame four steps are:\n\n1. `ljos remember \"...\"` when the sitting taught a lesson.\n2. `ljos island TASK --fire` when the island served: the strongest memories\n fire together and their links gain weight.\n3. `ljos complete ISSUE --status done` (`failed`, `cancelled`). Completing\n the session node does not close the ticket: `vissue update ISSUE -s DONE`\n does, when the work is accepted.\n Nor does `finish`: `--close` on it does, for the same acceptance.\n4. `ljos learn ISSUE --outcome OPTION` when the world says which option was\n right. Every voter it refuted shrinks in every other voter\'s row, and a\n persona it refuted holds its next ballot less firmly.\n\nWhen the tracker is a git checkout, `sitting` after its claim and `finish`\nat the end commit the ticket\'s `issues.org` (that file alone) and push it,\nand print a `tracker git:` line. A claim or a closure that stays in one\nworking tree does not exist for any other host. `LJOS_TRACKER_GIT=commit`\nkeeps it local; `=off` skips it. A refused push is reported, not raised:\npush the tracker yourself before you leave. `ljos doctor` names how many\ncommits origin lacks, and fails the tracker row when that count sits\nthrough the push wait; a leftover refused-push log is named on the row.\n\n`ljos handover --out DIR --issue ISSUE [--to user@host:path]` is a separate\nverb for when another seat takes over. The receiver runs `ljos receive DIR`,\nthen `--import`.\n\n## When nobody names an outcome\n\nMost issues close without anyone saying which option was right, and then\n`learn` never runs and every voter keeps the same weight. `ljos calibrate\n--project PROJECT` reads every issue of the project with two or more\nballots and estimates each voter\'s accuracy from how often it agrees with\nthe answer the other voters make likely (Dawid and Skene), then writes\nthose accuracies back as trust rows. Run it once per project after a few\nissues have been voted on, and again when many more have. A consensus\nunder equal weights is a count; under calibrated rows it is not.\n\n## Refusals worth knowing\n\n- `claim: assignee busy HEX`: that name still holds that node.\n `ljos release HEX --assignee NAME` hands it back, `ljos complete HEX`\n finishes it. Occupancy is per issue, so a second ticket does not take\n this path.\n- `already held by NAME; the sitting resumes`: not a refusal. A second\n `sitting` on the issue you hold renews the lease and goes on. Held by\n another seat, the claim names that actor and the two verbs that free it.\n- `complete: status not terminal`: the statuses are `done`, `failed`,\n `cancelled`. To stop without finishing, `release`.\n- `panel: no playbook bound`: personas cannot enter until a recipe is\n named. `ljos playbook ISSUE NAME` or `ljos sitting ISSUE --playbook NAME`.\n- `playbook: ISSUE is bound to NAME until finish or release`: mid-sitting\n turns re-read that note. A new task is a new sitting.\n- A claim on an issue whose earlier sitting finished reopens its session\n node and takes it: a new sitting on old work, with the ledger kept.\n- `not a deed accession`: `--why` on `forget` and `trust` takes accessions\n from `deedar`, never free text.\n- `the pack writer did not answer`: the pack is down, not empty.\n `packset ensure`.\n- `no tracker ... relative root` or `root is not a directory` in `doctor`:\n the tracker root is private to your working directory (often a\n `VISSUE_ROOT` that kept a literal `~`). Anything filed there is invisible\n to every other seat. Fix the root before filing.\n- `no tracker ... N unpushed` in `doctor`: the tracker checkout holds\n commits origin does not. Closures on this host are invisible everywhere\n else. Push the tracker. A leftover `tracker-push-*.log` names the last\n refusal when the push was refused. The row also fails when another remote\n of the tracker holds a different head of the branch, as of the last fetch;\n seats that push to different remotes never see each other\'s claims.\n- `deedar: warning: this deed is signed by ed25519:...`: the host key is\n not a signer the store\'s `layout` lists, and `evidence` will refuse the\n deed. Add the printed `signer =` line to that file.\n- A refused `remember` names the sentence, its word count and the limit:\n split it where it says.\n- `ljos due` prints `0 due; nothing scheduled`: the seat has remembered\n nothing, and the review loop has nothing to run on. Remember something.\n `0 due; N scheduled, next at T` is a clock that is running.\n- `ljos policy ARGV` prints the line a command would run under argv law,\n then what the pack knows that bears on it. It is not a check.\n- `ljos hook` is the memory hook: a runner or a policy layer pipes the\n action about to happen (its hook JSON, or the plain argv) and gets back\n the memories that action activates, what two of the pack\'s scorers\n agreed on, preferences first, then lessons\n oldest to newest, each with its age (`[lesson, 3 weeks ago]`), so a\n later lesson reads as a revision of an earlier one. When the session\n ends, the memories it injected fire together, so what served one sitting\n is wired for the next. `ljos onboard`\n installs it on the runner\'s tool-call and prompt events, so the seat\'s\n memory reaches the agent at the point of action without being asked.\n\n## Identity and environment\n\nNothing here needs a variable set. The pack is found on `127.0.0.1:8761`\nand the seat\'s memory is one workspace, `seat`, whatever directory you\nstand in (`PACKSET_WORKSPACE` names another). The deed store and claim\ngraph live in the user\'s state directories, the tracker at the root\n`vissue identity` prints, and the host key at `~/.config/deedar/host.key`\nwhen it exists. The seat is the program that connected: `ljos-mcp` names\nit after the client that initialised it, and a shell the same runner opens\nfinds the same name through the process tree, so a runner\'s tools and its\ncommand-line verbs claim and vote as one. Two names come from that: the\nseat (`acme-cli`), which memory, ballots and trust rows accrue to across\nevery conversation of that runner, and the holder (`acme-cli-39u`),\nwhich this conversation\'s claims are held under; any `*_SESSION_ID` the\nrunner stamped is the holder ahead of the process tag, and occupancy is\n`{holder}:{issue}`, so two conversations of one runner hold two tickets and\na second sitting does not release the first. `ljos seat` prints both names\nand where they came from. `LJOS_SEAT` names the seat; a `*_SESSION_ID` still\nnames the holder. `VISSUE_AGENT` is\nthe tracker\'s own name for the same thing; `--as` names a persona over\nboth; a person at a terminal is their login user.\n";Expand description
The sitting protocol: which store answers which question, the order of
verbs before, during and after the work, and the refusals worth knowing.
ljos protocol prints it, ljos onboard installs it as a skill, and the
server serves it at ljos://protocol. Harness agnostic on purpose.