A new job: triage → open a case → pick the carrier
Speak in the user's language, and write the case file / board / inbox rows in the user's language. Status words and section letters are fixed bilingual, so a case written in either language must be readable by every skill here. Header-line fields: status (状态) / pen-holder (持笔) / updated (更新). Status words used here: in discussion (讨论中) / queued (排队) / to dispatch (待派) / running (在跑) / awaiting acceptance (待验收) / awaiting decision (候拍) / awaiting takeover (候接手) / delivered (已交货) / done (已完) / closed (已收口). Section letters A~I never change; the section names are bilingual and given in §2.
0. The case library (fix the project root first, then the library)
Project root = the repository root the current working directory sits in (the git root if there is a .git, otherwise cwd). The case library is only ever looked for inside the project root, and it is resolved in this order: the path on the line ctx-kit case library: <path relative to the project root> in the project root's CLAUDE.md if there is one, otherwise an existing _ops/CASES/, otherwise cases/ (create it if absent). Every skill here resolves it the same way, so a project that keeps its cases somewhere else says so once, in that one line, instead of being told the path session by session. The board = TASKBOARD.md inside the case library (create it if absent: the header is three zones — product top-level goal + milestone table + routine table — followed by the case index and the one-off area; the board is maintained by hand, so touch your own row and leave the rest alone).
Hard rule: a case file must never be written into a different project — read the target absolute path back to the user before writing. Measured, and it went wrong once: a session in a throwaway project wrote three personal-admin files into the main project's case library, numbered them off the main project's sequence, and rode along into the main project's git.
Case number = <prefix>-NN: the prefix is per project (the main project keeps its existing letter; another project takes the initials of the project name, and only has to avoid clashing with an existing prefix), and NN increments independently inside this project's case library, never looking at another project's numbers.
1. Triage (decide it yourself, do not ask the user)
| Signal |
Route |
| Part of a case already on the books — same problem area, and one plan would settle both |
Merge into that case, do not open a second one: the case you hold the pen on takes it in section D (something to decide) or as an E row (status queued); any other case takes it as one appended row in its inbox (§4 ④), never as an edit to their body text. Either way, name the case you merged it into |
| Needs discussion, needs several rounds of experiment, needs a ruling |
Open a case (step 2) |
| Executable in one pass, criteria are clear |
One-off: no case; one row on the board (the milestone tag is required, see below), plus a self-contained task brief |
| A quick fix (change a setting, change one line, answer a question) |
Just do it, no case and no task brief |
Look for it on the books before you open anything — and not only on the board. The same job may already be an E row in somebody's ledger, or already sitting in somebody's inbox waiting to be dealt with, and neither shows up in the case index. Fill in the two keywords first; one command over the whole library then answers all three:
D=$(sed -n 's/^[^A-Za-z]*ctx-kit case library:[[:space:]]*//p' CLAUDE.md 2>/dev/null | head -1 | sed 's/[`[:space:]]*$//')
[ -n "$D" ] || { D=_ops/CASES; [ -d "$D" ] || D=cases; }
grep -n -i -e "<a keyword from the job>" -e "<the other way people word it>" "$D"/*.md | head -40
Read each hit by where it landed: in TASKBOARD.md it is already a case or a one-off on the board; in a case's E table somebody has already hung it up as an experiment; in a case's §I inbox somebody has already sent it in and it is waiting on that case. A hit in a case you do not hold the pen on goes into that case's inbox as one appended row (§4 ④), never into a second case of its own — the inbox is the one route into a case you do not hold, and a row that turns out to be a duplicate costs one line to drop, while a duplicate case splits the books and costs far more to merge back. Say in the triage line which row you found and where you put it. Only when the search comes back with nothing is this a job of its own.
The test for merging: would the two be settled by one plan and written by one pen? Yes → merge. Merging takes nobody's pen: your own case takes the row directly, and anybody else's takes it through their inbox, which is the one route into a case you do not hold. Measured once: a job tightly coupled to an open case was triaged into a second case of its own, and the coupling had to be carried as a to-do between the two from then on. When it really is a job of its own, when in doubt open a case: opening one costs about two minutes, whereas the cost of not opening one is state rotting inside the session.
Opening a case or a one-off owes one question first — ask it out loud: which step of the top-level goal does this push, and is that milestone already on the board? Read the milestone table in the board header and answer in one of two ways: it matches a row → put that milestone's number in the tag cell (the case index's Milestone column, or the one-off's row); it matches none → write candidate milestone: <one line> in that cell and tell the owner in the triage line, because a job that matches nothing usually means the plan is a step short — and sometimes means the job should not be done. Do not invent a milestone row of your own and do not leave the cell empty; the tag is what ctx-status groups by, and an untagged job is a job nobody can place. A milestone is only a tag: tagging one asks nobody's approval and changes nobody's pen.
Every route owes one line of triage result — decide and move on, but leave a hatch for correction: opening a case returns the three-line summary from step 2; a merge returns "this belongs inside case , because ; I have put it at — its section D / an E row / its inbox; say so if that is wrong"; a one-off returns "I triaged this as a one-off, because ; it is on the board at row N, pushing milestone (or candidate milestone: …); say so if that is wrong"; a quick fix returns "I triaged this as a quick fix, because ; doing it now; say so if that is wrong". Silently dispatching as a quick fix something that deserved a case leaves the user no chance to stop it.
2. Open the case (create the file on the spot, do not ask first and create later)
Section heading format — ## A Goal: a capital letter, one space, then the section name (## A Goal (目标), ## E Experiment ledger (实验台账)). Do not put a period after the letter (## A. Goal), do not renumber and do not rename the letters — every skill here locates a section by that letter alone, so the letter is the only part of the heading that is load-bearing.
- Header line:
status: in discussion pen-holder: (TBD) stint: 01 updated: <today> (中文 状态: 讨论中 持笔: (TBD) 任期: 01 更新: <今日>). stint (任期) is the stint number this case is on, and it is where a title gets its number from (§3): the session opening the case is 01, and every takeover after it adds 1 to what stands there, so nobody has to ask the session list.
- A Goal (目标): write the five SMART elements (specific / measurable / achievable / relevant / time-bound) down hard, from your current understanding of the context, wording them as "my reading"; do not leave it blank for the user to fill in. Write relevance as two sentences: which product top-level goal it serves, tagged in the fixed form
milestone: M? (the number from the board's milestone table, or candidate milestone: <one line> when it matches none) + where this case stands on that milestone right now.
- B Current plan snapshot (当前方案快照): if you have an idea, describe the end state; if not, write "to be discussed".
- C Decisions (已拍决策): empty. D Open items & pending decisions (未决与候拍): hang up whatever you judge the user has to decide, each with a recommendation.
- E Experiment ledger (实验台账): hang up the experiments you can already foresee (status = queued). F Chronicle (编年志), G Archive pointers (档案指针; reference only), H Unsaved items (未落盘清单): create them empty (use exactly these section names, do not invent your own; I Inbox (收件位) is optional — it is this case's own address, so create it as soon as another case may need to reach it).
- The headers of tables D / E / I are fixed — copy them character for character, all of them in one language and never mixed: every skill here finds a column by its header text, so a renamed or dropped column reads downstream as a missing column. Measured: one small case built by feel twice came out with a six-column ledger and an eight-column one.
- D:
| # | Open item / decision needed | Note / recommendation | (中文 | # | 待办/待拍 | 说明 / 建议 |)
- E:
| ID | Question it answers | Task brief path | Carrier | Status | Delivery path | Verdict | Impact on plan | (中文 | ID | 要回答的问题 | 任务书路径 | 载体 | 状态 | 交货路径 | 判定 | 对方案的影响 |)
- I:
| Date | From | Message | Disposition | (中文 | 日期 | 来自 | 来话 | 处置 |)
- The Status cell of E takes one of six words and nothing else:
queued (排队) hung up, not started / to dispatch (待派) being given a carrier / running (在跑) a session is on it / awaiting acceptance (待验收) it has reported and nobody has accepted it yet / delivered (已交货) accepted, the deliverable is on disk / done (已完) finished with nothing to deliver. A takeover reads the first four as live and the last two as finished, matching on the word alone, so a date or a note after it (已交货(09-05)) is fine — but a word from outside the six is read as neither, and that row goes missing from every takeover. How it turned out belongs in the Verdict cell, never here: passed, partly achieved, stopped, handed to another case are all verdicts, and all four have been measured sitting in a Status cell, one of them on a row that was still waiting on the owner.
- E is an index, not a report: the pre-registered criteria (reading before / expected reading / what counts as a fail) live in the task brief that the Task-brief-path cell points at, not in a column of E; with no brief written yet, that cell says
to be written.
- An existing library whose older cases are shaped differently: use the fixed headers for the case you are opening, leave the older cases alone (they belong to whoever holds their pen), and say so in one line, so the difference is on the record instead of a surprise for the next reader.
- D holds open items only: a decision once made moves into C and its D row goes with it; an item once done has its row deleted (leave a line in F if it is worth remembering). Do not strike rows through — every row standing in D is open, and that is exactly what
ctx-status reports to the owner as awaiting decision.
- The Disposition cell of I decides whether a message is still waiting on somebody: empty = not disposed; disposed = the cell is non-empty and opens with
done (已办) / dropped (不办) / moved to <where> (已转 <去处>) — worded any other way it counts as not disposed, however finished the work behind it actually is. So write every disposition starting with one of those three: nothing reads the rest of the cell, and a row worded otherwise sits in every successor's slice for good.
- Register it on the board (the case is not open until this row exists): append one row to the 「Cases on the books」 (在册案) table of
<case library>/TASKBOARD.md. The row has seven columns, in this order — case number / name / milestone / status / pen-holder / where it is / next step — e.g. | C-07 | async vs streaming (short name: billing) | M2 | in discussion | (TBD) | just opened, goal written | user to correct A and D |. Fix the case's short name here and never again: two to four characters, one word in English, written into the Name cell as (short name: X) (中文 〔短名:X〕); every session on this case reuses it in its own title (§3), which is the only thing that makes a sidebar full of sessions readable. When you edit an existing row, split it on unescaped pipes only: a \| inside a cell is content, not a separator, so never cut the line at every | you see — measured once, and it lost a column and tore a \| in half. A freshly built board carries a (None yet. Open the first one with ctx-kickoff.) line under that table — delete that line when you add the first row. Touch your own row and nothing else: not the board header, not anybody else's row. A case that is not on the board is invisible to ctx-status, and its session shows up as an orphan in the retirement sweep at checkup.
Once it is built, reply with a three-line summary: the goal in one sentence / the key open item as you judge it in one sentence / the case file path. Ask the user to correct you — what the user changes is A and D, not the format.
3. Ask one question
Discuss it here, or dispatch it?
Ask nothing else (do not ask whether to open a case, do not ask about naming, do not ask about priority).
Branch A: discuss it here
set_session_title to C<NN>-<SS> <case short name>-<what this stint does>[-exec] (e.g. C07-03 billing-async-vs-streaming-decision; 中文 C07-03 计费-异步还是流式的决策): C<NN> = the case number with its hyphen taken out (C-07→C07); <SS> = the stint number, read off the case header line's stint (任期) field and nowhere else — a case you have just opened is 01, and every takeover after it adds 1 to what stands there (ctx-takeover §3). Never call list_sessions for a number: the project-wide counter this replaces cost 11,000–17,000 characters of session list every time somebody took a case over, and had collided twice anyway. Both parts are written two digits wide (C04-07); a project numbering past 99 simply runs wider. The case short name is the one fixed when the case was opened (§2) — off the board's Name cell, never coined twice — so one glance says both which case and which case that is, and a one-off has neither case number nor short name and is titled C00-<nn> instead, <nn> being the number of its row in the board's one-offs table — the same row number the triage reply quoted back; the last segment says what this stint is doing, not the case name — the number and the short name already stand for the case, and one case spans several stints that are not doing the same thing; the role suffix is left off by default — only a dispatched execution session writes -exec (the session you are talking to needs no label saying so); no project prefix by default, add a short one only on a genuine cross-project collision (ck-C07-03 billing-…); after retirement close-out adds the ✕ prefix. Old titles are never renamed — this form applies from here on, and a session already running under the older NN-C07short-… form keeps the name it has. If what this stint is mainly doing genuinely changes, rename it: set the new title, then write that same name into the case header line's pen-holder cell and into the Pen-holder cell of that case's row on the board, so the three never disagree. If the tool is unavailable, skip this and say so;
- put that name in the header line's "pen-holder"; if the title tool was unavailable, write the role and the reason instead —
lead (title tool unavailable), or exec (title tool unavailable) — and never write a title you did not actually set: whoever comes next checks the pen-holder against the live session list, and an invented name reads there as a live pen-holder nobody can find;
- start talking, and hold to this: write section C the moment a decision is made, rewrite section B the moment the plan changes — do not wait for close-out.
Branch B: dispatch it
Write a self-contained task brief (the case's A in one sentence + the relevant paragraphs of B copied in + pre-registered criteria: reading before / expected reading / what counts as a fail + the delivery path), put it on disk and hang it on an E row (status = queued). Then give the user an opening prompt they can copy straight across:
Read <task brief path> — read only that, and never read any old session transcript.
First action on starting: set_session_title to "C<NN>-<SS>.<child index> <case short name>-<what this stint does>-exec" (e.g. `C07-03.1 billing-load-test-batch-exec`, where `C07-03` is the dispatching session's own case-and-stint number; a one-off is `C00-<nn>.<child index>`, `<nn>` being its row number in the board's one-offs table, and carries no short name; the child index increments inside the dispatcher — take the largest `.x` it has already handed out and add 1; if the board already names the dispatch, use that name). **Second action on starting: write that name back into the 「carrier」 cell of that job's row on the board (one-off row) or the carrier column of the case's E row** — fill in only your own cell. Leave it out and the board cannot tell whose you are; you appear in the register as an "orphan", and the retirement sweep at checkup may mark you dead while you are still working (one measured near-miss, survived only because that session happened to be warm).
**A dispatched session always uses the dispatcher's own number plus a child index, never a fresh number of its own** — only the dispatcher hands out its child numbers, so a collision is structurally impossible; the old "global max + 1" collides whenever two leads dispatch at the same time (it has collided twice in practice).
And change your row in the E table of <case file path> to status "running".
Execute against the pre-registered criteria in the task brief, writing to disk as you go; report a fail as a fail, do not dress it up.
Delivery = a machine-readable ledger + a summary for people, written into <delivery path> as both layers;
write back the E row (Status = awaiting acceptance / Delivery path / Verdict / one sentence in Impact on plan) — **the Verdict cell and the Impact-on-plan cell are each ≤200 characters**; E is an index, not a report, and detail belongs only in the results section of the deliverable. Stop when done, do not open a new topic.
Once dispatched, do not wait (anything over 15 minutes goes async). Do not dispatch a subagent from here once this session is expensive (past the yellow line — 400k by default) — the cold tax of waiting = this session's watermark × 2.
4. Park a to-do (the other entry point)
Trigger: the user says "note this down", "save this for later", "save this task", "come back to it"; or you raised a to-do yourself and the user said "save it".
Do not open a case, do not start work, do not chase priority — decide where it belongs first, then write it down, and there are only these four landing spots:
| What the to-do is |
Where it lands |
| ① A to-do belonging to the case you hold the pen on (something to decide, something to think through) |
one row added to that case's section D, with one sentence of your recommendation |
| ② Belongs to the current case, and is something to execute |
an E row of that case, status = queued, task brief path = to be written |
| ③ A standalone small job outside this case |
a one-off row on the board (the milestone tag is required — the milestone it pushes, or candidate milestone: <one line> plus a word to the owner; §1) |
| ④ Belongs to another case |
that case's inbox (section I), append only, never touch their body text; leave the Disposition cell empty — an empty disposition is what marks the row as still waiting on them. Escape every pipe inside your message as |: an unescaped one splits the row into the wrong number of cells, and a takeover reads that row as malformed |
If you cannot tell where it belongs, ask one question (this is the only follow-up allowed); do not stuff it somewhere yourself.
Once it has landed, reply with one line saying where it went: file path + which section / which row number (e.g. _ops/CASES/C-07_xx.md:42 (section D)). Replying "noted" is not writing it down — if the user cannot find it later, it was never noted.
1---2name: ctx-kickoff3description: Triage and open a case — use on "I want to do X", "plan this", "start a new job", "note this down", "save this for later", or /ctx-kickoff; routes to case / one-off / quick-fix, creates the case file on the spot, parks to-dos where they belong, then asks one question — discuss here or dispatch. Also triggers on Chinese — 用户说"我要做 X""帮我规划 X""开个新活""这事怎么搞",说"记一下""先存着""保存这个任务""回头再做"要存待办,或显式 /ctx-kickoff 时用。4---56# A new job: triage → open a case → pick the carrier78> **Speak in the user's language, and write the case file / board / inbox rows in the user's language.** Status words and section letters are fixed bilingual, so a case written in either language must be readable by every skill here. Header-line fields: `status` (状态) / `pen-holder` (持笔) / `updated` (更新). Status words used here: **in discussion** (讨论中) / **queued** (排队) / **to dispatch** (待派) / **running** (在跑) / **awaiting acceptance** (待验收) / **awaiting decision** (候拍) / **awaiting takeover** (候接手) / **delivered** (已交货) / **done** (已完) / **closed** (已收口). Section letters A~I never change; the section names are bilingual and given in §2.910## 0. The case library (fix the project root first, then the library)11**Project root** = the repository root the current working directory sits in (the git root if there is a `.git`, otherwise cwd). **The case library is only ever looked for inside the project root**, and it is **resolved in this order: the path on the line `ctx-kit case library: <path relative to the project root>` in the project root's `CLAUDE.md` if there is one, otherwise an existing `_ops/CASES/`, otherwise `cases/`** (create it if absent). Every skill here resolves it the same way, so a project that keeps its cases somewhere else says so once, in that one line, instead of being told the path session by session. The board = `TASKBOARD.md` inside the case library (create it if absent: the header is three zones — product top-level goal + milestone table + routine table — followed by the case index and the one-off area; **the board is maintained by hand**, so touch your own row and leave the rest alone).1213**Hard rule: a case file must never be written into a different project** — read the target **absolute path** back to the user before writing. Measured, and it went wrong once: a session in a throwaway project wrote three personal-admin files into the main project's case library, numbered them off the main project's sequence, and rode along into the main project's git.1415**Case number = `<prefix>-NN`**: the prefix is per project (the main project keeps its existing letter; another project takes the initials of the project name, and only has to avoid clashing with an existing prefix), and **NN increments independently inside this project's case library, never looking at another project's numbers**.1617## 1. Triage (decide it yourself, do not ask the user)18| Signal | Route |19|---|---|20| Part of a case already on the books — same problem area, and one plan would settle both | **Merge into that case**, do not open a second one: the case **you** hold the pen on takes it in section D (something to decide) or as an E row (status `queued`); **any other case takes it as one appended row in its inbox** (§4 ④), never as an edit to their body text. Either way, name the case you merged it into |21| Needs discussion, needs several rounds of experiment, needs a ruling | **Open a case** (step 2) |22| Executable in one pass, criteria are clear | **One-off**: no case; one row on the board (**the milestone tag is required**, see below), plus a self-contained task brief |23| A quick fix (change a setting, change one line, answer a question) | **Just do it**, no case and no task brief |2425**Look for it on the books before you open anything — and not only on the board.** The same job may already be an E row in somebody's ledger, or already sitting in somebody's inbox waiting to be dealt with, and neither shows up in the case index. Fill in the two keywords first; one command over the whole library then answers all three:2627```bash28D=$(sed -n 's/^[^A-Za-z]*ctx-kit case library:[[:space:]]*//p' CLAUDE.md 2>/dev/null | head -1 | sed 's/[`[:space:]]*$//')29[ -n "$D" ] || { D=_ops/CASES; [ -d "$D" ] || D=cases; }30grep -n -i -e "<a keyword from the job>" -e "<the other way people word it>" "$D"/*.md | head -4031```3233Read each hit by where it landed: in `TASKBOARD.md` it is already a case or a one-off on the board; in a case's **E** table somebody has already hung it up as an experiment; in a case's **§I** inbox somebody has already sent it in and it is waiting on that case. **A hit in a case you do not hold the pen on goes into that case's inbox as one appended row (§4 ④), never into a second case of its own** — the inbox is the one route into a case you do not hold, and a row that turns out to be a duplicate costs one line to drop, while a duplicate case splits the books and costs far more to merge back. Say in the triage line which row you found and where you put it. Only when the search comes back with nothing is this a job of its own.3435The test for merging: would the two be settled by one plan and written by one pen? Yes → merge. Merging takes nobody's pen: your own case takes the row directly, and anybody else's takes it through their inbox, which is the one route into a case you do not hold. Measured once: a job tightly coupled to an open case was triaged into a second case of its own, and the coupling had to be carried as a to-do between the two from then on. When it really is a job of its own, when in doubt open a case: opening one costs about two minutes, whereas the cost of not opening one is state rotting inside the session.3637**Opening a case or a one-off owes one question first — ask it out loud**: *which step of the top-level goal does this push, and is that milestone already on the board?* Read the milestone table in the board header and answer in one of two ways: it matches a row → **put that milestone's number in the tag cell** (the case index's `Milestone` column, or the one-off's row); it matches none → write **`candidate milestone: <one line>`** in that cell and **tell the owner in the triage line**, because a job that matches nothing usually means the plan is a step short — and sometimes means the job should not be done. Do not invent a milestone row of your own and do not leave the cell empty; the tag is what `ctx-status` groups by, and an untagged job is a job nobody can place. A milestone is only a tag: tagging one asks nobody's approval and changes nobody's pen.3839**Every route owes one line of triage result** — decide and move on, but leave a hatch for correction: opening a case returns the three-line summary from step 2; a **merge** returns "this belongs inside case <number> <short name>, because <one sentence>; I have put it at <path> — its section D / an E row / its inbox; say so if that is wrong"; a **one-off** returns "I triaged this as a one-off, because <one sentence>; it is on the board at row N, pushing milestone <X> (or `candidate milestone: …`); say so if that is wrong"; a **quick fix** returns "I triaged this as a quick fix, because <one sentence>; doing it now; say so if that is wrong". Silently dispatching as a quick fix something that deserved a case leaves the user no chance to stop it.4041## 2. Open the case (create the file on the spot, do not ask first and create later)42**Section heading format — `## A Goal`**: a capital letter, one space, then the section name (`## A Goal (目标)`, `## E Experiment ledger (实验台账)`). **Do not put a period after the letter** (`## A. Goal`), do not renumber and do not rename the letters — every skill here locates a section by that letter alone, so the letter is the only part of the heading that is load-bearing.43- Header line: `status: in discussion pen-holder: (TBD) stint: 01 updated: <today>` (中文 `状态: 讨论中 持笔: (TBD) 任期: 01 更新: <今日>`). **`stint` (任期) is the stint number this case is on**, and it is where a title gets its number from (§3): the session opening the case is `01`, and every takeover after it adds 1 to what stands there, so nobody has to ask the session list.44- **A Goal (目标)**: write the five SMART elements (specific / measurable / achievable / relevant / time-bound) down hard, from your current understanding of the context, wording them as "my reading"; **do not leave it blank for the user to fill in**. Write relevance as two sentences: which product top-level goal it serves, **tagged in the fixed form `milestone: M?`** (the number from the board's milestone table, or `candidate milestone: <one line>` when it matches none) + where this case stands on that milestone right now.45- **B Current plan snapshot (当前方案快照)**: if you have an idea, describe the end state; if not, write "to be discussed".46- **C Decisions (已拍决策)**: empty. **D Open items & pending decisions (未决与候拍)**: hang up whatever you judge the user has to decide, each with a recommendation.47- **E Experiment ledger (实验台账)**: hang up the experiments you can already foresee (status = queued). **F Chronicle (编年志), G Archive pointers (档案指针; reference only), H Unsaved items (未落盘清单)**: create them empty (use exactly these section names, do not invent your own; **I Inbox (收件位)** is optional — it is this case's own address, so create it as soon as another case may need to reach it).48- **The headers of tables D / E / I are fixed — copy them character for character**, all of them in one language and never mixed: every skill here finds a column by its header text, so a renamed or dropped column reads downstream as a missing column. Measured: one small case built by feel twice came out with a six-column ledger and an eight-column one.49 - **D**: `| # | Open item / decision needed | Note / recommendation |` (中文 `| # | 待办/待拍 | 说明 / 建议 |`)50 - **E**: `| ID | Question it answers | Task brief path | Carrier | Status | Delivery path | Verdict | Impact on plan |` (中文 `| ID | 要回答的问题 | 任务书路径 | 载体 | 状态 | 交货路径 | 判定 | 对方案的影响 |`)51 - **I**: `| Date | From | Message | Disposition |` (中文 `| 日期 | 来自 | 来话 | 处置 |`)52 - **The Status cell of E takes one of six words and nothing else**: `queued` (排队) hung up, not started / `to dispatch` (待派) being given a carrier / `running` (在跑) a session is on it / `awaiting acceptance` (待验收) it has reported and nobody has accepted it yet / `delivered` (已交货) accepted, the deliverable is on disk / `done` (已完) finished with nothing to deliver. A takeover reads the first four as live and the last two as finished, matching on the word alone, so a date or a note after it (`已交货(09-05)`) is fine — but **a word from outside the six is read as neither, and that row goes missing from every takeover**. **How it turned out belongs in the Verdict cell, never here**: `passed`, `partly achieved`, `stopped`, `handed to another case` are all verdicts, and all four have been measured sitting in a Status cell, one of them on a row that was still waiting on the owner.53 - **E is an index, not a report**: the pre-registered criteria (reading before / expected reading / what counts as a fail) live in the task brief that the Task-brief-path cell points at, **not** in a column of E; with no brief written yet, that cell says `to be written`.54 - **An existing library whose older cases are shaped differently**: use the fixed headers for the case you are opening, **leave the older cases alone** (they belong to whoever holds their pen), and say so in one line, so the difference is on the record instead of a surprise for the next reader.55 - **D holds open items only**: a decision once made moves into C and its D row goes with it; an item once done has its row deleted (leave a line in F if it is worth remembering). **Do not strike rows through** — every row standing in D is open, and that is exactly what `ctx-status` reports to the owner as awaiting decision.56 - **The Disposition cell of I** decides whether a message is still waiting on somebody: empty = not disposed; **disposed** = the cell is non-empty **and opens with** `done` (已办) / `dropped` (不办) / `moved to <where>` (已转 <去处>) — worded any other way it counts as not disposed, however finished the work behind it actually is. So **write every disposition starting with one of those three**: nothing reads the rest of the cell, and a row worded otherwise sits in every successor's slice for good.57- **Register it on the board (the case is not open until this row exists)**: append one row to the 「Cases on the books」 (在册案) table of `<case library>/TASKBOARD.md`. **The row has seven columns, in this order** — case number / name / milestone / status / pen-holder / where it is / next step — e.g. `| C-07 | async vs streaming (short name: billing) | M2 | in discussion | (TBD) | just opened, goal written | user to correct A and D |`. **Fix the case's short name here and never again**: two to four characters, one word in English, written into the Name cell as `(short name: X)` (中文 `〔短名:X〕`); every session on this case reuses it in its own title (§3), which is the only thing that makes a sidebar full of sessions readable. **When you edit an existing row, split it on unescaped pipes only**: a `\|` inside a cell is content, not a separator, so never cut the line at every `|` you see — measured once, and it lost a column and tore a `\|` in half. A freshly built board carries a `(None yet. Open the first one with ctx-kickoff.)` line under that table — delete that line when you add the first row. **Touch your own row and nothing else**: not the board header, not anybody else's row. A case that is not on the board is invisible to `ctx-status`, and its session shows up as an orphan in the retirement sweep at checkup.5859Once it is built, reply with a **three-line summary**: the goal in one sentence / the key open item as you judge it in one sentence / the case file path. Ask the user to correct you — what the user changes is A and D, not the format.6061## 3. Ask one question62> **Discuss it here, or dispatch it?**6364Ask nothing else (do not ask whether to open a case, do not ask about naming, do not ask about priority).6566### Branch A: discuss it here671. `set_session_title` to `C<NN>-<SS> <case short name>-<what this stint does>[-exec]` (e.g. `C07-03 billing-async-vs-streaming-decision`; 中文 `C07-03 计费-异步还是流式的决策`): **`C<NN>`** = the case number with its hyphen taken out (`C-07`→`C07`); **`<SS>`** = the stint number, **read off the case header line's `stint` (任期) field and nowhere else** — a case you have just opened is `01`, and every takeover after it adds 1 to what stands there (`ctx-takeover` §3). **Never call `list_sessions` for a number**: the project-wide counter this replaces cost 11,000–17,000 characters of session list every time somebody took a case over, and had collided twice anyway. Both parts are written two digits wide (`C04-07`); a project numbering past 99 simply runs wider. The **case short name** is the one fixed when the case was opened (§2) — off the board's Name cell, never coined twice — so one glance says both which case and *which case that is*, and **a one-off has neither case number nor short name and is titled `C00-<nn>` instead**, `<nn>` being the number of its row in the board's one-offs table — the same row number the triage reply quoted back; **the last segment says what this stint is doing, not the case name** — the number and the short name already stand for the case, and one case spans several stints that are not doing the same thing; **the role suffix is left off by default — only a dispatched execution session writes `-exec`** (the session you are talking to needs no label saying so); **no project prefix by default**, add a short one only on a genuine cross-project collision (`ck-C07-03 billing-…`); after retirement close-out adds the `✕ ` prefix. **Old titles are never renamed** — this form applies from here on, and a session already running under the older `NN-C07short-…` form keeps the name it has. **If what this stint is mainly doing genuinely changes, rename it**: set the new title, then write that same name into the case header line's pen-holder cell and into the Pen-holder cell of that case's row on the board, so the three never disagree. If the tool is unavailable, skip this and say so;682. put that name in the header line's "pen-holder"; **if the title tool was unavailable**, write the role and the reason instead — `lead (title tool unavailable)`, or `exec (title tool unavailable)` — and **never write a title you did not actually set**: whoever comes next checks the pen-holder against the live session list, and an invented name reads there as a live pen-holder nobody can find;693. start talking, and hold to this: **write section C the moment a decision is made, rewrite section B the moment the plan changes** — do not wait for close-out.7071### Branch B: dispatch it72Write a self-contained task brief (the case's A in one sentence + the relevant paragraphs of B **copied in** + pre-registered criteria: reading before / expected reading / what counts as a fail + the delivery path), put it on disk and hang it on an E row (status = queued). Then give the user an opening prompt they can copy straight across:7374```75Read <task brief path> — read only that, and never read any old session transcript.76First action on starting: set_session_title to "C<NN>-<SS>.<child index> <case short name>-<what this stint does>-exec" (e.g. `C07-03.1 billing-load-test-batch-exec`, where `C07-03` is the dispatching session's own case-and-stint number; a one-off is `C00-<nn>.<child index>`, `<nn>` being its row number in the board's one-offs table, and carries no short name; the child index increments inside the dispatcher — take the largest `.x` it has already handed out and add 1; if the board already names the dispatch, use that name). **Second action on starting: write that name back into the 「carrier」 cell of that job's row on the board (one-off row) or the carrier column of the case's E row** — fill in only your own cell. Leave it out and the board cannot tell whose you are; you appear in the register as an "orphan", and the retirement sweep at checkup may mark you dead while you are still working (one measured near-miss, survived only because that session happened to be warm).77**A dispatched session always uses the dispatcher's own number plus a child index, never a fresh number of its own** — only the dispatcher hands out its child numbers, so a collision is structurally impossible; the old "global max + 1" collides whenever two leads dispatch at the same time (it has collided twice in practice).78And change your row in the E table of <case file path> to status "running".79Execute against the pre-registered criteria in the task brief, writing to disk as you go; report a fail as a fail, do not dress it up.80Delivery = a machine-readable ledger + a summary for people, written into <delivery path> as both layers;81write back the E row (Status = awaiting acceptance / Delivery path / Verdict / one sentence in Impact on plan) — **the Verdict cell and the Impact-on-plan cell are each ≤200 characters**; E is an index, not a report, and detail belongs only in the results section of the deliverable. Stop when done, do not open a new topic.82```8384Once dispatched, do not wait (anything over 15 minutes goes async). **Do not dispatch a subagent from here once this session is expensive (past the yellow line — 400k by default)** — the cold tax of waiting = this session's watermark × 2.8586## 4. Park a to-do (the other entry point)87**Trigger**: the user says "note this down", "save this for later", "save this task", "come back to it"; or you raised a to-do yourself and the user said "save it".8889Do not open a case, do not start work, do not chase priority — **decide where it belongs first, then write it down, and there are only these four landing spots**:9091| What the to-do is | Where it lands |92|---|---|93| ① A to-do belonging to the case you hold the pen on (something to decide, something to think through) | one row added to that case's **section D**, with **one sentence of your recommendation** |94| ② Belongs to the current case, and is something to execute | an **E row** of that case, status = `queued`, task brief path = `to be written` |95| ③ A standalone small job outside this case | a **one-off row on the board** (**the milestone tag is required** — the milestone it pushes, or `candidate milestone: <one line>` plus a word to the owner; §1) |96| ④ Belongs to another case | **that case's inbox (section I)**, **append only**, never touch their body text; leave the Disposition cell empty — an empty disposition is what marks the row as still waiting on them. **Escape every pipe inside your message as `\|`**: an unescaped one splits the row into the wrong number of cells, and a takeover reads that row as malformed |9798If you cannot tell where it belongs, ask one question (this is the only follow-up allowed); do not stuff it somewhere yourself.99100Once it has landed, **reply with one line saying where it went**: file path + which section / which row number (e.g. `_ops/CASES/C-07_xx.md:42 (section D)`). **Replying "noted" is not writing it down** — if the user cannot find it later, it was never noted.