From afb75b9324649a9f5f6fb7b61d94e47bea453457 Mon Sep 17 00:00:00 2001 From: Abir Abbas Date: Sun, 27 Sep 2026 22:21:35 -0400 Subject: [PATCH 1/7] =?UTF-8?q?manual:=20a=20standing=20card's=20keys=20ar?= =?UTF-8?q?e=201,=203=20where=20offered,=200,=20esc=20later=20and=20o=20Ch?= =?UTF-8?q?ange=E2=80=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit standing-orders.md promised a `2` that changes when an order wakes and said `esc` declines. The card has no `2`; `3` (once) is offered on checks and watches only, `0` declines, `esc` leaves it for later, and `o Change…` (`o Change where…` on a rule) opens the box for a correction (#1545). Co-Authored-By: Claude Opus 5.5 (1M context) --- internal/manual/chat/standing-orders.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/internal/manual/chat/standing-orders.md b/internal/manual/chat/standing-orders.md index 63f175534..e40e8c0a3 100644 --- a/internal/manual/chat/standing-orders.md +++ b/internal/manual/chat/standing-orders.md @@ -31,8 +31,10 @@ codeaf recognises it and puts a card in the conversation; you answer the card, a stands. - **In a conversation** — say it. The card appears in the transcript with your own - sentence on it. `1` sets it up, `2` changes when it wakes, `3` does the thing once - and leaves nothing behind, and `0` or `esc` says no. + sentence on it. `1` sets it up; where offered, `3` approves doing it once + without a schedule. A rule that only holds has no once answer. `0` declines, + `esc` leaves the answer for later, and `o Change…` (`o Change where…` on a rule) + opens a box for different words, time or place. - **From the home screen** — the `ask here` box takes the same sentence, and the card is drawn beside it with the same answers. @@ -289,7 +291,9 @@ They go through the same deliberate door `ctrl+enter` opens, with the same guara standing order's card — when it wakes, what it does, how far it reaches — and it does not carry the sentence out as one-off work as well. - **Nothing stands until you answer the card.** What comes back is the ordinary - ratification card: `1` sets it up, `2` changes when it wakes, `0` or `esc` says no. + ratification card: `1` sets it up, `3` approves one unscheduled run where offered, + `0` declines, `esc` leaves it for later, and `o Change…` (`o Change where…` + on a rule) opens a box for a correction. A rule that only holds has no once answer. - **A sentence that cannot stand at all** — "what time is it?", a one-off command with no condition in it — gets one short line saying so, and nothing else happens. - **Typed while an answer is still arriving**, it waits above the box like any other From cf3e22dc88171677727f5d0ad8f25b161b8bbed5 Mon Sep 17 00:00:00 2001 From: Abir Abbas Date: Sun, 27 Sep 2026 22:21:35 -0400 Subject: [PATCH 2/7] manual: the Model Pool seats no crew, and the --host pages quote what ssh really does The pool index supplies only model-name aliases to crew routing, and own.json is read by `codeaf pool` alone. `pool verify` prints metric names, `pool status` has pending-judge and last-sweep lines. The missing-codeaf message is quoted as the code spells it, and the drop rehearsal's pkill pattern now spans ssh's -o options (#1545). Co-Authored-By: Claude Opus 5.5 (1M context) --- .../manual/chat/running-from-the-terminal.md | 44 ++++++++++++------- .../manual/chat/running-on-another-machine.md | 7 +-- 2 files changed, 31 insertions(+), 20 deletions(-) diff --git a/internal/manual/chat/running-from-the-terminal.md b/internal/manual/chat/running-from-the-terminal.md index 0b86918a0..24f8ae80a 100644 --- a/internal/manual/chat/running-from-the-terminal.md +++ b/internal/manual/chat/running-from-the-terminal.md @@ -755,8 +755,10 @@ No competence evidence yet. ## The Model Pool — what this machine reads from it, with codeaf pool -codeaf picks its models against the public Model Pool: a signed index of -measured models that your runs improve. Nothing about your code ever leaves +The public Model Pool is a signed index of measured models. It does not seat +the task crew: codeaf routes that crew from its built-in prior and this install's +task outcomes, and all that routing reads of the pool is the model-name aliases in +the copy built into the binary. Your runs can improve the shared measurements. Nothing about your code ever leaves the machine — what is shared is a measurement of the run, not the work. One setting answers for all of it, `model_pool` in `/settings`, with three values: `on` reads and sends, `read` uses the pool and sends nothing, `off` @@ -776,25 +778,31 @@ and the addresses in force with the word saying where each came from (`default`, `setting`, `env`, `ci`, or `telemetry` when the telemetry off switch capped sending), then what index is cached, how old it is and how many cells it holds, or `no index cached yet · built-in -seed of `. The binary carries a seed index of our own scored runs, -read until a fresher signed one is cached. `--cells` lists the held +seed of `. The binary carries a seed index of scored runs, shown until a fresher +signed one is cached. `--cells` lists the held index's cells, one per line — the role, the model, the dims the cell spells, the measurement and the installs behind it — and `--json --cells` carries them as an array. Your install also keeps the scores its judge gave in `own.json` -under the pool directory — `show` and `status` say what that sheet holds — and -the crew reads them beside the index. `status` adds how many rows are waiting to be sent -and whether the mode allows sending and reading; `codeaf telemetry show` prints the -rows themselves, as JSON. `codeaf pool status` also -says whether the relay answered, and whether the mirror did, and what the -last judge did — which model, which seats it scored, or why it failed. `--json` prints -the same answer as one object; `show` reads nothing off the network. +under the pool directory — `show` and `status` say what that sheet holds. +Only `codeaf pool` reads that sheet; it does not pick the next crew. + +## What codeaf pool status shows — waiting rows, pending judge, last sweep + +`codeaf pool status` reports how many outbox rows wait to be sent and whether the mode +allows sending and reading. Its `pending` line can also say `dropped N` and `identity set`; +it counts waiting rows but does not list them. `codeaf telemetry show` prints the rows +themselves as JSON. Status also says whether the relay and mirror answered, what the last +judge did, how many runs are `pending judge:`, and what happened in the `last sweep:`. +`--json` prints the same answer as one object; `show` reads nothing off the network. + +## What the own sheet stores — scores from this install **The scores start here.** In a conversation, after a task lands, a model outside the crew is asked to score each seat the work ran on — the worker that carried it, and the seat that checked it when there was one. The scores stay -in your install's own sheet (`own.json`) and are read when the next crew is chosen; -nothing else reads them. With `model_pool` set to `on` the same scores also +in your install's own sheet (`own.json`). `codeaf pool` reads this sheet for its display; +crew routing does not read it. With `model_pool` set to `on` the same scores also wait in `outbox.jsonl` beside the sheet, to leave with the pool's other measurements; `read` keeps them local, and `off` asks no judge at all and writes nothing. The call itself is billed to the `judge` seat, so it shows up @@ -810,11 +818,13 @@ index is fetched once a day, checked against the key built into the binary — or the key in `models.pool.public_key` when one is set — and a changed document is read at the next start. +## Verify the Model Pool signature — codeaf pool verify + `verify` fetches a fresh index and checks its detached ed25519 signature, -then prints the version whose signature checked out: +then prints the version, generated date and metric names. For example: ``` -signature good: version 7, generated 2026-09-10, 3 metrics +signature good: version 1790468332, generated 2026-09-27, metrics acceptable, role_quality ``` It wants a public key: `--key `, repeatable, or @@ -1012,8 +1022,8 @@ there, and `waiting`, the rows themselves, `[]` on the day you install; and `off `session_ended` also carries `total_tokens`, the one exact number on it: the input and output tokens the provider reported across the session, never which model or what it read. `CODEAF_TELEMETRY=off` — or `DO_NOT_TRACK=1`, or `codeaf telemetry off` — stops both: the -usage counts go quiet and the Model Pool is capped at `read`, so it still picks models -from the index and sends nothing. The pool's own switch, `model_pool` in `/settings` or +usage counts go quiet and the Model Pool is capped at `read`, so it can still fetch the index +and sends nothing. The pool's own switch, `model_pool` in `/settings` or `CODEAF_MODEL_POOL`, adds `off`, which asks no judge at all. It reads and sends nothing of its own — it is a command about the counts, not a session. The notice names the bargain before the first byte leaves. A chat shows it once, dim, diff --git a/internal/manual/chat/running-on-another-machine.md b/internal/manual/chat/running-on-another-machine.md index 95d06deb4..b8ae61e7a 100644 --- a/internal/manual/chat/running-on-another-machine.md +++ b/internal/manual/chat/running-on-another-machine.md @@ -100,7 +100,7 @@ a real machine. For that, use a machine you actually ssh to. terminal kill the ssh child this session started: ``` -pkill -f "ssh -T localhost codeaf engine" +pkill -f '[s]sh -T .* localhost codeaf engine' ``` The status line grows its `connection` segment, the surface redials itself, and the answer @@ -112,8 +112,9 @@ in a moment`, and pressing enter again once it is back sends it. The failed dial says what it found, rather than guessing: -- codeaf missing over there: - `codeaf is not installed on — install it there, or put it on the PATH that a non-login ssh command sees` +- codeaf missing over there: the message says the program is called codeaf now, + gives its former name and date, and asks you to install it under the current name: + `the program is called codeaf now (it was … before 2026-09-14) and must be installed on under that name — put it on the PATH that a non-login ssh command sees` - ssh could not get a session at all: `ssh could not open a session on `. ssh has already printed its own reason on the line above. - no ssh on this machine: `this machine has no ssh on its path, and --host is ssh`, or From 9ac9d6098d6ec04af9b49d9b3b6e03c87da26054 Mon Sep 17 00:00:00 2001 From: Abir Abbas Date: Sun, 27 Sep 2026 22:21:35 -0400 Subject: [PATCH 3/7] manual: the task proposal card as drawn, and the run road's own bounds MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The card's clock sits on its top edge beside `codeaf asks` and defaults to 15s; its foot is `esc later · o other · ? clarify`. The 3-level and 20-piece bounds belong to the node belt; the default bash belt splits with plandb split under 256 per batch, 1024 per run and four wakes (#1545). Co-Authored-By: Claude Opus 5.5 (1M context) --- internal/manual/chat/questions.md | 14 ++++---- internal/manual/chat/tasks.md | 59 ++++++++++++++++++++++++------- 2 files changed, 54 insertions(+), 19 deletions(-) diff --git a/internal/manual/chat/questions.md b/internal/manual/chat/questions.md index a1ef1f782..ba11f42c3 100644 --- a/internal/manual/chat/questions.md +++ b/internal/manual/chat/questions.md @@ -78,15 +78,17 @@ Most of them wait. A wait that ended is not a no: an approval question, a standing card and a page waiting to be approved carry no clock at all, and they stay up until somebody answers them. -**A task proposal and a reversible recommendation may carry a clock.** The answers -row says which answer is about to be taken and when — `start it in 9s` — and when +**A task proposal and a reversible recommendation may carry a clock.** The card's +top edge, beside who is asking, says which answer is about to be taken and when — +`start it in 15s` at the task proposal's default — and when the time runs out the work STARTS. It is your chance to correct it, not a gate the work waits on. Any key you press stops that clock, and a proposal you hold loses -its deadline and then waits like everything else, with `waiting` on the end of the -row instead of a countdown. +its deadline and then waits like everything else, showing `waiting` instead of a countdown. + +## What a question's clock says before it acts **A clock says what it is going to do, in that shape's own words.** Where there -is a recommended answer the tail is that answer — `start it in 9s`. Where there +is a recommended answer the clock names that answer — `start it in 9s`. Where there is not, the words depend on the shape: a proposal reads `starts on its own in 9s` because something begins when it runs out, and an assumptions card reads `goes on in 9s`, because nothing begins — the asker simply stops waiting for you @@ -744,7 +746,7 @@ Almost nothing does. A wait that ended is not a no, and nothing on the block answers in your place if you say nothing. There is exactly one thing that decides by itself: **a task proposal**, whose -card says which answer it is going to take and when — `start it in 9s`. That +card says which answer it is going to take and when — `start it in 15s` at the default. That card is your chance to redirect the work, not a gate the work waits on, and it starts on its own if nobody says otherwise. Nothing else on this surface acts without you, and nothing that cannot be taken back ever will. diff --git a/internal/manual/chat/tasks.md b/internal/manual/chat/tasks.md index 017c22a01..b88e28bef 100644 --- a/internal/manual/chat/tasks.md +++ b/internal/manual/chat/tasks.md @@ -340,8 +340,10 @@ your money to learn what it was going to be told anyway. If the pieces share wha learn, they are one quick task's items instead, and they stay in order. ## Can a quick task start more work — quick tasks inside quick tasks, and the two bounds -**Yes, under exactly the bounds every task is under.** A quick task's worker carries -`quick_task` and `propose_task` on the same terms as any other worker. +**Yes, on the node belt selected with `CODEAF_TASK_BELT=node`.** A quick task's worker carries `quick_task` and +`propose_task` on the same terms as another node worker. These bounds describe the +session task tree, including ordinary tasks on that belt. With the switch unset, +the bash worker harness is the default and the conversation has no quick task. **Depth is 3 levels.** The conversation starts work; that work may start more; what it started may start more once again; the level below that may not. A worker at the floor @@ -357,6 +359,12 @@ may.` and to do the rest in its own hands. And a quick task takes a slot like anything else: if you have set `task.parallel`, quick tasks queue behind it with everything else. +On the default bash belt, a task starts a run instead. Its workers have neither +`quick_task` nor `propose_task`; they split work with `plandb split`. The plan store +allows at most 256 tasks in one added batch and 1024 in one run; a composite worker +can wake at most four times to integrate its children. The tree's 3/20 bounds do not +describe that run road. + ## A quick task started inside a task — a quick row appeared under my task, and who reads its answer A quick task started by a task is a row of its own on the column, under what it is doing, @@ -551,18 +559,25 @@ block in the conversation shows: because it is the one fact nothing else on screen will say again; on a narrow frame the hint is dropped and the model kept. -**There is no row of answers on it and no meter.** Those were a decision drawn in a place +## What the task proposal asks above the message box + +**There is no row of answers on the transcript block and no meter.** Those were a decision drawn in a place no other decision on this screen is drawn. The question is above the box: ``` -? wants to start a task: Fix the nil-map crash +? wants to start a task: Fix the nil-map crash codeaf asks · start it in 15s The parser drops a key on an empty map. · codeaf - ▸ 1 start it + ▸ 1 start it ◆ recommended + it starts on its own unless you say otherwise · fairly sure 2 no - enter take it · esc later · c change · start it in 9s + any key stops the clock · you can still change the answer afterwards + esc later · o other · ? clarify ``` -`▸` marks the answer the clock is about to take. The question is **not modal**: the message +`▸` marks the answer the clock is about to take. The default clock is 15 seconds +(`task.autoapprove_seconds` changes it). `◆ recommended` marks the asker's pick; +the reason and confidence appear below it when supplied. The clock sits at the top +right, and the keys sit at the bottom edge. The question is **not modal**: the message box stays live, and what you type into it is the correction. Only one proposal is a live question at a time. If a second one arrives while the first is @@ -1387,7 +1402,8 @@ grammar every question on this screen takes: | `enter` | box has words | sends what you typed as a correction, and starts the corrected work | | `enter` | box empty | takes the answer marked `▸`, which is the one the clock would take | | `esc` | always | **later** — folds the question to the chip and answers nothing | -| `c` | box empty | answer in words: the same thing as typing and pressing `enter` | +| `o` | box empty | opens **something else…** for your own answer or correction | +| `?` | box empty | asks for clarification | | `ctrl+e` | box empty | opens or closes the brief in the conversation | **Bare letters are ordinary text.** The question is not modal: the moment there is anything @@ -1403,6 +1419,8 @@ moving hand is not answered by a keystroke aimed at your sentence. You can also click an answer: each answer's row is pressable along its whole width. +## Choosing a different model or opening the task proposal's brief + **Honest limit:** there is no longer any way to pick the model from the proposal. When a word matched more than one model the card used to offer them on a row of chips answered by `1`–`4`, and those digits are the question's answers now. The work runs on the closest @@ -1417,12 +1435,17 @@ Expanding the brief: `ctrl+e` with an empty box, or `ctrl+o` on a block you sele on its own labelled line. Clicking the block's body does not open the brief — it opens the task's room. -## The countdown on a task proposal — start it in 9s +## The countdown on a task proposal — start it in 15s by default -The clock is the last thing on the question's own answers row, and it says which answer is -about to be taken and when: `start it in 9s`. It is rounded up, so the last second you have +The clock sits at the top right of the card, beside `codeaf asks`, and says which answer is +about to be taken and when: `start it in 15s` at the default setting. It is rounded up, so the last second you have is drawn as a second; above a minute it reads `2m 13s`. +While it runs, the card says `any key stops the clock · you can still change the answer afterwards`. +Its bottom edge reads `esc later · o other · ? clarify`. + +## What happens when a task proposal clock stops + **The clock runs toward yes.** Silence approves the work as briefed, with no correction appended, and the block settles as `approved · the clock`. This is the opposite of the permission question's countdown, which never answers at all: a task proposal is not a @@ -1438,6 +1461,8 @@ quarter-second the card drops keys, because they were aimed at whatever was ther The dropped key still holds the clock and moves the pointer to `2 no`, so an `enter` straight after it declines; it never starts the task. After that, `1` starts and `2` declines at once. +## Changing the task proposal countdown + The default window is 15 seconds. **Where is the setting for how long a proposal waits?** It is `task.autoapprove_seconds`, and it lives on the **`Safety`** tab of the settings panel — open that with `ctrl+,` or `/settings` — where it is the row labelled `task countdown`. It @@ -4218,8 +4243,8 @@ which is why neither is in the settings panel. Two hard bounds, and they behave differently on purpose. -**Both bounds count quick tasks and ordinary ones together**, and `quick_task` is withheld -at the floor exactly as `propose_task` is. +**On the optional node belt, both bounds count quick tasks and ordinary ones together**, +and `quick_task` is withheld at the floor exactly as `propose_task` is. **Depth: 3 levels.** The conversation proposes a task; that task may propose pieces; a piece may propose pieces of its own share; a piece of a piece may not. Neither @@ -4247,6 +4272,14 @@ splits. `task.parallel` still applies to the whole session: pieces queue behind it exactly as top-level tasks do. +## How the bash belt run splits work instead of nesting node tasks + +With the switch unset, or `CODEAF_TASK_BELT=bash`, a task uses the run engine instead of the node tree. +Run workers have neither `quick_task` nor `propose_task`; they split with `plandb split`. +The plan store allows up to 256 tasks in one added batch and 1024 tasks in one run. +A composite worker can wake at most four times to integrate its children. The node +tree's 3/20 bounds do not apply to that run. + ## How many tasks run at once — can I have it do two things at the same time, can you work on several parts of my answer at once **There is no limit by default.** codeaf does not cap the number of tasks running at the From e72e576668e6e37bb1f41575e02a9a99ac3af2fc Mon Sep 17 00:00:00 2001 From: Abir Abbas Date: Sun, 27 Sep 2026 22:21:35 -0400 Subject: [PATCH 4/7] =?UTF-8?q?manual:=20team=5Fstart=20asks=20only=20unde?= =?UTF-8?q?r=20=E2=97=87=20asks,=20and=20a=20held=20row=20carries=20its=20?= =?UTF-8?q?whole=20reason?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Under the default ◇ YOLO a manager's team_start runs with no card. The switcher's manager row exists only while a team is shown. A held Traffic row says what was spent and what is waiting (#1545). Co-Authored-By: Claude Opus 5.5 (1M context) --- internal/manual/chat/team-manager.md | 29 ++++++++++++++----- .../manual/chat/team-questions-and-caps.md | 6 ++-- internal/manual/chat/teams-page.md | 2 +- 3 files changed, 26 insertions(+), 11 deletions(-) diff --git a/internal/manual/chat/team-manager.md b/internal/manual/chat/team-manager.md index d6fe3dd82..070cb4def 100644 --- a/internal/manual/chat/team-manager.md +++ b/internal/manual/chat/team-manager.md @@ -58,7 +58,9 @@ like a pinned browser tab so it never scrolls away: that one the manager. When the team already has one, the row says which one it replaces: `◆ Make this harbor's manager (replaces Shipping the parser)`. On the manager itself the row reads **`◇ Make an ordinary member`**, which turns it back into an ordinary conversation with - all its history. + all its history. When the chip reads `teams ▾` with All shown, choose a team and reopen the + chip: All has no manager or Remove row. After you make a manager, the menu stays open and + that row changes to `◇ Make an ordinary member`. Once there is a manager the place reads **`◆ Manager`**, and on the conversations view its tile comes first, titled `◆ Manager · `. Point at the tab to see the team and the title in @@ -147,9 +149,14 @@ the Traffic is the team's own and a manager set from the laptop is the one the f follows. Against a far machine running an older codeaf, `+ Manager` and the menus say managers are not available over `--host`, and the column has no Traffic word. -When the manager starts a member with `team_start`, you are asked first, on a card that reads -`◆ manager wants to start @lexer`, with the brief under it and the clause `a new conversation; -it spends until it stops`. When you allow it, this window opens the new conversation in the +## When a manager starts a member — team_start and approvals + +When the manager starts a member with `team_start`, the conversation's approval posture +applies. The default `◇ YOLO` lets it start without a card; `◇ asks` raises a permission +card headed `◆ manager wants to start @lexer`, with the brief under it and the clause +`a new conversation; it spends until it stops`. With a card, `1 allow once` permits this +start, `2 always` permits this tool for the session, `3 deny` refuses, and `esc` leaves it +for later. An allowed start opens the new conversation in the team's folder **behind** the one you are in, never in front of it: what you were typing stays where it was. Its tab arrives at the end of the team's run, named `@lexer` until it has a title, and its working mark is the only thing that moves. With the team's auto-wake on, the member @@ -222,13 +229,16 @@ on one waits for you. | `team_read` | the end of one member's conversation, bounded; the member is not told | no | | `team_send` | a message to one member, to several (one message, every handle in `to`), or to everyone, as a note (information, which waits) or a directive (an instruction, which starts an idle member) | no | | `team_stop` | ends one member's current turn, the way your own Stop does, whether a window has it open or codeaf opened it in the background: nothing is deleted, and its background tasks and jobs keep running | no | -| `team_start` | a new member conversation with a handle and a brief; it opens in the team's folder and is handed the brief, marked as the manager's, on its first request. With kind `team` it starts a sub-team instead (see **Sub-teams**) | yes | +| `team_start` | a new member conversation with a handle and a brief; it opens in the team's folder and is handed the brief, marked as the manager's, on its first request. With kind `team` it starts a sub-team instead (see **Sub-teams**) | under `◇ asks` | | `team_decide` | answers a decision packet waiting on the manager, most often a member's question: an option, or its own words | no | | `team_escalate` | sends a packet waiting on the manager up, to its own manager or to you, with the reason it is not the manager's to decide | no | | `team_close_report` | brings you the team's closing report (done, left, where the files are) after you asked it to wrap up | no | | `team_raise` | raises a conflict to the manager above every party (see **Conflicts between members and teams**); members have it too | no | -`team_start` asks because a new conversation spends money for as long as it runs, and it is +## Why team_start may ask before it starts + +`team_start` follows the conversation's approval posture because a new conversation can +spend money; the default `◇ YOLO` allows it, while `◇ asks` raises the card. It is refused while the team is at its daily cap. The others act only inside the team you made, and every one of them is logged in the team's traffic. Questions, packets, caps and wrapping up are on the page **Team questions, decisions and caps**. @@ -265,8 +275,9 @@ move wakes it by itself, and a move that was refused writes no line. A manager can start a **sub-team**: `team_start` with kind `team`, a name for the new team, a handle and a brief for its manager, and optionally members of its own team to move into it. You -are asked first, on the same card as any start, which then reads `a new team "backend" under -yours`. When you allow it: +are asked first under `◇ asks`, on the same permission card as a member start, which then +reads `a new team "backend" under yours, managed by it.` The default `◇ YOLO` starts it +without that card. When allowed: - the new team is made under the manager's team, with its share of the pool: the parent's daily cap times `sub-team share` (`/settings`, **Teams**; 50% by default), written on the new team. @@ -282,6 +293,8 @@ It is refused, with the reason, past the team depth (`team depth` in `/settings` **Teams**, three levels by default, a team's own override first), under a closed team, at the team's daily cap, or when the name or the handle is taken. +## Sub-team orders and reports + **Orders go one level down, reports one level up.** A manager directs its own team's members, and a sub-team's manager is one of them; it never directs a sub-team's members. A `team_send` directive or a `team_stop` naming one is refused with a sentence that names the sub-team's diff --git a/internal/manual/chat/team-questions-and-caps.md b/internal/manual/chat/team-questions-and-caps.md index 49344d01c..5a10f052f 100644 --- a/internal/manual/chat/team-questions-and-caps.md +++ b/internal/manual/chat/team-questions-and-caps.md @@ -70,8 +70,10 @@ When the pool reaches its cap: - your own messages in a member's conversation are never held; the cap is on the work the team starts by itself. -A manager can never raise a cap: money is yours. Every held wake is one line in the traffic, -`held @web: harbor reached its $5 cap today`. +A manager can never raise a cap: money is yours. Every held wake is one Traffic row. +Its reason includes the spending and what is waiting, for example +`held @web: harbor reached its $5 cap today (spent $5.02); the person has been asked whether to raise it, and nothing new starts until they answer`. +After **Stop for today**, it ends `and the person chose to stop it for today` instead. ## Can a team cap be less than a cent diff --git a/internal/manual/chat/teams-page.md b/internal/manual/chat/teams-page.md index abc9d45a0..b07100f0b 100644 --- a/internal/manual/chat/teams-page.md +++ b/internal/manual/chat/teams-page.md @@ -292,7 +292,7 @@ cursor is on. A cap is dollars a day (0 for none), a depth is 1 to 10 levels, a 100 percent. The name is edited as you type and kept with `enter` or when the card is put away; `←` `→` choose a colour. `esc` or `Done` puts the card away. -## Closing a team +## Closing a team — will closing a sub-team stop its manager if also in the parent team `Close…`, `c`, `Close team…` on the card, or `D` on the conversations view closes a team. From 50c436decae57907cd7bface03d77398ba79edb4 Mon Sep 17 00:00:00 2001 From: Abir Abbas Date: Sun, 27 Sep 2026 22:21:35 -0400 Subject: [PATCH 5/7] manual: first run with a key found, the setup header, the landed card's badge and eight commands MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A key already in the profile or environment opens plain codeaf on home with no setup. The header reads `setting up · 1 of 2` under the wordmark. The landed card wears no program badge. The command table gains /drafts, /stop, /autonomy, /workspace, /effort and /senior-dev (#1545). Co-Authored-By: Claude Opus 5.5 (1M context) --- internal/manual/chat/commands.md | 44 +++++++++++++++++++++++++ internal/manual/chat/delegates.md | 5 ++- internal/manual/chat/getting-started.md | 20 ++++++++--- 3 files changed, 63 insertions(+), 6 deletions(-) diff --git a/internal/manual/chat/commands.md b/internal/manual/chat/commands.md index 9830bad72..3d1f08271 100644 --- a/internal/manual/chat/commands.md +++ b/internal/manual/chat/commands.md @@ -159,11 +159,19 @@ Canonical word, the other words it answers to, its argument form, and what it do | `/settings` | `/set`, `/config` | — | opens the fullscreen settings panel (also ctrl+,) | | `/connect` | `/connections` | — | opens the connection panel; its `models` group holds model services, followed by connected accounts | | `/new` | `/clear`, `/clean`, `/reset` | — | closes this session and starts a fresh one | +| `/drafts` | — | — | lists cleared drafts, newest first; enter restores one to the box and `d` lets one go; an empty ring says `no cleared draft is waiting` | | `/resume` | `/sessions` | — | opens the earlier-conversations picker | | `/compact` | — | — | summarizes the conversation now | + +## Home, project and file context commands — what does /workspace path do + +| Command | Aliases | Argument | Effect | +|---|---|---|---| | `/home` | — | — | every project and conversation on this machine, fullscreen | | `/folder` | `/place`, `/dir` | — | locally opens the add context sheet for THIS conversation; on home it opens a conversation first; over `--host` says the folder chooser is unavailable | | `/folder` | `/place`, `/dir` | `` | locally opens it with that in the box; over `--host` gives the same refusal | +| `/workspace` | — | — | opens a local folder picker to anchor a conversation with no workspace; says `this conversation already has a workspace` once anchored, and the picker is unavailable over `--host` | +| `/workspace` | — | `` | anchors an unanchored conversation to that project; refuses a path it cannot use, or a conversation that already has a workspace | | `/project` | — | — | on home: the browser, opened where the next conversation would open; in a conversation it says it is home's | | `/project` | — | `` | on home: sets the folder the next conversation opens in, with no browser | | `/attach` | `/upload` | — | opens the add context sheet for files, including over `--host`; enter on this row of the `/` list opens it at once | @@ -171,20 +179,38 @@ Canonical word, the other words it answers to, its argument form, and what it do | `/land` | — | — | says what has been changed for a folder you chose and is waiting to go into it | | `/land` | — | `now` | …puts it in: a branch merged for a repository, files copied back for a plain folder | | `/land` | — | `` | …when more than one folder is waiting; `/land now` puts that one in | + +## Rewind, approvals and standing commands + +| Command | Aliases | Argument | Effect | +|---|---|---|---| | `/rewind` | `/undo`, `/back` | — | opens the rewind timeline — the whole conversation as a list (esc esc is the quick inline version) | | `/permissions` | `/perms` | — | lists what runs without asking; `d` drops a line | +| `/autonomy` | — | — | prints this project's rules for questions while you are away; refuses when the conversation has no project to keep them in | +| `/autonomy` | — | ` ` | changes one project question rule; refuses an unknown kind or rule, a bad duration, and changes to confirmation or clarification that their limits forbid | | `/standing` | `/orders` | `` | makes those words a standing order — a card to answer, never work done once | | `/standing` | `/orders` | — | what stands over this conversation; `p` pauses, `s` stops, `n` excepts this place | + +## Programs, skills and memory commands + +| Command | Aliases | Argument | Effect | +|---|---|---|---| | `/harness` | `/harnesses` | — | lists the saved shapes of work and what they did | | `/subharness` | `/sub` | — | lists the programs you can run; type to filter, enter opens that one's card | | `/subharness` | `/sub` | `` | opens that subharness's intake card straight away | | `/` | — | `` | one row per program this build carries: starts a task that program does on its own | +| `/senior-dev` | — | `` | when this build or far engine carries senior-dev, its named row hands the whole task to that program; with no brief, it shows the required `` usage | | `/skill` | `/skills` | — | opens the skill shelf under the message box; enter toggles a skill, and its chip stays attached across messages | | `/memory` | — | — | opens the memory panel | | `/memory` | `/memories` | `` | prints matching memories into the conversation | | `/memories` | — | — | prints every memory into the conversation | | `/remember` | — | `` | keeps one thing across conversations | | `/forget` | — | `` | forgets the best matching memory | + +## Crew and task commands + +| Command | Aliases | Argument | Effect | +|---|---|---|---| | `/crew` | — | — | opens the crew panel: the three seats, the allowed models, the providers, the per-task limit and the daily cap, changed in place | | `/crew` | — | `pin ` | pins the worker, planner or checker to a model; `/model` stays | | `/crew` | — | `unpin ` | puts a seat back on auto | @@ -196,8 +222,14 @@ Canonical word, the other words it answers to, its argument form, and what it do | `/task` | — | `solo ` | starts one worker at once, with no reading of its width | | `/task` | — | `--best ` | starts the task on the strongest crew the allowed models make, this task only | | `/task` | — | `--cheap ` | starts the task on the cheapest crew that does the work, this task only | +| `/stop` | — | — | asks before stopping the open task or selected work; with no target says `open a running task to stop it` | | `/redo` | — | `stronger` | runs the last task again on a stronger crew, and teaches the crew that kind of work needs more | | `/history` | — | — | opens the full-screen sessions place — every task this machine has run, filterable (also ctrl+.) | + +## Status, search, teams and spending commands + +| Command | Aliases | Argument | Effect | +|---|---|---|---| | `/status` | `/info`, `/context` | — | prints every fact the status line knows, one per line | | `/status` | `/info`, `/context` | `--json` | prints the same facts as one JSON object, keys in the same order | | `/search` | none | none | opens the search place, everything said on this machine (also `alt+9`) | @@ -205,9 +237,16 @@ Canonical word, the other words it answers to, its argument form, and what it do | `/wall` | | | every open conversation at once, as a grid of live tiles, and the teams you group them into (also `alt+v`, or `▦` under the box) | | `/teams` | | | the teams page: your teams as a tree, what waits on you, and the selected team's manager conversation (also `alt+2`, or `teams` on the tab bar) | | `/cost` | `/usage`, `/tokens` | — | prints what this conversation has spent, and on what | +| `/effort` | `/think`, `/thinking` | — | opens this conversation's thinking levels; says it is unavailable when the session has no dial | +| `/effort` | `/think`, `/thinking` | `` | sets this conversation's thinking level; an unknown rung lists the accepted levels and changes nothing | | `/budget` | `/limits` | — | what codeaf may spend · every limit on one tab | | `/budget` | `/limits` | `` | sets the day's limit · `none` removes it | | `/budget` | `/limits` | ` ` | sets one by name: `day`, `conversation`, `plan`, `practice` | + +## Cache, display and export commands + +| Command | Aliases | Argument | Effect | +|---|---|---|---| | `/cache` | — | — | how big the shared build cache is, and where | | `/cache` | — | `clean` | asks first, then deletes the cache to free disk — confirm with `/cache clean now` | | `/debug` | — | — | keeps the full record of **this conversation** from here on, and says which folder it goes to | @@ -219,6 +258,11 @@ Canonical word, the other words it answers to, its argument form, and what it do | `/export` | `/save` | `` | …and writes it there; tab completes the path | | `/files` | — | — | lists what has been made for you; opens, reveals or copies one — over `--host` it opens the browse page for that machine | | `/files` | — | `` | over `--host`, brings that one file back and opens it here | + +## Help and leaving commands + +| Command | Aliases | Argument | Effect | +|---|---|---|---| | `/help` | `/?` | — | prints this list | | `/manual` | — | — | asks the model what codeaf can do, answered from codeaf's own manual | | `/manual` | — | `` | puts that question to the model, answered from codeaf's own manual, naming the page | diff --git a/internal/manual/chat/delegates.md b/internal/manual/chat/delegates.md index b5b671f9d..ddabd08ce 100644 --- a/internal/manual/chat/delegates.md +++ b/internal/manual/chat/delegates.md @@ -24,10 +24,13 @@ task's, shows the actions the program took, each under the step of its own proce program asks for, the run's own work model answers, and the raw calls name the model that did. +## Where a program's badge appears — and where it does not + **Every program's tasks wear its name as a badge**: `[]` after the task's title on -the side list, the card, the task's page, the `@` list, the tasks place and home, and its +the side list, the proposal card, the task's page, the `@` list, the tasks place and home, and its initials (`[sd]` for senior-dev) where a list is narrow. A task codeaf's own worker does wears none, and a program added to codeaf later gets its own badge from its name. +The landed card's head shows the title and outcome without a program badge. This is different from a harness or a subharness, which are built out of codeaf's own parts. A program codeaf carries has an engine of its own. diff --git a/internal/manual/chat/getting-started.md b/internal/manual/chat/getting-started.md index 7f3fddba5..4e1269885 100644 --- a/internal/manual/chat/getting-started.md +++ b/internal/manual/chat/getting-started.md @@ -12,19 +12,29 @@ terminal* page, under *How do I install or update codeaf*. ## Getting started — first time setup, what happens the first time I run codeaf -The first time `codeaf` opens on a profile with nothing in it, the chat does not open on -an empty prompt and a provider error. It opens in the chat itself, on **two screens** — -under a minute, nothing else on the frame: +The first time `codeaf` opens a new local conversation on a profile with nothing in it, +setup appears in the chat instead of an empty prompt and a provider error. When the +default provider needs a key and no daily limit is configured, it has **two screens** — under a minute, +nothing else on the frame: 1. **connect openrouter** — the default service; `enter` signs in in your browser, and pasting an existing key also works 2. **Models and spending** — one screen with two controls on it, **Daily limit** and **Chat model**, each already showing the value that is in force +**With a key already found, there is no setup screen.** When a provider key is saved in +the profile or set in the environment, such as `OPENROUTER_API_KEY`, a plain launch opens +straight on home: no connection screen and no **Models and spending**. `/budget` sets a +daily limit later. A `--no-host` launch on such a profile skips only the connection screen, +and still opens **Models and spending** while no daily limit is set. A resumed conversation, +or one on another machine, never opens first-run setup. + The second screen's way out is **`Start a conversation`**. Every control on it opens on the value you already have, so pressing `enter` there agrees to exactly what is on the screen. Its heading is `Models and spending` and the line under it is `Keep these choices or change them.` +## Skipping setup and reading its header + `esc` on the first screen skips the setup: the flow is marked seen and it does not open again. `esc` on the controls screen goes **back** to the connection when there is one behind it, and skips when the controls are the whole of the setup. A skip leaves one dim @@ -39,8 +49,8 @@ Codex is deliberately not another first-run step. After setup, its browser sign- available from the Codex row in `/connect`, or from `codeaf connect codex` without opening the chat. -The header reads `codeaf` on the left and `setup · 2 of 2` on the right; with only one -screen to show there is no count at all. The foot names the keys that work on the row you +The header reads `codeaf`, with `setting up · 1 of 2` under the wordmark on the first of two +steps. With only one step it reads `setting up`, without a count. The foot names the keys that work on the row you are standing on — `tab` walks the rows, `?` opens a control's detail — and on a narrow window it is cut by whole clauses rather than mid-word. From eaca0cc2e29e373bd2713b900ec3956574e55229 Mon Sep 17 00:00:00 2001 From: Abir Abbas Date: Sun, 27 Sep 2026 22:21:35 -0400 Subject: [PATCH 6/7] manual: probes for the sections #1545 rewrote Two of them (/drafts and /workspace ) reached no command row on dev. Co-Authored-By: Claude Opus 5.5 (1M context) --- internal/manual/chat_test.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/internal/manual/chat_test.go b/internal/manual/chat_test.go index 2718d4a4b..5a6f57a7b 100644 --- a/internal/manual/chat_test.go +++ b/internal/manual/chat_test.go @@ -3020,6 +3020,14 @@ func TestTheChatManualAnswersTheQuestionsPeopleAsk(t *testing.T) { {"which engine process is holding my folder", "staying-on-that-machine"}, {"the other window will not let go of my conversation", "home"}, {"does max-hours close the window when the time runs out", "starting-codeaf"}, + {"does the Model Pool choose my task models", "running-from-the-terminal"}, + {"what does codeaf pool status show", "running-from-the-terminal"}, + {"how many tasks can a bash run split into", "tasks"}, + {"what does the task proposal card look like", "tasks"}, + {"why did team_start not ask me first", "team-manager"}, + {"why did setup show only one screen", "getting-started"}, + {"where are my cleared drafts", "commands"}, + {"what does /workspace path do", "commands"}, } for _, ask := range asked { found := Chat().Search(ask.question, DefaultResults) From b34b07f6f535ae8a6d1f79f8fc84c13bbb2f1ec1 Mon Sep 17 00:00:00 2001 From: Abir Abbas Date: Sun, 27 Sep 2026 22:27:36 -0400 Subject: [PATCH 7/7] =?UTF-8?q?changes:=20#1639's=20entry=20=E2=80=94=20wh?= =?UTF-8?q?at=20the=20manual=20used=20to=20say=20about=20standing=20cards,?= =?UTF-8?q?=20the=20pool,=20task=20cards,=20team=20starts=20and=20first=20?= =?UTF-8?q?run?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5.5 (1M context) --- docs/changes/unreleased/1639-manual-truth.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 docs/changes/unreleased/1639-manual-truth.md diff --git a/docs/changes/unreleased/1639-manual-truth.md b/docs/changes/unreleased/1639-manual-truth.md new file mode 100644 index 000000000..b9bb742ad --- /dev/null +++ b/docs/changes/unreleased/1639-manual-truth.md @@ -0,0 +1,20 @@ +--- +kind: fixed +title: the manual's standing, pool, task-card, team-start and first-run pages say what the code does +pr: 1639 +surface: [chat, docs] +invalidates: + - "The manual said a standing card's `2` changes when it wakes and `esc` says no. The card has no `2`: `1` sets it up, `3` (once) is offered on checks and watches only, `0` declines, `esc` leaves it for later, and `o Change…` (`o Change where…` on a rule) corrects it." + - "The manual said codeaf picks its crew against the public Model Pool and that the crew reads `own.json`. Crew routing uses its own prior and this install's outcomes and reads only the model-name aliases in the index copy built into the binary; only `codeaf pool` reads `own.json`." + - "The manual said `codeaf pool verify` prints a metric count (`3 metrics`). It prints the metric names: `signature good: version , generated , metrics `." + - "The manual drew the task proposal's clock as `start it in 9s` on its answers row with the foot `enter take it · esc later · c change`. The clock is on the top edge beside `codeaf asks`, defaults to 15s, and the foot is `esc later · o other · ? clarify`; `c` is not a key on that card." + - "The manual said every task is bounded at 3 levels and 20 pieces per parent. Those bounds belong to the node belt (`CODEAF_TASK_BELT=node`); the default bash belt splits with `plandb split` under 256 tasks per batch, 1024 per run and four wakes per composite." + - "The manual said a manager's `team_start` always asks first on a card. It follows the conversation's approval posture: the default `◇ YOLO` starts the member with no card, and only `◇ asks` raises one." + - "The manual said the first run on an empty profile always opens two setup screens under a `setup · 2 of 2` header. With a provider key already in the profile or the environment, plain codeaf opens on home with no setup, and the header reads `setting up · 1 of 2` under the wordmark." + - "The manual said a program's `[]` badge is on the landed card. Only the proposal card and the task's rows wear it; the landed card's head does not." +--- + +Three of the issue's rows are code defects rather than page errors and are left for their own +issues: plain codeaf's engine road never draws `· N standing orders here — /standing`, the +`remember` and `stand` tools both claim a stated preference, and the standing card never shows +the grant.