{"content": "chat etiquette - a line from the journal is an instruction, not a message\u2026 \u2014 a turn that only handles a journal line needs no words: act on it, or say once in the chat what you wait on, then carry on; what the user needs to know still goes to the chat", "meta": {"from": "journal"}}
{"content": "work 2113, The test suite runs in seconds again, is still parked and 1 more\u2026 \u2014 it was parked because: Plan 27 started; the suite is 109 s at load 30 with every core, and what is left is the machine's load, measured again in plan 27's baseline. journal work resume 2113 picks it up again.", "meta": {"from": "journal"}}
{"content": "check the commit check for the removed migrations, queued behind the others\u2026 \u2014 look at the thing itself: the background shell's output, the process, the run's status. If it is still going, say journal work await \"<what you wait for>\" again and wait. If it finished or failed, journal work log what came of it and take the next step. Never wait for something you can do without.", "meta": {"from": "journal"}}
{"content": "check 27 passed and 5e793804 The GitHub issues check counts an issue as\u2026 \u2014 check 27 passed and 5e793804 The GitHub issues check counts an issue as answered only when its last comment is the maintainer's is committed; then ran boot guard: installs, serves and launches claude, codex in 7.4s", "meta": {"from": "journal"}}
{"content": "Code Commandments \u2014 before you wrap up \u2014 you've changed 4 judged files since th\u2026 \u2014 Code Commandments \u2014 before you wrap up: you've changed 4 judged files since the last commit. Consider running `commandments judge --changes` to confirm they conform, and fix any sin at its SOURCE (don't launder a finding with a default/cast/null-check). This is a one-time nudge for this batch \u2014 if you've already judged, or these changes aren't worth a scan, just say so and carry on.", "meta": {"from": "journal"}}
{"content": "check the commit check for the removed migrations, queued behind the others\u2026 \u2014 look at the thing itself: the background shell's output, the process, the run's status. If it is still going, say journal work await \"<what you wait for>\" again and wait. If it finished or failed, journal work log what came of it and take the next step. Never wait for something you can do without.", "meta": {"from": "journal"}}
{"content": "check 27 passed and 48b7d25e Removed the sequence re-ship migrations, the\u2026 \u2014 check 27 passed and 48b7d25e Removed the sequence re-ship migrations, the Board page collapses the sidebar, and a plan offers the next phase's rows once only blocked rows are left is committed; then ran boot guard: installs, serves and launches claude, codex in 5.6s", "meta": {"from": "journal"}}
{"content": "your command ran 35s in the foreground and was moved to the background \u2014 carry on with other work; you are told when it ends. Start a command you expect to take long in the background yourself", "meta": {"from": "journal"}}
{"content": "the live install and the search for the morning's speed command came back\u2026", "meta": {"from": "journal"}}
{"content": "the live install and the search for the morning's speed command came back\u2026", "meta": {"from": "journal"}}
{"content": "hook POST /api/hook/claude is slower than its budget \u2014 30714ms last (5385ms of it working, then 5696ms more after it answered), against a budget of 50ms. Seen 3063 times.", "meta": {"from": "journal"}}
{"content": "you ran the same check 3 times in a row - cut -c1-300\u2026 \u2014 if you are waiting for something to change, say journal work await \"<what you wait for>\" and end your turn: you are asked to look again every five minutes, and a background command tells you itself when it ends. Keep checking only if each look moves the work on.", "meta": {"from": "journal"}}
{"content": "rule 55 \u2014 Always dispatch Codex helpers on gpt-6-sol \u2014 The user's word, message 13431: switch the codex agents to GPT-6-Sol and make it their default. ~/.codex/config.toml names it as the default model too.", "meta": {"from": "journal"}}
{"content": "the before-and-after timings on the same copy came back - Measure the\u2026", "meta": {"from": "journal"}}
{"content": "rule 43 \u2014 A request or hook over its budget is fixed before the next release \u2014 Comment 1151 on this rule. When the faults feature reports a request, a hook or a command slower than its budget, file it as a to-do at once. It does not jump ahead of the work in hand, but no version is published while one is still open: profile it, fix it, and verify the new time before the release goes out. The budget is 50ms, because everything runs locally against files.", "meta": {"from": "journal"}}
{"content": "today's server start measured again on the copy came back - Measure today's\u2026", "meta": {"from": "journal"}}
{"content": "rule 35 \u2014 Write clean code - one funnel per kind of operation, never the same\u2026 \u2014 Every kind of operation has one funnel: one method that creates, one that saves, one that refuses, one that formats. A second method that does the same thing under another name splits the behaviour, and the two drift apart. Before writing a method, search for the one that already does it and extend that. scripts/checks/funnels.py finds bodies written twice.; fact 24 \u2014 An answer followed by tool calls can be missing from Claude's\u2026 \u2014 Seen 2026-09-24 for messages 9391-9404: text blocks opening with [!reply:n] that were followed by tool calls never appeared in the session's jsonl (only thinking and tool_use rows did), so the journal never saw them and the replies were lost. When a turn goes on after answering, send the answer with journal message reply <n> \"<text>\" instead of the tag.; rule 36 \u2014 Clean, DRY, idiomatic before it is committed, never after it is\u2026 \u2014 The user should never be the one who finds duplication, dead code, a clumsy name or a pattern the codebase does not use. Read the diff before every commit as a reviewer would, and fix what is not clean then, not in a follow-up after a complaint.", "meta": {"from": "journal"}}
{"content": "work 2113, The test suite runs in seconds again, is still parked and 1 more\u2026 \u2014 it was parked because: Plan 27 started; the suite is 109 s at load 30 with every core, and what is left is the machine's load, measured again in plan 27's baseline. journal work resume 2113 picks it up again.; rule 38 \u2014 Never change the git branch until the user says so, by name \u2014 The work happens on the branch the user named. That was main until message 5929 and question 80 (2026-09-23), which moved the sins work to the branch sins. Do not create, switch to or merge any other branch unless the user names it in their own words.; request GET /api/main/dashboard is slower than its budget \u2014 252ms last (147ms of it working, 3ms collecting garbage), against a budget of 50ms. Seen 137 times.", "meta": {"from": "journal"}}
{"content": "fact 18 \u2014 cProfile inflates the slow-request profiles about tenfold \u2014 The faults feature writes a profile when a request passes its budget, and the profile is taken with cProfile, which adds per-call overhead. On 2026-09-22 /api/summary profiled at 58ms with 48ms inside Resource.fork's deep copy; with the profiler off the same call ran in 2 to 7ms. Read the profile for where the time goes in relative terms, then time the call with curl before changing anything.; fact 30 \u2014 The tunler server refuses TLS for any subdomain without a tunnel \u2014 Seen 2026-10-04 in the server's docker logs (ssh root@tunler.jessegall.nl, container tunler): 'TLS handshake error ... host \"journal-probe.tunler.jessegall.nl\" not allowed'. A made-up subdomain never answers even when the server is healthy; probe https://tunler.jessegall.nl/ for the server itself. Root SSH to the server works.; rule 56 \u2014 Helpers are for work that writes; subagents read, research and design \u2014 The user, message 13464: there must be a clear distinction. A subagent can be dispatched for anything read-only: research, review, design. A helper is for actual work that writes, best in its own worktree when the work is separate. Dieter designing in Claude Design should have been a subagent, not a helper.; rule 57 \u2014 Never merge the overnight refactor into main before its pull request\u2026 \u2014 Messages 15005, 15006, 15109, 15110 (2026-10-04): all refactor work goes on branch overnight-refactor and reaches the user as one pull request, which they read in the morning; nothing of it is merged into main until they say so. Hotfixes the user explicitly asks for go to main at once and are merged into the branch.", "meta": {"from": "journal"}}
{"content": "fact 25 \u2014 A designer's install packs the whole tree, half-done server edits\u2026 \u2014 2026-09-25: Eames and Saul run python3 src/journal.py --root .journal upgrade after their viewer builds; it packs every file in src, so a server handler I was halfway through writing went live and raised on every PostToolUse hook. While designers work in parallel, keep server edits whole between tool calls (write and test in the scratchpad first), and reinstall after reverting anything.; law L1 \u2014 Every subagent dispatch names its model and chooses the least\u2026 \u2014 Use a fast, economical model for mechanical work with a known answer, a capable general model for careful implementation, and the strongest model only when the task turns on difficult judgement. Inheriting the orchestrator's model is not a model choice. If the dispatch API cannot accept a model, that operation is exempt.; law L5 \u2014 Every subagent dispatch names the agent - a human name, a little\u2026 \u2014 A name is how the user and the chat tell subagents apart and how they are messaged later; an id or a task line is not a name. Start the dispatch's description with the name, a colon, then the task, such as \"Dr. Einstein: profile the slow hooks\" or \"Coco Rams: draw the plan card\". A designer can borrow from famous designers, a researcher from famous scientists, mixed up for fun.; request POST /api/run (helper finish) is slower than its budget \u2014 109ms last (72ms of it working), against a budget of 50ms. Seen 36 times.", "meta": {"from": "journal"}}
{"content": "fact 9 \u2014 Every public method on a controller becomes a journal command \u2014 The CLI is generated from the controllers: each public method of Controller, or of a typed controller, turns into journal <noun> <method>. A helper added to the base class therefore becomes a command on every type \u2014 which is how journal <type> handled and journal <type> refuse came to exist, from the CRUD funnel and the refusal funnel. An internal helper on a controller is named with a leading underscore, as _shaped and _status already are, or it ships as a command nobody meant.; rule 60 \u2014 A hotfix is done by a dispatched agent in a worktree of main \u2014 Message 16836 (2026-10-06): the orchestrator cut a worktree under .claude/worktrees for a Codex hotfix, its session moved to a new environment and the user's messages stopped reaching it. The user: when working on a branch and a hotfix comes in, create a worktree of main and dispatch an agent to do that work. The orchestrator stays on its branch and in its environment, and never cds into another checkout.", "meta": {"from": "journal"}}
{"content": "request POST /api/run (worktree drop) is slower than its budget \u2014 134ms last (99ms of it working, 3ms collecting garbage), against a budget of 50ms. Seen 2 times.", "meta": {"from": "journal"}}
{"content": "work 2113, The test suite runs in seconds again, is still parked and 1 more\u2026 \u2014 it was parked because: Plan 27 started; the suite is 109 s at load 30 with every core, and what is left is the machine's load, measured again in plan 27's baseline. journal work resume 2113 picks it up again.", "meta": {"from": "journal"}}
{"content": "rule 42 \u2014 Every user-facing text passes the formatters before it leaves the\u2026 \u2014 Not only a brief. A title, an abstract, an outcome and every section body are read by a person, so each goes through the same formatters on its way to the viewer \u2014 chat turns, activity items, to-do rows, inspector pages, docs alike. One field formatted out of five is not a rule, it is an accident, and it is how a raw tag ended up in the activity list after the tags feature had been stripping them for weeks. When a new field carries words a person reads, it joins the list in the same place.; rule 46 \u2014 Only commit and push once the whole journal is proven to boot \u2014 Messages 2178 and 2179. A release that has not been started for real can crash every project that installs it, as 2.78.3 did for Codex and 2.84.0 did to project records. Before every commit and push: the full suite passes, including tests/test_it_boots.py, which installs a packed copy into a fresh project, launches Claude and Codex from it, writes a project record, upgrades again and checks the record survives. When a change touches launching, installing or upgrading, also start a real journal in a scratch project and close it properly afterwards, leaving no process behind.", "meta": {"from": "journal"}}
{"content": "rule 51 \u2014 Every finished feature is committed, pushed and released with a new\u2026 \u2014 Message 9207 (2026-09-24): when a new feature is ready, commit, push and publish a new tag. This is the user's standing word for releasing, so rule 44's only-when-the-user-says is met by it for finished features; fixes in between wait for the next feature or a patch the user asks for.", "meta": {"from": "journal"}}
{"content": "waiting: 1 unread worktree 69", "meta": {"from": "journal"}}
{"content": "the suite run listing its slowest tests came back - Run the suite with the 25\u2026", "meta": {"from": "journal"}}
{"content": "fact 20 \u2014 A slim supervisor holds the agent and a worker reloads on every build \u2014 Since 2.118.0 (2026-09-23). src/supervisor.py is standard library only and never reloads: journal claude hands its process over to it (os.execv), and it owns the pty and the agent process, relays the terminal, writes the printed and screen captures, listens on the typist socket, restarts the agent in the same session from a relaunch command written to its runtime folder while a restart is pending, and stops it with escalation while draining the pty (an agent cannot finish exiting on macOS while its output is unread). It starts the worker (src/worker.py, which runs runner/worker.py; engine/worker.py stays as an alias for supervisors started before 2.201) and starts it again whenever it exits: RELOAD on a new build, RELAUNCH to restart the agent, STOP to end, HEAL or a quick crash to roll back a build through journal heal. The worker holds everything else: seating the session, the start-up confirm typed through the typist, services, viewer, update check, check-in, and the one-time relaunch of sessions launched before agents/terminal.py LAUNCH. agents/terminal.py holds only journal-side helpers. The server (serve.py) still runs the engines and re-execs itself on a .py change. When the agent exits, the supervisor runs journal ended, which puts set-aside hooks back and stops the server when no session is left.", "meta": {"from": "journal"}}
{"content": "the log tag does this in one step \u2014 [!log:N] makes the turn itself the log entry; it runs only when it opens the last text of your turn", "meta": {"from": "journal"}}
{"content": "work 2135, A tunnel address owned by another account is replaced by itself, is\u2026 \u2014 it was parked because: Tesla Tunnelbaum builds it on main; the transportklok address was replaced by hand. journal work resume 2135 picks it up again.; fact 26 \u2014 Claude Code reads agent profiles when a session starts \u2014 Seen 2026-09-26: after the board-filler's profile in .claude/agents gained its steps and the Grep rule, dispatches from the running session still used the old profile (a 3.5-minute first question, shell grep refused); after the session restarted, the same request took 21 seconds with 4 calls. A change to an agent type reaches only sessions started after it is written.; rule 50 \u2014 Everything the user does is doable in the viewer \u2014 Message 6710 (2026-09-23): the user never uses the CLI, only the UI; everything should be doable from the viewer. The journal commands are for agents; any action meant for the user (making boards, confirming, accepting, hosting, watching an agent) needs its place in the viewer.", "meta": {"from": "journal"}}
{"content": "request GET /api/main/agent is slower than its budget \u2014 93ms last (52ms of it working, 1ms collecting garbage, then 3ms more after it answered), against a budget of 50ms. Seen 130 times.", "meta": {"from": "journal"}}
{"content": "request GET /api/main/dashboard is slower than its budget \u2014 700ms last (325ms of it working, 11ms collecting garbage, then 1ms more after it answered), against a budget of 50ms. Seen 138 times.", "meta": {"from": "journal"}}
{"content": "rule 47 \u2014 The journal sets itself up once, when the server starts, never per\u2026 \u2014 Messages 2220 and 2224. Discovering features and their handlers, seating the feature rows and the rename sweep happen once, at server boot, and again only when a feature is switched on or off, a plugin changes or an environment is added: features.load keeps a set-up generation per journal (SEATED) and redoes the work only when that generation moves. A command, a request or a hook uses what is already there; nothing in their path may rediscover handlers or rescan folders. A cost that repeats per call is a bug to fix, not a budget to raise.", "meta": {"from": "journal"}}
{"content": "rule 27 \u2014 Name a declaration with the word a reader already knows \u2014 An attribute, a variable or a field gets the ordinary programming word for what it holds, not an evocative one. was, heard and alone were poetry; aliases, notify_actions and urgent_actions are what they are. The test: could a reader who has never seen this codebase guess what it holds from the name alone? Prose belongs in the help text and the abstract, where it is read as prose. This does not license abbreviations \u2014 a plain word in full, not a short one.", "meta": {"from": "journal"}}
{"content": "work 2147 in hand \u2014 Writing a work log entry takes a quarter second of work \u2014 if this is not what you are doing, end it or park it and start the work you are in; rule 45 \u2014 No prose words as names in code - said, says, heard, spoke, told\u2026 \u2014 Messages 1360 and 1698. The user has said more than once that code must not read like prose: a variable, attribute, property or function is named for what it holds or does (text, command, labels, lines), never with a verb from a story. 'says' on the Design type (1360) and 'said = call.said.lower()' in features/recital.py (1698) are the examples. Rule 27 states the naming rule; this one carries the words, so writing one of them whispers it. Before writing a name, ask whether a reader who has never seen the code would know what it holds.", "meta": {"from": "journal"}}
{"content": "rule 37 \u2014 Close every to-do explicitly with todo done or a Journal commit\u2026 \u2014 Ending work does not close its row. A to-do is closed by journal todo done <n> --how, or by a commit whose message carries Journal: todos done <n> at column 0, several numbers separated by commas. A row left open after its work landed misleads the next session and auto mode.", "meta": {"from": "journal"}}
{"content": "fact 13 \u2014 This live session runs the installed copy in .journal/journal.pyz \u2014 The running journal (server, hooks, CLI) runs from .journal/journal.pyz with its viewer and skills in .journal/src, never from the repo. A change in the repo reaches it only through python3 src/journal.py --root .journal upgrade, which packs the zip again. A commit alone changes nothing that is running.", "meta": {"from": "journal"}}
{"content": "fact 9 \u2014 Every public method on a controller becomes a journal command \u2014 The CLI is generated from the controllers: each public method of Controller, or of a typed controller, turns into journal <noun> <method>. A helper added to the base class therefore becomes a command on every type \u2014 which is how journal <type> handled and journal <type> refuse came to exist, from the CRUD funnel and the refusal funnel. An internal helper on a controller is named with a leading underscore, as _shaped and _status already are, or it ships as a command nobody meant.; fact 23 \u2014 Every upgrade brings system sequences and their triggers in line\u2026 \u2014 install.py runs ship_sequences after the migrations on each upgrade, so features/sequences/shipped.py is the whole source: change its wording and the next upgrade updates every journal, no migration needed. Shipped rows carry system=True and are read-only for everyone but SYSTEM (controllers/base.py _shipped).; fact 24 \u2014 An answer followed by tool calls can be missing from Claude's\u2026 \u2014 Seen 2026-09-24 for messages 9391-9404: text blocks opening with [!reply:n] that were followed by tool calls never appeared in the session's jsonl (only thinking and tool_use rows did), so the journal never saw them and the replies were lost. When a turn goes on after answering, send the answer with journal message reply <n> \"<text>\" instead of the tag.; fact 25 \u2014 A designer's install packs the whole tree, half-done server edits\u2026 \u2014 2026-09-25: Eames and Saul run python3 src/journal.py --root .journal upgrade after their viewer builds; it packs every file in src, so a server handler I was halfway through writing went live and raised on every PostToolUse hook. While designers work in parallel, keep server edits whole between tool calls (write and test in the scratchpad first), and reinstall after reverting anything.; fact 27 \u2014 Running src/journal.py against the live .journal root starts a\u2026 \u2014 Seen 2026-10-01: with VERSION bumped in the tree, src/journal.py --root .journal saw the live server as another build and started a new one on a new port (8431, 8432), and the user's tabs kept losing connection. Run source builds against a throwaway or demo root (~/projects/demo-crumb/.journal), never the live one, until the release is installed.; fact 31 \u2014 The overnight branch may be merged once every to-do is done and all\u2026 \u2014 Message 16886 (2026-10-06): the user said to keep working the to-do list on overnight-refactor; when every to-do item is finished, the whole suite passes and no part is left untested, the agent may merge it into main. This is the user's go for rule 57's 'before its pull request is approved'. Until all three hold, nothing of the branch goes to main except the hotfixes the user asks for.; rule 39 \u2014 Use only registered exclamation response tags \u2014 A tag like [!reply:12] runs a command, and only the tags in the tags.runs setting are registered. An invented tag does nothing and shows as raw text in the chat. Use the registered ones (reply, log, end, todo, fact, rule) and nothing else.; rule 48 \u2014 The viewer is built from its component library, and pages only\u2026 \u2014 Message 4258. Every visual piece the viewer shows more than once, or that a user would recognise as the same kind of thing (a dialog, a side panel or inspector, a dropdown, a list row, a switch, a button), is one component in web/src/kit, extracted aggressively, and every page composes those components instead of building its own copy. Before writing markup or styles in a page, look for the kit component that already does it and extend it with a prop; a second hand-built version is a bug. The side panel that animated in but not out, while a separate skill panel did both, is the example.; rule 52 \u2014 A chat mark for something the user did sits on the user's side \u2014 Message 10960 (2026-09-25): marks for the user's own actions, such as answering a question, are right-aligned like the user's messages. A mark is put there by giving its card side=user.; rule 54 \u2014 Settings and feature switches are read at boot and on change, never\u2026 \u2014 The user, message 13349: the application boots, determines every feature and setting once, and re-evaluates only when something changes, such as a setting or a plugin. Never lazy-load settings.", "meta": {"from": "journal"}}
{"content": "Code Commandments \u2014 before you wrap up \u2014 you've changed 3 judged files since th\u2026 \u2014 Code Commandments \u2014 before you wrap up: you've changed 3 judged files since the last commit. Consider running `commandments judge --changes` to confirm they conform, and fix any sin at its SOURCE (don't launder a finding with a default/cast/null-check). This is a one-time nudge for this batch \u2014 if you've already judged, or these changes aren't worth a scan, just say so and carry on.", "meta": {"from": "journal"}}
{"content": "waiting: 1 unread worktree 70", "meta": {"from": "journal"}}
{"content": "work 2135, A tunnel address owned by another account is replaced by itself, is\u2026 \u2014 it was parked because: Tesla Tunnelbaum builds it on main; the transportklok address was replaced by hand. journal work resume 2135 picks it up again.", "meta": {"from": "journal"}}
{"content": "check 27 failed, nothing was committed \u2014 check 27 failed, nothing was committed def hook(body: dict): return subprocess.run([\"sh\", \"-c\", wired], input=json.dumps(body), text=True, env=env, capture_output=True, timeout=WAIT) channel = json.loads((root.parent / \".mcp.json\").read_text())[\"mcpServers\"][\"journal\"] assert channel == {\"command\": sys.executable, \"args\": [str(root / \"journal.py\"), \"-m\", \"channel\", str(root)]}, \\ \"the channel runs the interpreter that installed it, with a path that has a space in it kept whole\" display = {\"hook_event_name\": \"MessageDisplay\", \"session_id\": \"s1\", \"message_id\": \"m1\", \"index\": 0, \"final\": True, \"delta\": \"said while the server was down\"} def serving(): server = subprocess.Popen([*journal, \"serve\", \"--port\", \"0\"], cwd=root.parent, env=env, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) began = time.time() while time.time() - began < WAIT and not (root / \"runtime\" / \"heartbeat\").is_file(): time.sleep(0.1) return server server = serving() try: hook({\"hook_event_name\": \"SessionStart\", \"session_id\": \"s1\", \"cwd\": str(root.parent), \"source\": \"startup\"}) finally: server.terminate() server.wait(WAIT) (root / \"runtime\" / \"heartbeat\").unlink(missing_ok=True) hook(display) assert list((root / \"runtime\" / \"unsent\").glob(\"*.json\")), \"the display hook keeps what the server could not take\" server = serving() try: began, listed = time.time(), \"\" while \"said while the server was down\" not in listed and time.time() - began < WAIT: time.sleep(0.2) listed = subprocess.run([*journal, \"message\", \"all\"], cwd=root.parent, env=env, capture_output=True, text=True, timeout=WAIT).stdout finally: server.terminate() server.wait(WAIT) >       assert \"said while the server was down\" in listed, \"a message shown while the server was down reaches the chat once it is back\" E       AssertionError: a message shown while the server was down reaches the chat once it is back E       assert 'said while the server was down' in '' tests/test_it_boots.py:343: AssertionError =========================== short test summary info ============================ FAILED tests/test_it_boots.py::test_a_message_shown_while_the_server_is_down_reaches_the_chat_once_it_is_back 1 failed, 438 passed in 206.96s (0:03:26); check 27 failed - 1 failed, 438 passed in 206.96s (0 -03 -26) \u2014 journal check show 27 says why; fix it, then journal check run 27", "meta": {"from": "journal"}}
{"content": "work 2135, A tunnel address owned by another account is replaced by itself, is\u2026 \u2014 it was parked because: Tesla Tunnelbaum builds it on main; the transportklok address was replaced by hand. journal work resume 2135 picks it up again.; fact 18 \u2014 cProfile inflates the slow-request profiles about tenfold \u2014 The faults feature writes a profile when a request passes its budget, and the profile is taken with cProfile, which adds per-call overhead. On 2026-09-22 /api/summary profiled at 58ms with 48ms inside Resource.fork's deep copy; with the profiler off the same call ran in 2 to 7ms. Read the profile for where the time goes in relative terms, then time the call with curl before changing anything.; fact 26 \u2014 Claude Code reads agent profiles when a session starts \u2014 Seen 2026-09-26: after the board-filler's profile in .claude/agents gained its steps and the Grep rule, dispatches from the running session still used the old profile (a 3.5-minute first question, shell grep refused); after the session restarted, the same request took 21 seconds with 4 calls. A change to an agent type reaches only sessions started after it is written.", "meta": {"from": "journal"}}
{"content": "chat etiquette - a line from the journal is an instruction, not a message\u2026 \u2014 a turn that only handles a journal line needs no words: act on it, or say once in the chat what you wait on, then carry on; what the user needs to know still goes to the chat", "meta": {"from": "journal"}}
{"content": "Code Commandments \u2014 you're editing `test_it_boots.py`, a test/stub/fixture that\u2026 \u2014 Code Commandments \u2014 you're editing `test_it_boots.py`, a test/stub/fixture that `judge` never scans, so nothing here will flag a symptom-fix. If you're changing it to make a failing check pass, first ask WHERE the failure is born: a failing test usually means the PRODUCTION code is missing behaviour \u2014 a method, a type, a total value on the real type. Fix it THERE (trace to the source; re-open the relevant skill), and change this file only if the TEST itself is wrong. If this is just legitimate test coverage, carry on.", "meta": {"from": "journal"}}
{"content": "helper 92, Grace Vitestwood, reported in message 16959 \u2014 read it, then journal helper finish 92 once its work is taken or dropped", "meta": {"from": "journal"}}
{"content": "law L2 \u2014 Every subagent is bound to a concrete job; never dispatch a generic\u2026 \u2014 Use the most specific available agent type whose declared purpose matches the assignment. On providers without agent types, give the dispatch a concrete task name and bounded prompt. If no suitable specialization exists, keep the work in the main agent instead of manufacturing an unscoped helper.; law L3 \u2014 Read narrowly - grep for the line, sed a range, head the file; never\u2026 \u2014 Everything a tool returns stays in the context for good and is paid for on every turn after it. Search before you read, read the range you need, and cap output with grep, head or tail. Read a whole file only when you need all of it.; law L4 \u2014 Follow-up work goes back to the subagent that did the first part\u2026 \u2014 A subagent that drew a design, wrote the code or ran the research keeps what it learned. When the user asks for a change to its work, continue that subagent with a message rather than dispatching a new one that has to rediscover everything; start fresh only when the earlier one is gone or the new work is unrelated.", "meta": {"from": "journal"}}
{"content": "rule 55 \u2014 Always dispatch Codex helpers on gpt-6-sol \u2014 The user's word, message 13431: switch the codex agents to GPT-6-Sol and make it their default. ~/.codex/config.toml names it as the default model too.", "meta": {"from": "journal"}}
{"content": "work 2135, A tunnel address owned by another account is replaced by itself, is\u2026 \u2014 it was parked because: Tesla Tunnelbaum builds it on main; the transportklok address was replaced by hand. journal work resume 2135 picks it up again.; commit 3768ddead closed to-do 2915 and ended work 2147 \u2014 The rows and the work are done; take the next one.", "meta": {"from": "journal"}}
{"content": "check 27 passed and 3768ddea A work log entry no longer rebuilds the session's\u2026 \u2014 check 27 passed and 3768ddea A work log entry no longer rebuilds the session's start block: 52-88 ms of handler work becomes 3-4 ms is committed; then ran boot guard: installs, serves and launches claude, codex in 11.2s", "meta": {"from": "journal"}}
{"content": "fact 20 \u2014 A slim supervisor holds the agent and a worker reloads on every build \u2014 Since 2.118.0 (2026-09-23). src/supervisor.py is standard library only and never reloads: journal claude hands its process over to it (os.execv), and it owns the pty and the agent process, relays the terminal, writes the printed and screen captures, listens on the typist socket, restarts the agent in the same session from a relaunch command written to its runtime folder while a restart is pending, and stops it with escalation while draining the pty (an agent cannot finish exiting on macOS while its output is unread). It starts the worker (src/worker.py, which runs runner/worker.py; engine/worker.py stays as an alias for supervisors started before 2.201) and starts it again whenever it exits: RELOAD on a new build, RELAUNCH to restart the agent, STOP to end, HEAL or a quick crash to roll back a build through journal heal. The worker holds everything else: seating the session, the start-up confirm typed through the typist, services, viewer, update check, check-in, and the one-time relaunch of sessions launched before agents/terminal.py LAUNCH. agents/terminal.py holds only journal-side helpers. The server (serve.py) still runs the engines and re-execs itself on a .py change. When the agent exits, the supervisor runs journal ended, which puts set-aside hooks back and stops the server when no session is left.", "meta": {"from": "journal"}}
{"content": "request GET /api/main/agent is slower than its budget \u2014 484ms last (101ms of it working, 3ms collecting garbage, then 27ms more after it answered), against a budget of 50ms. Seen 139 times.; request GET /api/main/helper is slower than its budget \u2014 437ms last (95ms of it working, then 11ms more after it answered), against a budget of 50ms. Seen 32 times.", "meta": {"from": "journal"}}
{"content": "request GET /api/main/dashboard is slower than its budget \u2014 2422ms last (826ms of it working, 6ms collecting garbage), against a budget of 50ms. Seen 139 times.", "meta": {"from": "journal"}}
{"content": "rule 43 \u2014 A request or hook over its budget is fixed before the next release \u2014 Comment 1151 on this rule. When the faults feature reports a request, a hook or a command slower than its budget, file it as a to-do at once. It does not jump ahead of the work in hand, but no version is published while one is still open: profile it, fix it, and verify the new time before the release goes out. The budget is 50ms, because everything runs locally against files.", "meta": {"from": "journal"}}
{"content": "fact 13 \u2014 This live session runs the installed copy in .journal/journal.pyz \u2014 The running journal (server, hooks, CLI) runs from .journal/journal.pyz with its viewer and skills in .journal/src, never from the repo. A change in the repo reaches it only through python3 src/journal.py --root .journal upgrade, which packs the zip again. A commit alone changes nothing that is running.; rule 60 \u2014 A hotfix is done by a dispatched agent in a worktree of main \u2014 Message 16836 (2026-10-06): the orchestrator cut a worktree under .claude/worktrees for a Codex hotfix, its session moved to a new environment and the user's messages stopped reaching it. The user: when working on a branch and a hotfix comes in, create a worktree of main and dispatch an agent to do that work. The orchestrator stays on its branch and in its environment, and never cds into another checkout.", "meta": {"from": "journal"}}
{"content": "fact 9 \u2014 Every public method on a controller becomes a journal command \u2014 The CLI is generated from the controllers: each public method of Controller, or of a typed controller, turns into journal <noun> <method>. A helper added to the base class therefore becomes a command on every type \u2014 which is how journal <type> handled and journal <type> refuse came to exist, from the CRUD funnel and the refusal funnel. An internal helper on a controller is named with a leading underscore, as _shaped and _status already are, or it ships as a command nobody meant.; fact 23 \u2014 Every upgrade brings system sequences and their triggers in line\u2026 \u2014 install.py runs ship_sequences after the migrations on each upgrade, so features/sequences/shipped.py is the whole source: change its wording and the next upgrade updates every journal, no migration needed. Shipped rows carry system=True and are read-only for everyone but SYSTEM (controllers/base.py _shipped).", "meta": {"from": "journal"}}
{"content": "check 27 failed, nothing was committed \u2014 check 27 failed, nothing was committed ERROR src/features/browser_control/test.py::test_the_extension_drives_a_tab_answers_an_ask_and_its_picture_is_attached ERROR src/features/dumps/test.py::test_one_dump_is_worked_at_a_time_its_log_is_kept_and_filing_asks_for_the_next_step ERROR src/features/ask_questions/test.py::test_offers_choices_recognizes_numbered_and_lettered_options_but_not_prose ERROR src/features/terminal/test.py::test_the_worker_stops_on_request_or_signal_reloads_when_its_session_moves_and_a_failing_check_stops_nothing ERROR src/features/kanban/test.py::test_a_row_outside_an_active_plan_stays_in_to_do_and_the_hold_is_one_line ERROR src/features/session_briefing/test.py::test_a_model_switch_is_confirmed_when_claude_asks ERROR tests/test_it_boots.py::test_every_agent_launches_from_an_installed_zip[codex] ERROR src/features/record_audit/test.py::test_evidence_finds_dead_paths_and_verbs_and_a_struck_claim_has_none ERROR src/features/worktrees/test.py::test_a_restarted_worker_keeps_the_seat_its_terminal_moved_to ERROR src/features/organization/test.py::test_the_board_counts_each_role_by_the_tickets_where_its_work_is_in_hand ERROR src/features/chat_etiquette/test.py::test_chat_that_talks_about_the_journal_is_named_back_and_the_skill_is_always_loaded ERROR src/features/dumps/test.py::test_a_message_declared_a_transcript_becomes_a_dump ERROR src/features/reminders/test.py::test_nothing_standing_nothing_said - Im... ERROR src/features/worktrees/test.py::test_continuing_names_the_folders_latest_conversation ERROR tests/test_it_boots.py::test_the_launcher_carries_its_running_agent_over_to_a_new_build ERROR src/features/worktrees/test.py::test_journal_claude_with_a_worktree_makes_it_itself_and_starts_claude_inside_it ERROR src/features/session_briefing/test.py::test_a_typed_line_left_in_the_input_box_is_sent_again ERROR src/features/chat_etiquette/test.py::test_every_twentieth_journal_line_reminds_the_agent_of_chat_etiquette ERROR src/features/organization/test.py::test_a_global_role_takes_one_task_at_a_time_across_every_environment ERROR src/features/worktrees/test.py::test_a_bare_worktree_flag_is_named_after_the_chosen_environment ERROR src/features/dumps/test.py::test_a_filed_dump_is_summed_up_with_suggestions_the_user_takes_or_leaves ERROR src/features/reminders/test.py::test_configured_by_unit_every_2_tool_uses ERROR src/features/reminders/test.py::test_by_default_standing_reminders_are_said_at_every_quarter_of_context_not_on_idle ERROR src/features/dumps/test.py::test_an_idle_agent_is_told_to_carry_on_filing_even_with_auto_off ERROR src/features/worktrees/test.py::test_a_command_run_inside_a_worktree_works_the_worktrees_environment ERROR tests/test_it_boots.py::test_the_journal_starts_on_a_record_with_a_damaged_row ERROR src/features/organization/test.py::test_a_role_that_runs_as_an_agent_is_started_in_the_tickets_worktree ERROR src/features/worktrees/test.py::test_a_worktree_links_the_projects_journal_even_when_git_brings_old_journal_files ERROR src/features/dumps/test.py::test_pasted_text_splits_into_parts_and_a_question_carries_guesses ERROR src/features/session_recording/test.py::test_a_write_makes_a_frame_with_the_changed_row_and_file_and_a_quiet_poll_makes_none ERROR src/features/checks/test.py::test_a_check_runs_its_command_and_a_failure_is_filed_until_it_passes ERROR src/features/permission_prompts/test.py::test_a_permission_the_agent_waits_on_is_shown_in_the_chat_until_it_is_answered ERROR src/features/reminders/test.py::test_every_10_percent_of_context_said_when_a_mark_is_crossed ERROR src/features/permission_prompts/test.py::test_the_skip_switch_restarts_in_the_same_conversation_with_the_flag ERROR src/features/facts/test.py::test_standing_pins_are_repeated_at_the_first_quarter_and_superseding_or_promoting_strikes_the_old ERROR src/features/session_recording/test.py::test_stop_copies_the_transcript_of_an_agent_that_ran ERROR src/features/reminders/test.py::test_switched_off_silent - ImportError:... ERROR src/features/reminders/test.py::test_on_worked_the_standing_reminders_are_said_once_per_idle_stretch_after_tool_use ERROR src/features/checks/test.py::test_a_check_without_a_command_refuses_in_words 4 skipped, 440 errors in 3.83s; check 27 failed - 4 skipped, 440 errors in 3.83s \u2014 journal check show 27 says why; fix it, then journal check run 27", "meta": {"from": "journal"}}
{"content": "fact 25 \u2014 A designer's install packs the whole tree, half-done server edits\u2026 \u2014 2026-09-25: Eames and Saul run python3 src/journal.py --root .journal upgrade after their viewer builds; it packs every file in src, so a server handler I was halfway through writing went live and raised on every PostToolUse hook. While designers work in parallel, keep server edits whole between tool calls (write and test in the scratchpad first), and reinstall after reverting anything.; rule 41 \u2014 Keep moving, run the whole suite before every commit, never wait \u2014 The full suite runs in about seven seconds: .venv/bin/python -m pytest -q --timeout=300 -n auto. Run it before every commit instead of picking tests by name. Group rows that sit in the same code into one sitting: write them all, test once, commit once. And never wait, not for a subagent, a build, or an answer you can carry on without. Dispatch it and keep working. If you truly are waiting on something, say so in the work log.; rule 42 \u2014 Every user-facing text passes the formatters before it leaves the\u2026 \u2014 Not only a brief. A title, an abstract, an outcome and every section body are read by a person, so each goes through the same formatters on its way to the viewer \u2014 chat turns, activity items, to-do rows, inspector pages, docs alike. One field formatted out of five is not a rule, it is an accident, and it is how a raw tag ended up in the activity list after the tags feature had been stripping them for weeks. When a new field carries words a person reads, it joins the list in the same place.; rule 57 \u2014 Never merge the overnight refactor into main before its pull request\u2026 \u2014 Messages 15005, 15006, 15109, 15110 (2026-10-04): all refactor work goes on branch overnight-refactor and reaches the user as one pull request, which they read in the morning; nothing of it is merged into main until they say so. Hotfixes the user explicitly asks for go to main at once and are merged into the branch.", "meta": {"from": "journal"}}
{"content": "rule 40 \u2014 A feature is named for what it is, never for its machinery \u2014 Messages 599, 600 and 703. A feature is a capability the user would name and would think of switching off. File tracking, a write gate, a phrase bank, a tree diff are services used inside a feature, not features of their own: they live in the feature they serve. Before adding a directory under features/, say what the user would call it; if the answer names a mechanism, it belongs inside something else. Report 16 holds the grouping this implies.", "meta": {"from": "journal"}}
{"content": "work 2150 in hand \u2014 Recommend plugins that fit the project's languages \u2014 if this is not what you are doing, end it or park it and start the work you are in", "meta": {"from": "journal"}}
{"content": "Code Commandments \u2014 before you wrap up \u2014 you've changed 8 judged files since th\u2026 \u2014 Code Commandments \u2014 before you wrap up: you've changed 8 judged files since the last commit. Consider running `commandments judge --changes` to confirm they conform, and fix any sin at its SOURCE (don't launder a finding with a default/cast/null-check). This is a one-time nudge for this batch \u2014 if you've already judged, or these changes aren't worth a scan, just say so and carry on.", "meta": {"from": "journal"}}
{"content": "helper 94, Edsger Enginewright, reported in message 16968 \u2014 read it, then journal helper finish 94 once its work is taken or dropped", "meta": {"from": "journal"}}
{"content": "check 27 passed and a855efd2 The server's identity names the build it runs\u2026 \u2014 check 27 passed and a855efd2 The server's identity names the build it runs, and the boot test proves an upgrade brings the running server onto the new build is committed; then ran boot guard: installs, serves and launches claude, codex in 10.2s", "meta": {"from": "journal"}}
{"content": "work 2135, A tunnel address owned by another account is replaced by itself, is\u2026 \u2014 it was parked because: Tesla Tunnelbaum builds it on main; the transportklok address was replaced by hand. journal work resume 2135 picks it up again.; todo 2927, journal codex offers to set aside the current hooks and settings\u2026 \u2014 it is blocked because: on main in 2.249.8; Hedy ports it to the overnight branch. If it is not any more, journal todo unblock 2927. If it waits on a person or a decision, make it a question to them: journal todo ask 2927 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2928, Codex can dispatch subagents, is still blocked - is it still? \u2014 it is blocked because: on main in 2.249.8; Hedy ports it to the overnight branch. If it is not any more, journal todo unblock 2928. If it waits on a person or a decision, make it a question to them: journal todo ask 2928 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2929, Codex subagents show in the agent dropdown, is still blocked - is\u2026 \u2014 it is blocked because: on main in 2.249.8; Hedy ports it to the overnight branch. If it is not any more, journal todo unblock 2929. If it waits on a person or a decision, make it a question to them: journal todo ask 2929 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2876, A search mark opens to show what the search found and what was read\u2026 \u2014 it is blocked because: Linus Markwell (helper) is on it. If it is not any more, journal todo unblock 2876. If it waits on a person or a decision, make it a question to them: journal todo ask 2876 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2886, Every git action shows as a mark in the chat, is still blocked - is\u2026 \u2014 it is blocked because: Linus Markwell (helper) is on it. If it is not any more, journal todo unblock 2886. If it waits on a person or a decision, make it a question to them: journal todo ask 2886 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2936, A crashing service backs off, fails after five stops, and says why\u2026 \u2014 it is blocked because: a helper is on it (report 81 batches). If it is not any more, journal todo unblock 2936. If it waits on a person or a decision, make it a question to them: journal todo ask 2936 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2937, A share link opens only what it shares, is still blocked - is it\u2026 \u2014 it is blocked because: a helper is on it (report 81 batches). If it is not any more, journal todo unblock 2937. If it waits on a person or a decision, make it a question to them: journal todo ask 2937 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2938, The tunnel's problems are tested for a missing, logged-out or\u2026 \u2014 it is blocked because: a helper is on it (report 81 batches). If it is not any more, journal todo unblock 2938. If it waits on a person or a decision, make it a question to them: journal todo ask 2938 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2939, One engine runs per environment, and an orphan is ended, is still\u2026 \u2014 it is blocked because: a helper has it (report 81 batches). If it is not any more, journal todo unblock 2939. If it waits on a person or a decision, make it a question to them: journal todo ask 2939 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2940, The engine's terminal controls are tested with a fake driver, is\u2026 \u2014 it is blocked because: a helper has it (report 81 batches). If it is not any more, journal todo unblock 2940. If it waits on a person or a decision, make it a question to them: journal todo ask 2940 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2941, Ending a session keeps its worktree's commits, is still blocked\u2026 \u2014 it is blocked because: a helper has it (report 81 batches). If it is not any more, journal todo unblock 2941. If it waits on a person or a decision, make it a question to them: journal todo ask 2941 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2942, Hooks bind sessions to the right environment and process, is still\u2026 \u2014 it is blocked because: a helper has it (report 81 batches). If it is not any more, journal todo unblock 2942. If it waits on a person or a decision, make it a question to them: journal todo ask 2942 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2943, The Codex model and effort picker is tested, is still blocked - is\u2026 \u2014 it is blocked because: a helper has it (report 81 batches). If it is not any more, journal todo unblock 2943. If it waits on a person or a decision, make it a question to them: journal todo ask 2943 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2944, Codex usage and subagent rows are tested, is still blocked - is it\u2026 \u2014 it is blocked because: a helper has it (report 81 batches). If it is not any more, journal todo unblock 2944. If it waits on a person or a decision, make it a question to them: journal todo ask 2944 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2945, A phone code is never made without a tunnel address, is still\u2026 \u2014 it is blocked because: a helper is on it (report 81 batches). If it is not any more, journal todo unblock 2945. If it waits on a person or a decision, make it a question to them: journal todo ask 2945 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2946, Choosing a new tunnel address is tested, is still blocked - is it\u2026 \u2014 it is blocked because: a helper is on it (report 81 batches). If it is not any more, journal todo unblock 2946. If it waits on a person or a decision, make it a question to them: journal todo ask 2946 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2947, Sequence start filters, row deletion and dispatch mode are tested\u2026 \u2014 it is blocked because: a helper has it (report 81 batches). If it is not any more, journal todo unblock 2947. If it waits on a person or a decision, make it a question to them: journal todo ask 2947 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2948, No raw chip marker reaches a command's output or the agent, is\u2026 \u2014 it is blocked because: a helper has it (report 81 batches). If it is not any more, journal todo unblock 2948. If it waits on a person or a decision, make it a question to them: journal todo ask 2948 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2949, The orchestrator's calls fire once and repeat on time, is still\u2026 \u2014 it is blocked because: a helper has it (report 81 batches). If it is not any more, journal todo unblock 2949. If it waits on a person or a decision, make it a question to them: journal todo ask 2949 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2950, Branch links and viewer ports are tested, is still blocked - is it\u2026 \u2014 it is blocked because: a helper has it (report 81 batches). If it is not any more, journal todo unblock 2950. If it waits on a person or a decision, make it a question to them: journal todo ask 2950 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2951, The viewer gets a test runner for its own code, is still blocked\u2026 \u2014 it is blocked because: a helper is on it (report 81 batches). If it is not any more, journal todo unblock 2951. If it waits on a person or a decision, make it a question to them: journal todo ask 2951 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2952, The phone dialog's every state ends in words and an action, is\u2026 \u2014 it is blocked because: a helper is on it (report 81 batches). If it is not any more, journal todo unblock 2952. If it waits on a person or a decision, make it a question to them: journal todo ask 2952 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2953, Tunler login and install outcomes are tested, is still blocked - is\u2026 \u2014 it is blocked because: a helper has it (report 81 batches). If it is not any more, journal todo unblock 2953. If it waits on a person or a decision, make it a question to them: journal todo ask 2953 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2954, The share tunnel pill shows the right state, is still blocked - is\u2026 \u2014 it is blocked because: a helper has it (report 81 batches). If it is not any more, journal todo unblock 2954. If it waits on a person or a decision, make it a question to them: journal todo ask 2954 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2955, The viewer's boot is tested on a scratch install, is still blocked\u2026 \u2014 it is blocked because: a helper is on it (report 81 batches). If it is not any more, journal todo unblock 2955. If it waits on a person or a decision, make it a question to them: journal todo ask 2955 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2956, The viewer recovers after the server goes away and comes back, is\u2026 \u2014 it is blocked because: a helper has it (report 81 batches). If it is not any more, journal todo unblock 2956. If it waits on a person or a decision, make it a question to them: journal todo ask 2956 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2957, Sending in the chat never loses or doubles a message, is still\u2026 \u2014 it is blocked because: a helper has it (report 81 batches). If it is not any more, journal todo unblock 2957. If it waits on a person or a decision, make it a question to them: journal todo ask 2957 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2958, Answering a question is tested, failure included, is still blocked\u2026 \u2014 it is blocked because: a helper has it (report 81 batches). If it is not any more, journal todo unblock 2958. If it waits on a person or a decision, make it a question to them: journal todo ask 2958 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2959, The settings functions and a settings round trip are tested, is\u2026 \u2014 it is blocked because: a helper is on it (report 81 batches). If it is not any more, journal todo unblock 2959. If it waits on a person or a decision, make it a question to them: journal todo ask 2959 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2960, Board, plan and ticket flows are tested, is still blocked - is it\u2026 \u2014 it is blocked because: a helper has it (report 81 batches). If it is not any more, journal todo unblock 2960. If it waits on a person or a decision, make it a question to them: journal todo ask 2960 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2961, The Documents page's states are tested, is still blocked - is it\u2026 \u2014 it is blocked because: a helper has it (report 81 batches). If it is not any more, journal todo unblock 2961. If it waits on a person or a decision, make it a question to them: journal todo ask 2961 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2962, The phone app is tested, is still blocked - is it still? \u2014 it is blocked because: a helper has it (report 81 batches). If it is not any more, journal todo unblock 2962. If it waits on a person or a decision, make it a question to them: journal todo ask 2962 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2963, Routing builds and reads every viewer address, is still blocked\u2026 \u2014 it is blocked because: a helper is on it (report 81 batches). If it is not any more, journal todo unblock 2963. If it waits on a person or a decision, make it a question to them: journal todo ask 2963 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2964, The stores keep rows and unread marks right, is still blocked - is\u2026 \u2014 it is blocked because: a helper has it (report 81 batches). If it is not any more, journal todo unblock 2964. If it waits on a person or a decision, make it a question to them: journal todo ask 2964 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2965, The shared page a visitor opens is tested, is still blocked - is it\u2026 \u2014 it is blocked because: a helper has it (report 81 batches). If it is not any more, journal todo unblock 2965. If it waits on a person or a decision, make it a question to them: journal todo ask 2965 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2966, Installing on Python 3.9 says plainly that 3.10 is needed, is still\u2026 \u2014 it is blocked because: a helper is on it (report 81 batches). If it is not any more, journal todo unblock 2966. If it waits on a person or a decision, make it a question to them: journal todo ask 2966 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2967, Hooks work with a curl older than 7.87, is still blocked - is it\u2026 \u2014 it is blocked because: a helper is on it (report 81 batches). If it is not any more, journal todo unblock 2967. If it waits on a person or a decision, make it a question to them: journal todo ask 2967 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2968, Putting hooks back keeps what changed during the session, is still\u2026 \u2014 it is blocked because: a helper is on it (report 81 batches). If it is not any more, journal todo unblock 2968. If it waits on a person or a decision, make it a question to them: journal todo ask 2968 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2969, install.sh is tested as a first-time user runs it, is still blocked\u2026 \u2014 it is blocked because: a helper is on it (report 81 batches). If it is not any more, journal todo unblock 2969. If it waits on a person or a decision, make it a question to them: journal todo ask 2969 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2970, A broken build with nothing to roll back to stops and says so, is\u2026 \u2014 it is blocked because: a helper is on it (report 81 batches). If it is not any more, journal todo unblock 2970. If it waits on a person or a decision, make it a question to them: journal todo ask 2970 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2971, journal claude or codex without the agent installed refuses before\u2026 \u2014 it is blocked because: a helper is on it (report 81 batches). If it is not any more, journal todo unblock 2971. If it waits on a person or a decision, make it a question to them: journal todo ask 2971 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2972, The start menus are tested in a real terminal, is still blocked\u2026 \u2014 it is blocked because: a helper has it (report 81 batches). If it is not any more, journal todo unblock 2972. If it waits on a person or a decision, make it a question to them: journal todo ask 2972 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2973, An old record upgrades through every migration, is still blocked\u2026 \u2014 it is blocked because: a helper has it (report 81 batches). If it is not any more, journal todo unblock 2973. If it waits on a person or a decision, make it a question to them: journal todo ask 2973 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2974, Launching offline or behind a prompt does not hang, is still\u2026 \u2014 it is blocked because: a helper has it (report 81 batches). If it is not any more, journal todo unblock 2974. If it waits on a person or a decision, make it a question to them: journal todo ask 2974 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2975, A moved or upgraded Python is reported plainly, is still blocked\u2026 \u2014 it is blocked because: a helper has it (report 81 batches). If it is not any more, journal todo unblock 2975. If it waits on a person or a decision, make it a question to them: journal todo ask 2975 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2976, A slow machine during warm-up loses no hooks and starts no second\u2026 \u2014 it is blocked because: a helper has it (report 81 batches). If it is not any more, journal todo unblock 2976. If it waits on a person or a decision, make it a question to them: journal todo ask 2976 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2977, A server that hangs on start is rolled back, is still blocked - is\u2026 \u2014 it is blocked because: a helper has it (report 81 batches). If it is not any more, journal todo unblock 2977. If it waits on a person or a decision, make it a question to them: journal todo ask 2977 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2978, Worktrees and helpers work in a new git repo, is still blocked - is\u2026 \u2014 it is blocked because: a helper has it (report 81 batches). If it is not any more, journal todo unblock 2978. If it waits on a person or a decision, make it a question to them: journal todo ask 2978 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2979, A machine with only Claude or only Codex boots, is still blocked\u2026 \u2014 it is blocked because: a helper has it (report 81 batches). If it is not any more, journal todo unblock 2979. If it waits on a person or a decision, make it a question to them: journal todo ask 2979 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2980, Plugin services run from the packed build, is still blocked - is it\u2026 \u2014 it is blocked because: a helper has it (report 81 batches). If it is not any more, journal todo unblock 2980. If it waits on a person or a decision, make it a question to them: journal todo ask 2980 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2981, Long typed text is never cut short, is still blocked - is it still? \u2014 it is blocked because: a helper has it (report 81 batches). If it is not any more, journal todo unblock 2981. If it waits on a person or a decision, make it a question to them: journal todo ask 2981 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2982, Running out of viewer ports says so plainly, is still blocked - is\u2026 \u2014 it is blocked because: a helper is on it (report 81 batches). If it is not any more, journal todo unblock 2982. If it waits on a person or a decision, make it a question to them: journal todo ask 2982 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2984, Close GitHub issue 4 once helpers can start in a nested checkout\u2026 \u2014 it is blocked because: waits for the overnight branch to be released. If it is not any more, journal todo unblock 2984. If it waits on a person or a decision, make it a question to them: journal todo ask 2984 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.", "meta": {"from": "journal"}}
{"content": "Code Commandments \u2014 before you wrap up \u2014 you've changed 5 judged files since th\u2026 \u2014 Code Commandments \u2014 before you wrap up: you've changed 5 judged files since the last commit. Consider running `commandments judge --changes` to confirm they conform, and fix any sin at its SOURCE (don't launder a finding with a default/cast/null-check). This is a one-time nudge for this batch \u2014 if you've already judged, or these changes aren't worth a scan, just say so and carry on.", "meta": {"from": "journal"}}
{"content": "1 new message 16971 - answer by opening your turn with [!reply:16971]; message 16971 updated", "meta": {"from": "journal"}}
{"content": "check 27 passed and f3c007d7 Taking a helper's work that changes viewer text\u2026 \u2014 check 27 passed and f3c007d7 Taking a helper's work that changes viewer text asks for a wording review first is committed; then ran boot guard: installs, serves and launches claude, codex in 10.4s", "meta": {"from": "journal"}}
{"content": "work 2135, A tunnel address owned by another account is replaced by itself, is\u2026 \u2014 it was parked because: Tesla Tunnelbaum builds it on main; the transportklok address was replaced by hand. journal work resume 2135 picks it up again.", "meta": {"from": "journal"}}
{"content": "Code Commandments \u2014 before you wrap up \u2014 you've changed 4 judged files since th\u2026 \u2014 Code Commandments \u2014 before you wrap up: you've changed 4 judged files since the last commit. Consider running `commandments judge --changes` to confirm they conform, and fix any sin at its SOURCE (don't launder a finding with a default/cast/null-check). This is a one-time nudge for this batch \u2014 if you've already judged, or these changes aren't worth a scan, just say so and carry on.", "meta": {"from": "journal"}}
{"content": "closing Edsger's to-dos and starting the next commit check came back - Close\u2026", "meta": {"from": "journal"}}
{"content": "todo 2876, A search mark opens to show what the search found and what was read\u2026 \u2014 it is blocked because: Linus Markwell (helper) is on it. If it is not any more, journal todo unblock 2876. If it waits on a person or a decision, make it a question to them: journal todo ask 2876 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2886, Every git action shows as a mark in the chat, is still blocked - is\u2026 \u2014 it is blocked because: Linus Markwell (helper) is on it. If it is not any more, journal todo unblock 2886. If it waits on a person or a decision, make it a question to them: journal todo ask 2886 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2953, Tunler login and install outcomes are tested, is still blocked - is\u2026 \u2014 it is blocked because: a helper has it (report 81 batches). If it is not any more, journal todo unblock 2953. If it waits on a person or a decision, make it a question to them: journal todo ask 2953 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2954, The share tunnel pill shows the right state, is still blocked - is\u2026 \u2014 it is blocked because: a helper has it (report 81 batches). If it is not any more, journal todo unblock 2954. If it waits on a person or a decision, make it a question to them: journal todo ask 2954 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2956, The viewer recovers after the server goes away and comes back, is\u2026 \u2014 it is blocked because: a helper has it (report 81 batches). If it is not any more, journal todo unblock 2956. If it waits on a person or a decision, make it a question to them: journal todo ask 2956 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2957, Sending in the chat never loses or doubles a message, is still\u2026 \u2014 it is blocked because: a helper has it (report 81 batches). If it is not any more, journal todo unblock 2957. If it waits on a person or a decision, make it a question to them: journal todo ask 2957 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2958, Answering a question is tested, failure included, is still blocked\u2026 \u2014 it is blocked because: a helper has it (report 81 batches). If it is not any more, journal todo unblock 2958. If it waits on a person or a decision, make it a question to them: journal todo ask 2958 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2960, Board, plan and ticket flows are tested, is still blocked - is it\u2026 \u2014 it is blocked because: a helper has it (report 81 batches). If it is not any more, journal todo unblock 2960. If it waits on a person or a decision, make it a question to them: journal todo ask 2960 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2961, The Documents page's states are tested, is still blocked - is it\u2026 \u2014 it is blocked because: a helper has it (report 81 batches). If it is not any more, journal todo unblock 2961. If it waits on a person or a decision, make it a question to them: journal todo ask 2961 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2962, The phone app is tested, is still blocked - is it still? \u2014 it is blocked because: a helper has it (report 81 batches). If it is not any more, journal todo unblock 2962. If it waits on a person or a decision, make it a question to them: journal todo ask 2962 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2964, The stores keep rows and unread marks right, is still blocked - is\u2026 \u2014 it is blocked because: a helper has it (report 81 batches). If it is not any more, journal todo unblock 2964. If it waits on a person or a decision, make it a question to them: journal todo ask 2964 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2965, The shared page a visitor opens is tested, is still blocked - is it\u2026 \u2014 it is blocked because: a helper has it (report 81 batches). If it is not any more, journal todo unblock 2965. If it waits on a person or a decision, make it a question to them: journal todo ask 2965 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2966, Installing on Python 3.9 says plainly that 3.10 is needed, is still\u2026 \u2014 it is blocked because: a helper is on it (report 81 batches). If it is not any more, journal todo unblock 2966. If it waits on a person or a decision, make it a question to them: journal todo ask 2966 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2967, Hooks work with a curl older than 7.87, is still blocked - is it\u2026 \u2014 it is blocked because: a helper is on it (report 81 batches). If it is not any more, journal todo unblock 2967. If it waits on a person or a decision, make it a question to them: journal todo ask 2967 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2968, Putting hooks back keeps what changed during the session, is still\u2026 \u2014 it is blocked because: a helper is on it (report 81 batches). If it is not any more, journal todo unblock 2968. If it waits on a person or a decision, make it a question to them: journal todo ask 2968 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2969, install.sh is tested as a first-time user runs it, is still blocked\u2026 \u2014 it is blocked because: a helper is on it (report 81 batches). If it is not any more, journal todo unblock 2969. If it waits on a person or a decision, make it a question to them: journal todo ask 2969 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2970, A broken build with nothing to roll back to stops and says so, is\u2026 \u2014 it is blocked because: a helper is on it (report 81 batches). If it is not any more, journal todo unblock 2970. If it waits on a person or a decision, make it a question to them: journal todo ask 2970 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2971, journal claude or codex without the agent installed refuses before\u2026 \u2014 it is blocked because: a helper is on it (report 81 batches). If it is not any more, journal todo unblock 2971. If it waits on a person or a decision, make it a question to them: journal todo ask 2971 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2972, The start menus are tested in a real terminal, is still blocked\u2026 \u2014 it is blocked because: a helper has it (report 81 batches). If it is not any more, journal todo unblock 2972. If it waits on a person or a decision, make it a question to them: journal todo ask 2972 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2973, An old record upgrades through every migration, is still blocked\u2026 \u2014 it is blocked because: a helper has it (report 81 batches). If it is not any more, journal todo unblock 2973. If it waits on a person or a decision, make it a question to them: journal todo ask 2973 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2974, Launching offline or behind a prompt does not hang, is still\u2026 \u2014 it is blocked because: a helper has it (report 81 batches). If it is not any more, journal todo unblock 2974. If it waits on a person or a decision, make it a question to them: journal todo ask 2974 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2975, A moved or upgraded Python is reported plainly, is still blocked\u2026 \u2014 it is blocked because: a helper has it (report 81 batches). If it is not any more, journal todo unblock 2975. If it waits on a person or a decision, make it a question to them: journal todo ask 2975 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2976, A slow machine during warm-up loses no hooks and starts no second\u2026 \u2014 it is blocked because: a helper has it (report 81 batches). If it is not any more, journal todo unblock 2976. If it waits on a person or a decision, make it a question to them: journal todo ask 2976 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2977, A server that hangs on start is rolled back, is still blocked - is\u2026 \u2014 it is blocked because: a helper has it (report 81 batches). If it is not any more, journal todo unblock 2977. If it waits on a person or a decision, make it a question to them: journal todo ask 2977 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2978, Worktrees and helpers work in a new git repo, is still blocked - is\u2026 \u2014 it is blocked because: a helper has it (report 81 batches). If it is not any more, journal todo unblock 2978. If it waits on a person or a decision, make it a question to them: journal todo ask 2978 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2979, A machine with only Claude or only Codex boots, is still blocked\u2026 \u2014 it is blocked because: a helper has it (report 81 batches). If it is not any more, journal todo unblock 2979. If it waits on a person or a decision, make it a question to them: journal todo ask 2979 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2980, Plugin services run from the packed build, is still blocked - is it\u2026 \u2014 it is blocked because: a helper has it (report 81 batches). If it is not any more, journal todo unblock 2980. If it waits on a person or a decision, make it a question to them: journal todo ask 2980 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2981, Long typed text is never cut short, is still blocked - is it still? \u2014 it is blocked because: a helper has it (report 81 batches). If it is not any more, journal todo unblock 2981. If it waits on a person or a decision, make it a question to them: journal todo ask 2981 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2982, Running out of viewer ports says so plainly, is still blocked - is\u2026 \u2014 it is blocked because: a helper is on it (report 81 batches). If it is not any more, journal todo unblock 2982. If it waits on a person or a decision, make it a question to them: journal todo ask 2982 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2984, Close GitHub issue 4 once helpers can start in a nested checkout\u2026 \u2014 it is blocked because: waits for the overnight branch to be released. If it is not any more, journal todo unblock 2984. If it waits on a person or a decision, make it a question to them: journal todo ask 2984 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.", "meta": {"from": "journal"}}
{"content": "helper 95, Linus Markwell, reported in message 16977 \u2014 read it, then journal helper finish 95 once its work is taken or dropped", "meta": {"from": "journal"}}
{"content": "check 27 passed and 4f89104b5 A project's languages get it a suggestion for a\u2026 \u2014 check 27 passed and 4f89104b5 A project's languages get it a suggestion for a plugin that fits, and the labelled stop button loses its icon is committed; then ran boot guard: installs, serves and launches claude, codex in 10.0s", "meta": {"from": "journal"}}
{"content": "work 2135, A tunnel address owned by another account is replaced by itself, is\u2026 \u2014 it was parked because: Tesla Tunnelbaum builds it on main; the transportklok address was replaced by hand. journal work resume 2135 picks it up again.; commit 4f89104b5 closed to-do 2692 and ended work 2150 \u2014 The rows and the work are done; take the next one.; fact 27 \u2014 Running src/journal.py against the live .journal root starts a\u2026 \u2014 Seen 2026-10-01: with VERSION bumped in the tree, src/journal.py --root .journal saw the live server as another build and started a new one on a new port (8431, 8432), and the user's tabs kept losing connection. Run source builds against a throwaway or demo root (~/projects/demo-crumb/.journal), never the live one, until the release is installed.", "meta": {"from": "journal"}}
{"content": "chat etiquette - a line from the journal is an instruction, not a message\u2026 \u2014 a turn that only handles a journal line needs no words: act on it, or say once in the chat what you wait on, then carry on; what the user needs to know still goes to the chat", "meta": {"from": "journal"}}
{"content": "the live install, then Linus's work came back - Install the branch live\u2026", "meta": {"from": "journal"}}
{"content": "work 2135, A tunnel address owned by another account is replaced by itself, is\u2026 \u2014 it was parked because: Tesla Tunnelbaum builds it on main; the transportklok address was replaced by hand. journal work resume 2135 picks it up again.", "meta": {"from": "journal"}}
{"content": "commit 3da970897 closed to-do 2886, to-do 2876 \u2014 The rows and the work are done; take the next one.", "meta": {"from": "journal"}}
{"content": "request POST /api/run (helper finish) is slower than its budget \u2014 1270ms last (362ms of it working, then 26ms more after it answered), against a budget of 50ms. Seen 39 times.", "meta": {"from": "journal"}}
{"content": "fact 30 \u2014 The tunler server refuses TLS for any subdomain without a tunnel \u2014 Seen 2026-10-04 in the server's docker logs (ssh root@tunler.jessegall.nl, container tunler): 'TLS handshake error ... host \"journal-probe.tunler.jessegall.nl\" not allowed'. A made-up subdomain never answers even when the server is healthy; probe https://tunler.jessegall.nl/ for the server itself. Root SSH to the server works.", "meta": {"from": "journal"}}
{"content": "helper 93, Ada Firstboot, reported in message 16982 \u2014 read it, then journal helper finish 93 once its work is taken or dropped", "meta": {"from": "journal"}}
{"content": "phone 38 completed; 1 new phone 39", "meta": {"from": "journal"}}
{"content": "1 new message 16983 - answer by opening your turn with [!reply:16983]; message 16983 updated", "meta": {"from": "journal"}}
{"content": "helper 92, Grace Vitestwood, reported in message 16984 \u2014 read it, then journal helper finish 92 once its work is taken or dropped", "meta": {"from": "journal"}}
{"content": "phone 39 completed; 1 new phone 40", "meta": {"from": "journal"}}
{"content": "waiting: 1 unread phone 40", "meta": {"from": "journal"}}
{"content": "work 2135, A tunnel address owned by another account is replaced by itself, is\u2026 \u2014 it was parked because: Tesla Tunnelbaum builds it on main; the transportklok address was replaced by hand. journal work resume 2135 picks it up again.", "meta": {"from": "journal"}}
{"content": "todo 2960, Board, plan and ticket flows are tested, is still blocked - is it\u2026 \u2014 it is blocked because: a helper has it (report 81 batches). If it is not any more, journal todo unblock 2960. If it waits on a person or a decision, make it a question to them: journal todo ask 2960 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2961, The Documents page's states are tested, is still blocked - is it\u2026 \u2014 it is blocked because: a helper has it (report 81 batches). If it is not any more, journal todo unblock 2961. If it waits on a person or a decision, make it a question to them: journal todo ask 2961 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2962, The phone app is tested, is still blocked - is it still? \u2014 it is blocked because: a helper has it (report 81 batches). If it is not any more, journal todo unblock 2962. If it waits on a person or a decision, make it a question to them: journal todo ask 2962 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2964, The stores keep rows and unread marks right, is still blocked - is\u2026 \u2014 it is blocked because: a helper has it (report 81 batches). If it is not any more, journal todo unblock 2964. If it waits on a person or a decision, make it a question to them: journal todo ask 2964 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2965, The shared page a visitor opens is tested, is still blocked - is it\u2026 \u2014 it is blocked because: a helper has it (report 81 batches). If it is not any more, journal todo unblock 2965. If it waits on a person or a decision, make it a question to them: journal todo ask 2965 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2984, Close GitHub issue 4 once helpers can start in a nested checkout\u2026 \u2014 it is blocked because: waits for the overnight branch to be released. If it is not any more, journal todo unblock 2984. If it waits on a person or a decision, make it a question to them: journal todo ask 2984 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.", "meta": {"from": "journal"}}
{"content": "1 new message 16989 - answer by opening your turn with [!reply:16989]; message 16989 updated", "meta": {"from": "journal"}}
{"content": "1 new message 16991 - answer by opening your turn with [!reply:16991]", "meta": {"from": "journal"}}
{"content": "the todo tag does this in one step \u2014 [!todo=\"the title\"] files it with the turn as its brief; it runs only when it opens the last text of your turn", "meta": {"from": "journal"}}
{"content": "answer message 16989 before you write anything \u2014 answer by opening your turn with [!reply:16989]. a reply, a reaction, or journal message processed <n>", "meta": {"from": "journal"}}
{"content": "Code Commandments \u2014 before you wrap up \u2014 you've changed 2 judged files since th\u2026 \u2014 Code Commandments \u2014 before you wrap up: you've changed 2 judged files since the last commit. Consider running `commandments judge --changes` to confirm they conform, and fix any sin at its SOURCE (don't launder a finding with a default/cast/null-check). This is a one-time nudge for this batch \u2014 if you've already judged, or these changes aren't worth a scan, just say so and carry on.", "meta": {"from": "journal"}}
{"content": "1 new message 16992 - answer by opening your turn with [!reply:16992]", "meta": {"from": "journal"}}
{"content": "1 new message 16993 - answer by opening your turn with [!reply:16993]", "meta": {"from": "journal"}}
{"content": "1 new message 16994 - answer by opening your turn with [!reply:16994]", "meta": {"from": "journal"}}
{"content": "phone 40 completed; 1 new phone 41", "meta": {"from": "journal"}}
{"content": "1 new message 16996 - answer by opening your turn with [!reply:16996]", "meta": {"from": "journal"}}
{"content": "chat etiquette - a line from the journal is an instruction, not a message\u2026 \u2014 a turn that only handles a journal line needs no words: act on it, or say once in the chat what you wait on, then carry on; what the user needs to know still goes to the chat", "meta": {"from": "journal"}}
{"content": "phone 41 completed; 1 new phone 42", "meta": {"from": "journal"}}
{"content": "phone 42 completed; 1 new phone 43", "meta": {"from": "journal"}}
{"content": "1 new message 16997 - answer by opening your turn with [!reply:16997]", "meta": {"from": "journal"}}
{"content": "answer message 16996 before you write anything \u2014 answer by opening your turn with [!reply:16996]. a reply, a reaction, or journal message processed <n>", "meta": {"from": "journal"}}
{"content": "1 new message 16998 - answer by opening your turn with [!reply:16998]", "meta": {"from": "journal"}}
{"content": "work 2135, A tunnel address owned by another account is replaced by itself, is\u2026 \u2014 it was parked because: Tesla Tunnelbaum builds it on main; the transportklok address was replaced by hand. journal work resume 2135 picks it up again.", "meta": {"from": "journal"}}
{"content": "check 27 passed and a53217e32 The System settings tabs are called Project\u2026 \u2014 check 27 passed and a53217e32 The System settings tabs are called Project, Browser and Shut down is committed; then ran boot guard: installs, serves and launches claude, codex in 5.0s", "meta": {"from": "journal"}}
{"content": "sequence 10, Writing a report, step 1 of 6 - Add the report\u2019s section headings \u2014 Finishing this sequence comes before anything else you do; everything else waits until it is finished or abandoned. Take it up first with journal sequence follow 10 --about report:82. Lead with the answer in the report's brief, then put every part you plan on the report before writing any of them: journal report section 82 \"<part>\" \"Being written.\" for each, in order: the evidence, what was already sound, what remains uncertain. Then journal sequence next 10 --about report:82.", "meta": {"from": "journal"}}
{"content": "waiting: 3 unread worktrees 71, 72, 73; 1 unread phone 43", "meta": {"from": "journal"}}
{"content": "work 2135, A tunnel address owned by another account is replaced by itself, is\u2026 \u2014 it was parked because: Tesla Tunnelbaum builds it on main; the transportklok address was replaced by hand. journal work resume 2135 picks it up again.", "meta": {"from": "journal"}}
{"content": "fact 9 \u2014 Every public method on a controller becomes a journal command \u2014 The CLI is generated from the controllers: each public method of Controller, or of a typed controller, turns into journal <noun> <method>. A helper added to the base class therefore becomes a command on every type \u2014 which is how journal <type> handled and journal <type> refuse came to exist, from the CRUD funnel and the refusal funnel. An internal helper on a controller is named with a leading underscore, as _shaped and _status already are, or it ships as a command nobody meant.", "meta": {"from": "journal"}}
{"content": "rule 41 \u2014 Keep moving, run the whole suite before every commit, never wait \u2014 The full suite runs in about seven seconds: .venv/bin/python -m pytest -q --timeout=300 -n auto. Run it before every commit instead of picking tests by name. Group rows that sit in the same code into one sitting: write them all, test once, commit once. And never wait, not for a subagent, a build, or an answer you can carry on without. Dispatch it and keep working. If you truly are waiting on something, say so in the work log.", "meta": {"from": "journal"}}
{"content": "Code Commandments \u2014 before you wrap up \u2014 you've changed 2 judged files since th\u2026 \u2014 Code Commandments \u2014 before you wrap up: you've changed 2 judged files since the last commit. Consider running `commandments judge --changes` to confirm they conform, and fix any sin at its SOURCE (don't launder a finding with a default/cast/null-check). This is a one-time nudge for this batch \u2014 if you've already judged, or these changes aren't worth a scan, just say so and carry on.", "meta": {"from": "journal"}}
{"content": "1 new message 17008 - answer by opening your turn with [!reply:17008]", "meta": {"from": "journal"}}
{"content": "1 new message 17009 - answer by opening your turn with [!reply:17009]", "meta": {"from": "journal"}}
{"content": "check 27 passed and 2afaad624 A helper started again in a stopped helper's\u2026 \u2014 check 27 passed and 2afaad624 A helper started again in a stopped helper's environment takes its place, so the stopped row is never listed twice is committed; then ran boot guard: installs, serves and launches claude, codex in 9.1s", "meta": {"from": "journal"}}
{"content": "work 2135, A tunnel address owned by another account is replaced by itself, is\u2026 \u2014 it was parked because: Tesla Tunnelbaum builds it on main; the transportklok address was replaced by hand. journal work resume 2135 picks it up again.; commit 2afaad624 closed to-do 2986 and ended work 2154 \u2014 The rows and the work are done; take the next one.", "meta": {"from": "journal"}}
{"content": "fact 13 \u2014 This live session runs the installed copy in .journal/journal.pyz \u2014 The running journal (server, hooks, CLI) runs from .journal/journal.pyz with its viewer and skills in .journal/src, never from the repo. A change in the repo reaches it only through python3 src/journal.py --root .journal upgrade, which packs the zip again. A commit alone changes nothing that is running.", "meta": {"from": "journal"}}
{"content": "waiting: 1 unread message 17012", "meta": {"from": "journal"}}
{"content": "helper 99, Massimo Nameright, reported in message 17014 \u2014 read it, then journal helper finish 99 once its work is taken or dropped; suggestion 12 completed", "meta": {"from": "journal"}}
{"content": "work 2135, A tunnel address owned by another account is replaced by itself, is\u2026 \u2014 it was parked because: Tesla Tunnelbaum builds it on main; the transportklok address was replaced by hand. journal work resume 2135 picks it up again.; rule 49 \u2014 A dialog whose content grows keeps one fixed height, and its content\u2026 \u2014 Message 5361, after asking more than once: a dialog that shows output as it arrives (install, update, logs) opens at its final height and never jumps; only its content scrolls.; 1 new message 17016 - answer by opening your turn with [!reply:17016]; message 17016 updated", "meta": {"from": "journal"}}
{"content": "waiting: 1 unread todo 3014", "meta": {"from": "journal"}}
{"content": "helper 97, Nikola Keepalive, reported in message 17031 \u2014 read it, then journal helper finish 97 once its work is taken or dropped", "meta": {"from": "journal"}}
{"content": "check 27 failed, nothing was committed \u2014 check 27 failed, nothing was committed bringing up nodes... bringing up nodes... ........................................................................ [ 14%] ........................................................................ [ 29%] ........................................................................ [ 44%] ........................................................................ [ 59%] ........................................................................ [ 74%] ........................................................................ [ 89%] ......................................F..............                    [100%] =================================== FAILURES =================================== ___________ test_the_viewer_answers_every_state_in_a_browser[tunnel] ___________ [gw7] darwin -- Python 3.14.7 /Users/jessegall/projects/agent-journal/.venv/bin/python scratch_viewer = Scratch(url='http://127.0.0.1:56488/', root=PosixPath('/private/var/folders/jw/5_sm4hg92x70kql0hrg4w54c0000gn/T/pytest-of-jessegall/pytest-1851/popen-gw7/viewer0/Project builds/.journal')) script = 'tunnel' @needs_node_modules @pytest.mark.parametrize(\"script\", sorted(path.stem for path in (WEB / \"browser\").glob(\"*.mjs\") if path.stem not in HELPERS)) def test_the_viewer_answers_every_state_in_a_browser(scratch_viewer, script): env = {**os.environ, \"JOURNAL_SCRATCH_ROOT\": str(scratch_viewer.root), \"JOURNAL_PYTHON\": sys.executable} run = subprocess.run([\"node\", f\"browser/{script}.mjs\", scratch_viewer.url], cwd=WEB, env=env, capture_output=True, text=True, timeout=SCENARIOS_WAIT) assert run.returncode == 0, run.stderr[-2000:] >       assert json.loads(run.stdout.strip().splitlines()[-1]) == {} E       AssertionError: assert {'an Accept o...ble\\x1b[22m '} == {} E E         Left contains 1 more item: E         {'an Accept or a Deny the server refuses shows why and leaves the share waiting': 'locator.waitFor: ' E                                                                                           'Timeout ' E                                                                                           '6000ms ' E                                                                                           'exceeded. ' E                                                                                           'Call '... E E         ...Full output truncated (12 lines hidden), use '-vv' to show tests/test_the_viewer.py:80: AssertionError =========================== short test summary info ============================ FAILED tests/test_the_viewer.py::test_the_viewer_answers_every_state_in_a_browser[tunnel] 1 failed, 484 passed in 203.07s (0:03:23)", "meta": {"from": "journal"}}
{"content": "helper 98, Claude Netwright, reported in message 17034 \u2014 read it, then journal helper finish 98 once its work is taken or dropped", "meta": {"from": "journal"}}
{"content": "Code Commandments \u2014 before you wrap up \u2014 you've changed 12 judged files since t\u2026 \u2014 Code Commandments \u2014 before you wrap up: you've changed 12 judged files since the last commit. Consider running `commandments judge --changes` to confirm they conform, and fix any sin at its SOURCE (don't launder a finding with a default/cast/null-check). This is a one-time nudge for this batch \u2014 if you've already judged, or these changes aren't worth a scan, just say so and carry on.", "meta": {"from": "journal"}}
{"content": "1 new message 17038 - answer by opening your turn with [!reply:17038]", "meta": {"from": "journal"}}
{"content": "1 new message 17039 - answer by opening your turn with [!reply:17039]", "meta": {"from": "journal"}}
{"content": "1 new message 17040 - answer by opening your turn with [!reply:17040]", "meta": {"from": "journal"}}
{"content": "check 27 passed and 202b9c759 Settings gets a Services tab, a group drawn\u2026 \u2014 check 27 passed and 202b9c759 Settings gets a Services tab, a group drawn without a heading stays out of the side list, the transcript's rows are padded, and a peek of an unknown type no longer throws is committed; then ran boot guard: installs, serves and launches claude, codex in 7.2s", "meta": {"from": "journal"}}
{"content": "work 2135, A tunnel address owned by another account is replaced by itself, is\u2026 \u2014 it was parked because: Tesla Tunnelbaum builds it on main; the transportklok address was replaced by hand. journal work resume 2135 picks it up again.; commit 202b9c759 closed to-do 3014 and ended work 2157 \u2014 The rows and the work are done; take the next one.; fact 27 \u2014 Running src/journal.py against the live .journal root starts a\u2026 \u2014 Seen 2026-10-01: with VERSION bumped in the tree, src/journal.py --root .journal saw the live server as another build and started a new one on a new port (8431, 8432), and the user's tabs kept losing connection. Run source builds against a throwaway or demo root (~/projects/demo-crumb/.journal), never the live one, until the release is installed.", "meta": {"from": "journal"}}
{"content": "1 new message 17042 - answer by opening your turn with [!reply:17042]", "meta": {"from": "journal"}}
{"content": "journal-collections, journal-memory, journal-organization\u2026 \u2014 load one again when you next need it; only the every-start skills are held for", "meta": {"from": "journal"}}
{"content": "the todo tag does this in one step \u2014 [!todo=\"the title\"] files it with the turn as its brief; it runs only when it opens the last text of your turn", "meta": {"from": "journal"}}
{"content": "helper 97, Nikola Keepalive, reported in message 17043 \u2014 read it, then journal helper finish 97 once its work is taken or dropped", "meta": {"from": "journal"}}
{"content": "work 2135, A tunnel address owned by another account is replaced by itself, is\u2026 \u2014 it was parked because: Tesla Tunnelbaum builds it on main; the transportklok address was replaced by hand. journal work resume 2135 picks it up again.", "meta": {"from": "journal"}}
{"content": "waiting: 1 unread message 17045", "meta": {"from": "journal"}}
{"content": "chat etiquette - a line from the journal is an instruction, not a message\u2026 \u2014 a turn that only handles a journal line needs no words: act on it, or say once in the chat what you wait on, then carry on; what the user needs to know still goes to the chat", "meta": {"from": "journal"}}
{"content": "helper 98, Claude Netwright, reported in message 17047 \u2014 read it, then journal helper finish 98 once its work is taken or dropped", "meta": {"from": "journal"}}
{"content": "1 new comment 2907; todo 3015 commented", "meta": {"from": "journal"}}
{"content": "1 new message 17048 - answer by opening your turn with [!reply:17048]", "meta": {"from": "journal"}}
{"content": "helper 96, Tesla Tunnelbaum, reported in message 17049 \u2014 read it, then journal helper finish 96 once its work is taken or dropped", "meta": {"from": "journal"}}
{"content": "work 2152, A tunnel address owned by another account is replaced by itself, is\u2026 \u2014 it was parked because: Tesla Tunnelbaum is releasing it on main. journal work resume 2152 picks it up again.", "meta": {"from": "journal"}}
{"content": "rule 60 \u2014 A hotfix is done by a dispatched agent in a worktree of main \u2014 Message 16836 (2026-10-06): the orchestrator cut a worktree under .claude/worktrees for a Codex hotfix, its session moved to a new environment and the user's messages stopped reaching it. The user: when working on a branch and a hotfix comes in, create a worktree of main and dispatch an agent to do that work. The orchestrator stays on its branch and in its environment, and never cds into another checkout.", "meta": {"from": "journal"}}
{"content": "fact 20 \u2014 A slim supervisor holds the agent and a worker reloads on every build \u2014 Since 2.118.0 (2026-09-23). src/supervisor.py is standard library only and never reloads: journal claude hands its process over to it (os.execv), and it owns the pty and the agent process, relays the terminal, writes the printed and screen captures, listens on the typist socket, restarts the agent in the same session from a relaunch command written to its runtime folder while a restart is pending, and stops it with escalation while draining the pty (an agent cannot finish exiting on macOS while its output is unread). It starts the worker (src/worker.py, which runs runner/worker.py; engine/worker.py stays as an alias for supervisors started before 2.201) and starts it again whenever it exits: RELOAD on a new build, RELAUNCH to restart the agent, STOP to end, HEAL or a quick crash to roll back a build through journal heal. The worker holds everything else: seating the session, the start-up confirm typed through the typist, services, viewer, update check, check-in, and the one-time relaunch of sessions launched before agents/terminal.py LAUNCH. agents/terminal.py holds only journal-side helpers. The server (serve.py) still runs the engines and re-execs itself on a .py change. When the agent exits, the supervisor runs journal ended, which puts set-aside hooks back and stops the server when no session is left.", "meta": {"from": "journal"}}
{"content": "1 new message 17051 - answer by opening your turn with [!reply:17051]", "meta": {"from": "journal"}}
{"content": "1 new message 17052 - answer by opening your turn with [!reply:17052]", "meta": {"from": "journal"}}
{"content": "1 new message 17053 - answer by opening your turn with [!reply:17053]", "meta": {"from": "journal"}}
{"content": "your last message ran its paragraphs together \u2014 a blank line between parts is what makes a message readable: one thought to a paragraph", "meta": {"from": "journal"}}
{"content": "the todo tag does this in one step \u2014 [!todo=\"the title\"] files it with the turn as its brief; it runs only when it opens the last text of your turn", "meta": {"from": "journal"}}
{"content": "waiting: 1 unread worktree 75", "meta": {"from": "journal"}}
{"content": "1 new message 17055 - answer by opening your turn with [!reply:17055]", "meta": {"from": "journal"}}
{"content": "1 new message 17056 - answer by opening your turn with [!reply:17056]", "meta": {"from": "journal"}}
{"content": "1 new message 17058 - answer by opening your turn with [!reply:17058]", "meta": {"from": "journal"}}
{"content": "answer message 17056 before you write anything \u2014 answer by opening your turn with [!reply:17056]. a reply, a reaction, or journal message processed <n>", "meta": {"from": "journal"}}
{"content": "1 new message 17061 - answer by opening your turn with [!reply:17061]", "meta": {"from": "journal"}}
{"content": "1 new message 17063 - answer by opening your turn with [!reply:17063]", "meta": {"from": "journal"}}
{"content": "the phone's address did not answer 3 times, so its tunnel was restarted", "meta": {"from": "journal"}}
{"content": "work 2160 in hand \u2014 A blocked phase offers later rows, and delegated choices\u2026 \u2014 if this is not what you are doing, end it or park it and start the work you are in; after POST /api/hook/claude hit an error \u2014 journal: after POST /api/hook/claude hit an error and kept going; the last of it is below and the whole of it is in .journal/runtime/engine.log. Fix it, then say so. ValueError: No closing quotation", "meta": {"from": "journal"}}
{"content": "chat etiquette - a line from the journal is an instruction, not a message\u2026 \u2014 a turn that only handles a journal line needs no words: act on it, or say once in the chat what you wait on, then carry on; what the user needs to know still goes to the chat", "meta": {"from": "journal"}}
{"content": "helper 100, Linus Mergewell, reported in message 17065 \u2014 read it, then journal helper finish 100 once its work is taken or dropped", "meta": {"from": "journal"}}
{"content": "auto mode is on and work 2160 stands still while todo 3019 is ready \u2014 if work 2160 waits on the user, decide it yourself when you can; otherwise put the question on its row with journal todo ask, end or park the work, and start todo 3019. Stop only when nothing ready is left.; the journal is ready on main \u2014 say hello in the chat in plain words, so the journal's messages reach you", "meta": {"from": "journal"}}
{"content": "rule 35 \u2014 Write clean code - one funnel per kind of operation, never the same\u2026 \u2014 Every kind of operation has one funnel: one method that creates, one that saves, one that refuses, one that formats. A second method that does the same thing under another name splits the behaviour, and the two drift apart. Before writing a method, search for the one that already does it and extend that. scripts/checks/funnels.py finds bodies written twice.; rule 56 \u2014 Helpers are for work that writes; subagents read, research and design \u2014 The user, message 13464: there must be a clear distinction. A subagent can be dispatched for anything read-only: research, review, design. A helper is for actual work that writes, best in its own worktree when the work is separate. Dieter designing in Claude Design should have been a subagent, not a helper.", "meta": {"from": "journal"}}
{"content": "fact 23 \u2014 Every upgrade brings system sequences and their triggers in line\u2026 \u2014 install.py runs ship_sequences after the migrations on each upgrade, so features/sequences/shipped.py is the whole source: change its wording and the next upgrade updates every journal, no migration needed. Shipped rows carry system=True and are read-only for everyone but SYSTEM (controllers/base.py _shipped).; rule 47 \u2014 The journal sets itself up once, when the server starts, never per\u2026 \u2014 Messages 2220 and 2224. Discovering features and their handlers, seating the feature rows and the rename sweep happen once, at server boot, and again only when a feature is switched on or off, a plugin changes or an environment is added: features.load keeps a set-up generation per journal (SEATED) and redoes the work only when that generation moves. A command, a request or a hook uses what is already there; nothing in their path may rediscover handlers or rescan folders. A cost that repeats per call is a bug to fix, not a budget to raise.", "meta": {"from": "journal"}}
{"content": "fact 9 \u2014 Every public method on a controller becomes a journal command \u2014 The CLI is generated from the controllers: each public method of Controller, or of a typed controller, turns into journal <noun> <method>. A helper added to the base class therefore becomes a command on every type \u2014 which is how journal <type> handled and journal <type> refuse came to exist, from the CRUD funnel and the refusal funnel. An internal helper on a controller is named with a leading underscore, as _shaped and _status already are, or it ships as a command nobody meant.", "meta": {"from": "journal"}}
{"content": "fact 24 \u2014 An answer followed by tool calls can be missing from Claude's\u2026 \u2014 Seen 2026-09-24 for messages 9391-9404: text blocks opening with [!reply:n] that were followed by tool calls never appeared in the session's jsonl (only thinking and tool_use rows did), so the journal never saw them and the replies were lost. When a turn goes on after answering, send the answer with journal message reply <n> \"<text>\" instead of the tag.", "meta": {"from": "journal"}}
{"content": "rule 54 \u2014 Settings and feature switches are read at boot and on change, never\u2026 \u2014 The user, message 13349: the application boots, determines every feature and setting once, and re-evaluates only when something changes, such as a setting or a plugin. Never lazy-load settings.", "meta": {"from": "journal"}}
{"content": "check 27 passed and 851bb4786 A blocked plan phase offers the rows of every\u2026 \u2014 check 27 passed and 851bb4786 A blocked plan phase offers the rows of every later phase, and the agent decides what the user delegated is committed; then ran boot guard: installs, serves and launches claude, codex in 5.8s", "meta": {"from": "journal"}}
{"content": "check 27 passed and 3ba3594c8 A failing check reaches the agent even while it\u2026 \u2014 check 27 passed and 3ba3594c8 A failing check reaches the agent even while it waits, and is told again only when what it reports changes is committed; then ran boot guard: installs, serves and launches claude, codex in 5.8s", "meta": {"from": "journal"}}
{"content": "commit 3ba3594c8 closed to-do 3019 and ended work 2161 \u2014 The rows and the work are done; take the next one.; commit 851bb4786 closed to-do 3020 \u2014 The rows and the work are done; take the next one.", "meta": {"from": "journal"}}
{"content": "fact 31 \u2014 The overnight branch may be merged once every to-do is done and all\u2026 \u2014 Messages 16886 and 17009 (2026-10-06): the user said to keep working the to-do list on overnight-refactor; when every to-do item is finished and the whole suite is green, the agent may merge the pull request into main, then release a new minor version (message 17008). This is the user's go for rule 57's 'before its pull request is approved'. Until both hold, nothing of the branch goes to main except the hotfixes the user asks for.; rule 37 \u2014 Close every to-do explicitly with todo done or a Journal commit\u2026 \u2014 Ending work does not close its row. A to-do is closed by journal todo done <n> --how, or by a commit whose message carries Journal: todos done <n> at column 0, several numbers separated by commas. A row left open after its work landed misleads the next session and auto mode.", "meta": {"from": "journal"}}
{"content": "fact 13 \u2014 This live session runs the installed copy in .journal/journal.pyz \u2014 The running journal (server, hooks, CLI) runs from .journal/journal.pyz with its viewer and skills in .journal/src, never from the repo. A change in the repo reaches it only through python3 src/journal.py --root .journal upgrade, which packs the zip again. A commit alone changes nothing that is running.", "meta": {"from": "journal"}}
{"content": "your message 17075 names 3018 without saying what they are \u2014 put the type before each number, like message 1712 or to-do 644, so the chat links it: journal message edit 17075 \"<the text>\"", "meta": {"from": "journal"}}
{"content": "rule 46 \u2014 Only commit and push once the whole journal is proven to boot \u2014 Messages 2178 and 2179. A release that has not been started for real can crash every project that installs it, as 2.78.3 did for Codex and 2.84.0 did to project records. Before every commit and push: the full suite passes, including tests/test_it_boots.py, which installs a packed copy into a fresh project, launches Claude and Codex from it, writes a project record, upgrades again and checks the record survives. When a change touches launching, installing or upgrading, also start a real journal in a scratch project and close it properly afterwards, leaving no process behind.; rule 55 \u2014 Always dispatch Codex helpers on gpt-6-sol \u2014 The user's word, message 13431: switch the codex agents to GPT-6-Sol and make it their default. ~/.codex/config.toml names it as the default model too.", "meta": {"from": "journal"}}
{"content": "todo 2989, The phone dialog says Connected as soon as the phone scans the\u2026 \u2014 it is blocked because: Tesla Tunnelbaum takes it after 2.249.9 is out (report 82). If it is not any more, journal todo unblock 2989. If it waits on a person or a decision, make it a question to them: journal todo ask 2989 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 2984, Close GitHub issue 4 once helpers can start in a nested checkout\u2026 \u2014 it is blocked because: waits for the overnight branch to be released. If it is not any more, journal todo unblock 2984. If it waits on a person or a decision, make it a question to them: journal todo ask 2984 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 3001, Logging in finishes the job and the tunnel comes up, is still\u2026 \u2014 it is blocked because: Tesla Tunnelbaum takes it after 2.249.9 is out (report 82). If it is not any more, journal todo unblock 3001. If it waits on a person or a decision, make it a question to them: journal todo ask 3001 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 3002, A first start checks the address is ours, silently, is still\u2026 \u2014 it is blocked because: Tesla Tunnelbaum takes it after 2.249.9 is out (report 82). If it is not any more, journal todo unblock 3002. If it waits on a person or a decision, make it a question to them: journal todo ask 3002 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 3003, Logging out stops the tunnel and an expired account says so, is\u2026 \u2014 it is blocked because: Tesla Tunnelbaum takes it after 2.249.9 is out (report 82). If it is not any more, journal todo unblock 3003. If it waits on a person or a decision, make it a question to them: journal todo ask 3003 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 3004, The same project on two machines does not fight over one address\u2026 \u2014 it is blocked because: Tesla Tunnelbaum takes it after 2.249.9 is out (report 82). If it is not any more, journal todo unblock 3004. If it waits on a person or a decision, make it a question to them: journal todo ask 3004 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 3005, Releasing the journal's own address asks first, and old names are\u2026 \u2014 it is blocked because: Tesla Tunnelbaum takes it after 2.249.9 is out (report 82). If it is not any more, journal todo unblock 3005. If it waits on a person or a decision, make it a question to them: journal todo ask 3005 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 3006, An unreadable sharing.json is repaired before it is replaced, is\u2026 \u2014 it is blocked because: Tesla Tunnelbaum takes it after 2.249.9 is out (report 82). If it is not any more, journal todo unblock 3006. If it waits on a person or a decision, make it a question to them: journal todo ask 3006 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 3008, A fresh machine can find its tunler server without being told, is\u2026 \u2014 it is blocked because: Tesla Tunnelbaum takes it after 2.249.9 is out (report 82). If it is not any more, journal todo unblock 3008. If it waits on a person or a decision, make it a question to them: journal todo ask 3008 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 3009, Installing tunler verifies the binary before it replaces one, is\u2026 \u2014 it is blocked because: Tesla Tunnelbaum takes it after 2.249.9 is out (report 82). If it is not any more, journal todo unblock 3009. If it waits on a person or a decision, make it a question to them: journal todo ask 3009 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 3010, tunler is found wherever it is installed, is still blocked - is it\u2026 \u2014 it is blocked because: Tesla Tunnelbaum takes it after 2.249.9 is out (report 82). If it is not any more, journal todo unblock 3010. If it waits on a person or a decision, make it a question to them: journal todo ask 3010 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 3011, An old tunler, the wrong architecture or a macOS block is named and\u2026 \u2014 it is blocked because: Tesla Tunnelbaum takes it after 2.249.9 is out (report 82). If it is not any more, journal todo unblock 3011. If it waits on a person or a decision, make it a question to them: journal todo ask 3011 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 3012, The phone dialog names the cause and offers the fix, is still\u2026 \u2014 it is blocked because: Tesla Tunnelbaum takes it after 2.249.9 is out (report 82). If it is not any more, journal todo unblock 3012. If it waits on a person or a decision, make it a question to them: journal todo ask 3012 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 3013, Every name the viewer navigates by reads like a normal dashboard\u2026 \u2014 it is blocked because: Massimo Nameright (helper) is on it. If it is not any more, journal todo unblock 3013. If it waits on a person or a decision, make it a question to them: journal todo ask 3013 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 3015, A to-do a helper finished waits as done, pending its merge, is\u2026 \u2014 it is blocked because: an idea for after the overnight merge (message 17042). If it is not any more, journal todo unblock 3015. If it waits on a person or a decision, make it a question to them: journal todo ask 3015 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.", "meta": {"from": "journal"}}
{"content": "rule 60 \u2014 A hotfix is done by a dispatched agent in a worktree of main \u2014 Message 16836 (2026-10-06): the orchestrator cut a worktree under .claude/worktrees for a Codex hotfix, its session moved to a new environment and the user's messages stopped reaching it. The user: when working on a branch and a hotfix comes in, create a worktree of main and dispatch an agent to do that work. The orchestrator stays on its branch and in its environment, and never cds into another checkout.; fact 20 \u2014 A slim supervisor holds the agent and a worker reloads on every build \u2014 Since 2.118.0 (2026-09-23). src/supervisor.py is standard library only and never reloads: journal claude hands its process over to it (os.execv), and it owns the pty and the agent process, relays the terminal, writes the printed and screen captures, listens on the typist socket, restarts the agent in the same session from a relaunch command written to its runtime folder while a restart is pending, and stops it with escalation while draining the pty (an agent cannot finish exiting on macOS while its output is unread). It starts the worker (src/worker.py, which runs runner/worker.py; engine/worker.py stays as an alias for supervisors started before 2.201) and starts it again whenever it exits: RELOAD on a new build, RELAUNCH to restart the agent, STOP to end, HEAL or a quick crash to roll back a build through journal heal. The worker holds everything else: seating the session, the start-up confirm typed through the typist, services, viewer, update check, check-in, and the one-time relaunch of sessions launched before agents/terminal.py LAUNCH. agents/terminal.py holds only journal-side helpers. The server (serve.py) still runs the engines and re-execs itself on a .py change. When the agent exits, the supervisor runs journal ended, which puts set-aside hooks back and stops the server when no session is left.; fact 30 \u2014 The tunler server refuses TLS for any subdomain without a tunnel \u2014 Seen 2026-10-04 in the server's docker logs (ssh root@tunler.jessegall.nl, container tunler): 'TLS handshake error ... host \"journal-probe.tunler.jessegall.nl\" not allowed'. A made-up subdomain never answers even when the server is healthy; probe https://tunler.jessegall.nl/ for the server itself. Root SSH to the server works.; rule 45 \u2014 No prose words as names in code - said, says, heard, spoke, told\u2026 \u2014 Messages 1360 and 1698. The user has said more than once that code must not read like prose: a variable, attribute, property or function is named for what it holds or does (text, command, labels, lines), never with a verb from a story. 'says' on the Design type (1360) and 'said = call.said.lower()' in features/recital.py (1698) are the examples. Rule 27 states the naming rule; this one carries the words, so writing one of them whispers it. Before writing a name, ask whether a reader who has never seen the code would know what it holds.; rule 59 \u2014 Every viewer heading and label says plainly what it is about \u2014 The user, messages 16499, 16839, 16844, 16989, 16992 and 16993 (2026-10-06), after 'Where the words count', 'Watch for the words in', 'This project', 'This browser' and 'Stop the journal' as tab names: viewer text reads like Linear, GitHub or Vercel. A place (page, tab, group, sidebar item) is a short noun: Settings, Project, Browser, Services, Updates, Plugins; never 'This project' or a phrase. A button is a verb for what happens: Stop, Install, Copy link, Pause the plan. A heading names what the reader looks at, and its options finish its sentence: 'Trigger when' / 'A word is written'. Plain literal words: no metaphor or whimsy ('kettle on, waiting'), no app speaking as I, none of the journal's internal words (row, hook, nudge, engine, slate). One word for one thing everywhere, sentence case, as short as it can be while clear. Applies to designers' prototypes, helpers' builds, the viewer's JavaScript lists, feature details, and shipped sequence and trigger titles alike.", "meta": {"from": "journal"}}
{"content": "rule 27 \u2014 Name a declaration with the word a reader already knows \u2014 An attribute, a variable or a field gets the ordinary programming word for what it holds, not an evocative one. was, heard and alone were poetry; aliases, notify_actions and urgent_actions are what they are. The test: could a reader who has never seen this codebase guess what it holds from the name alone? Prose belongs in the help text and the abstract, where it is read as prose. This does not license abbreviations \u2014 a plain word in full, not a short one.", "meta": {"from": "journal"}}
{"content": "rule 48 \u2014 The viewer is built from its component library, and pages only\u2026 \u2014 Message 4258. Every visual piece the viewer shows more than once, or that a user would recognise as the same kind of thing (a dialog, a side panel or inspector, a dropdown, a list row, a switch, a button), is one component in web/src/kit, extracted aggressively, and every page composes those components instead of building its own copy. Before writing markup or styles in a page, look for the kit component that already does it and extend it with a prop; a second hand-built version is a bug. The side panel that animated in but not out, while a separate skill panel did both, is the example.", "meta": {"from": "journal"}}
{"content": "rule 41 \u2014 Keep moving, run the whole suite before every commit, never wait \u2014 The full suite runs in about seven seconds: .venv/bin/python -m pytest -q --timeout=300 -n auto. Run it before every commit instead of picking tests by name. Group rows that sit in the same code into one sitting: write them all, test once, commit once. And never wait, not for a subagent, a build, or an answer you can carry on without. Dispatch it and keep working. If you truly are waiting on something, say so in the work log.", "meta": {"from": "journal"}}
{"content": "rule 57 \u2014 Never merge the overnight refactor into main before its pull request\u2026 \u2014 Messages 15005, 15006, 15109, 15110 (2026-10-04): all refactor work goes on branch overnight-refactor and reaches the user as one pull request, which they read in the morning; nothing of it is merged into main until they say so. Hotfixes the user explicitly asks for go to main at once and are merged into the branch.", "meta": {"from": "journal"}}
{"content": "law L3 \u2014 Read narrowly - grep for the line, sed a range, head the file; never\u2026 \u2014 Everything a tool returns stays in the context for good and is paid for on every turn after it. Search before you read, read the range you need, and cap output with grep, head or tail. Read a whole file only when you need all of it.", "meta": {"from": "journal"}}
{"content": "your command ran 33s in the foreground and was moved to the background \u2014 carry on with other work; you are told when it ends. Start a command you expect to take long in the background yourself", "meta": {"from": "journal"}}
{"content": "fact 18 \u2014 cProfile inflates the slow-request profiles about tenfold \u2014 The faults feature writes a profile when a request passes its budget, and the profile is taken with cProfile, which adds per-call overhead. On 2026-09-22 /api/summary profiled at 58ms with 48ms inside Resource.fork's deep copy; with the profiler off the same call ran in 2 to 7ms. Read the profile for where the time goes in relative terms, then time the call with curl before changing anything.; fact 25 \u2014 A designer's install packs the whole tree, half-done server edits\u2026 \u2014 2026-09-25: Eames and Saul run python3 src/journal.py --root .journal upgrade after their viewer builds; it packs every file in src, so a server handler I was halfway through writing went live and raised on every PostToolUse hook. While designers work in parallel, keep server edits whole between tool calls (write and test in the scratchpad first), and reinstall after reverting anything.; rule 38 \u2014 Never change the git branch until the user says so, by name \u2014 The work happens on the branch the user named. That was main until message 5929 and question 80 (2026-09-23), which moved the sins work to the branch sins. Do not create, switch to or merge any other branch unless the user names it in their own words.", "meta": {"from": "journal"}}
{"content": "fact 13 \u2014 This live session runs the installed copy in .journal/journal.pyz \u2014 The running journal (server, hooks, CLI) runs from .journal/journal.pyz with its viewer and skills in .journal/src, never from the repo. A change in the repo reaches it only through python3 src/journal.py --root .journal upgrade, which packs the zip again. A commit alone changes nothing that is running.", "meta": {"from": "journal"}}
{"content": "Code Commandments \u2014 before you wrap up \u2014 you've changed 6 judged files since th\u2026 \u2014 Code Commandments \u2014 before you wrap up: you've changed 6 judged files since the last commit. Consider running `commandments judge --changes` to confirm they conform, and fix any sin at its SOURCE (don't launder a finding with a default/cast/null-check). This is a one-time nudge for this batch \u2014 if you've already judged, or these changes aren't worth a scan, just say so and carry on.", "meta": {"from": "journal"}}
{"content": "check 27 failed, nothing was committed \u2014 check 27 failed, nothing was committed with monkeypatch.context() as patched: >           keeps_the_tunnel_across_upgrades_and_ports_apart(tmp_path, patched) src/features/sharing/test.py:676: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tmp_path = PosixPath('/private/var/folders/jw/5_sm4hg92x70kql0hrg4w54c0000gn/T/pytest-of-jessegall/pytest-1914/popen-gw8/test_the_tunnel_is_watched_by_0') monkeypatch = <_pytest.monkeypatch.MonkeyPatch object at 0x11a1f8c80> def keeps_the_tunnel_across_upgrades_and_ports_apart(tmp_path, monkeypatch): import features from engine import services from engine.keeper import BUILD from features.sharing import services as share_pages features.load() record = fresh() approved_share(record) binary = tmp_path / \"tunler\" binary.write_text(\"#!/bin/sh\\n\") binary.chmod(0o755) monkeypatch.setattr(share_pages, \"tunler\", lambda: str(binary)) builds = [] for journal_build in (\"build-a\", \"build-b\"): monkeypatch.setattr(share_pages, \"current_build\", lambda root, named=journal_build: named) specs = share_pages.share_services(record.root, set()) builds.append(next(spec.env[BUILD] for spec in specs if spec.id == share_pages.TUNNEL)) >       assert builds[0] == builds[1], \"the tunnel's build does not change when the journal's does\" E       AssertionError: the tunnel's build does not change when the journal's does E       assert '/private/var...063:8471:8451' == '/private/var...063:8452:8451' E E         Skipping 153 identical leading characters in diff, use -v to show E         - 1784063:8452:8451 E         ?           ^^ E         + 1784063:8471:8451 E         ?           ^^ src/features/sharing/test.py:570: AssertionError =========================== short test summary info ============================ FAILED src/features/sharing/test.py::test_the_tunnel_is_watched_by_the_share_server_and_repaired_within_seconds 1 failed, 486 passed in 124.56s (0:02:04)", "meta": {"from": "journal"}}
{"content": "your message 17087 names 8452, 8471 without saying what they are \u2014 put the type before each number, like message 1712 or to-do 644, so the chat links it: journal message edit 17087 \"<the text>\"", "meta": {"from": "journal"}}
{"content": "helper 96, Tesla Tunnelbaum, reported in message 17088 \u2014 read it, then journal helper finish 96 once its work is taken or dropped", "meta": {"from": "journal"}}
{"content": "the suite gate for to-do 3018 came back - Wait for the gate process to end\u2026", "meta": {"from": "journal"}}
{"content": "after POST /api/hook/claude hit an error \u2014 journal: after POST /api/hook/claude hit an error and kept going; the last of it is below and the whole of it is in .journal/runtime/engine.log. Fix it, then say so. ValueError: No closing quotation", "meta": {"from": "journal"}}
{"content": "rule 35 \u2014 Write clean code - one funnel per kind of operation, never the same\u2026 \u2014 Every kind of operation has one funnel: one method that creates, one that saves, one that refuses, one that formats. A second method that does the same thing under another name splits the behaviour, and the two drift apart. Before writing a method, search for the one that already does it and extend that. scripts/checks/funnels.py finds bodies written twice.; rule 49 \u2014 A dialog whose content grows keeps one fixed height, and its content\u2026 \u2014 Message 5361, after asking more than once: a dialog that shows output as it arrives (install, update, logs) opens at its final height and never jumps; only its content scrolls.; rule 56 \u2014 Helpers are for work that writes; subagents read, research and design \u2014 The user, message 13464: there must be a clear distinction. A subagent can be dispatched for anything read-only: research, review, design. A helper is for actual work that writes, best in its own worktree when the work is separate. Dieter designing in Claude Design should have been a subagent, not a helper.", "meta": {"from": "journal"}}
{"content": "your chat talked about the journal's workings - \"Reading it\" \u2014 the user sees replies, reactions, pills and reads themselves; say what the work is instead", "meta": {"from": "journal"}}
{"content": "Code Commandments \u2014 before you wrap up \u2014 you've changed 10 judged files since t\u2026 \u2014 Code Commandments \u2014 before you wrap up: you've changed 10 judged files since the last commit. Consider running `commandments judge --changes` to confirm they conform, and fix any sin at its SOURCE (don't launder a finding with a default/cast/null-check). This is a one-time nudge for this batch \u2014 if you've already judged, or these changes aren't worth a scan, just say so and carry on.", "meta": {"from": "journal"}}
{"content": "check 27 failed, nothing was committed \u2014 check 27 failed, nothing was committed setattr(viewer, name, _VIEWER_FUNCTIONS[name]) >       assert not changed, f\"{request.node.nodeid} left engine.viewer.{', '.join(changed)} replaced for every later test\" E       AssertionError: tests/test_it_boots.py::test_a_hook_reaches_a_busy_server_whose_heartbeat_is_late_and_no_second_server_is_started left engine.viewer.available replaced for every later test E       assert not ['available'] tests/conftest.py:127: AssertionError ----------------------------- Captured stderr call ----------------------------- ---------------------------------------- Exception occurred during processing of request from ('127.0.0.1', 60522) Traceback (most recent call last): File \"/opt/homebrew/Cellar/python@3.14/3.14.7/Frameworks/Python.framework/Versions/3.14/lib/python3.14/socketserver.py\", line 318, in _handle_request_noblock self.process_request(request, client_address) ~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^ File \"/opt/homebrew/Cellar/python@3.14/3.14.7/Frameworks/Python.framework/Versions/3.14/lib/python3.14/socketserver.py\", line 349, in process_request self.finish_request(request, client_address) ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^ File \"/opt/homebrew/Cellar/python@3.14/3.14.7/Frameworks/Python.framework/Versions/3.14/lib/python3.14/socketserver.py\", line 362, in finish_request self.RequestHandlerClass(request, client_address, self) ~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File \"/opt/homebrew/Cellar/python@3.14/3.14.7/Frameworks/Python.framework/Versions/3.14/lib/python3.14/socketserver.py\", line 766, in __init__ self.handle() ~~~~~~~~~~~^^ File \"/opt/homebrew/Cellar/python@3.14/3.14.7/Frameworks/Python.framework/Versions/3.14/lib/python3.14/http/server.py\", line 500, in handle self.handle_one_request() ~~~~~~~~~~~~~~~~~~~~~~~^^ File \"/opt/homebrew/Cellar/python@3.14/3.14.7/Frameworks/Python.framework/Versions/3.14/lib/python3.14/http/server.py\", line 488, in handle_one_request method() ~~~~~~^^ File \"/Users/jessegall/projects/agent-journal/tests/test_it_boots.py\", line 840, in do_GET self.wfile.write(body) ~~~~~~~~~~~~~~~~^^^^^^ File \"/opt/homebrew/Cellar/python@3.14/3.14.7/Frameworks/Python.framework/Versions/3.14/lib/python3.14/socketserver.py\", line 845, in write self._sock.sendall(b) ~~~~~~~~~~~~~~~~~~^^^ BrokenPipeError: [Errno 32] Broken pipe ---------------------------------------- =========================== short test summary info ============================ ERROR tests/test_it_boots.py::test_a_second_journal_gets_a_free_viewer_port_and_a_journal_already_served_says_where ERROR tests/test_it_boots.py::test_a_hook_reaches_a_busy_server_whose_heartbeat_is_late_and_no_second_server_is_started 487 passed, 2 errors in 97.62s (0:01:37)", "meta": {"from": "journal"}}
{"content": "the suite gate for to-do 3018, to-do 3016 and Tesla's tunnel work came back\u2026", "meta": {"from": "journal"}}
{"content": "your command ran 34s in the foreground and was moved to the background \u2014 carry on with other work; you are told when it ends. Start a command you expect to take long in the background yourself", "meta": {"from": "journal"}}
{"content": "the boot tests on the conftest fix came back - Undo monkeypatch before the\u2026", "meta": {"from": "journal"}}
{"content": "rule 36 \u2014 Clean, DRY, idiomatic before it is committed, never after it is\u2026 \u2014 The user should never be the one who finds duplication, dead code, a clumsy name or a pattern the codebase does not use. Read the diff before every commit as a reviewer would, and fix what is not clean then, not in a follow-up after a complaint.; rule 39 \u2014 Use only registered exclamation response tags \u2014 A tag like [!reply:12] runs a command, and only the tags in the tags.runs setting are registered. An invented tag does nothing and shows as raw text in the chat. Use the registered ones (reply, log, end, todo, fact, rule) and nothing else.", "meta": {"from": "journal"}}
{"content": "check 27 passed and d54842136 A reply that names a newly filed to-do links it\u2026 \u2014 check 27 passed and d54842136 A reply that names a newly filed to-do links it to the message it answers and a new to-do left unlinked is pointed out once; a command shlex cannot split no longer raises in the hooks; every test runs on ports of its own and outside the caller's session; the address in use is labelled In use is committed; then ran boot guard: installs, serves and launches claude, codex in 6.0s", "meta": {"from": "journal"}}
{"content": "commit d54842136 closed to-do 3018, to-do 3016, to-do 3021 and ended work 2163 \u2014 The rows and the work are done; take the next one.", "meta": {"from": "journal"}}
{"content": "fact 30 \u2014 The tunler server refuses TLS for any subdomain without a tunnel \u2014 Seen 2026-10-04 in the server's docker logs (ssh root@tunler.jessegall.nl, container tunler): 'TLS handshake error ... host \"journal-probe.tunler.jessegall.nl\" not allowed'. A made-up subdomain never answers even when the server is healthy; probe https://tunler.jessegall.nl/ for the server itself. Root SSH to the server works.; fact 27 \u2014 Running src/journal.py against the live .journal root starts a\u2026 \u2014 Seen 2026-10-01: with VERSION bumped in the tree, src/journal.py --root .journal saw the live server as another build and started a new one on a new port (8431, 8432), and the user's tabs kept losing connection. Run source builds against a throwaway or demo root (~/projects/demo-crumb/.journal), never the live one, until the release is installed.", "meta": {"from": "journal"}}
{"content": "journal-messages changed since you loaded them \u2014 load one again when you next need it; only the every-start skills are held for", "meta": {"from": "journal"}}
{"content": "your command ran 34s in the foreground and was moved to the background \u2014 carry on with other work; you are told when it ends. Start a command you expect to take long in the background yourself", "meta": {"from": "journal"}}
{"content": "fact 9 \u2014 Every public method on a controller becomes a journal command \u2014 The CLI is generated from the controllers: each public method of Controller, or of a typed controller, turns into journal <noun> <method>. A helper added to the base class therefore becomes a command on every type \u2014 which is how journal <type> handled and journal <type> refuse came to exist, from the CRUD funnel and the refusal funnel. An internal helper on a controller is named with a leading underscore, as _shaped and _status already are, or it ships as a command nobody meant.", "meta": {"from": "journal"}}
{"content": "fact 13 \u2014 This live session runs the installed copy in .journal/journal.pyz \u2014 The running journal (server, hooks, CLI) runs from .journal/journal.pyz with its viewer and skills in .journal/src, never from the repo. A change in the repo reaches it only through python3 src/journal.py --root .journal upgrade, which packs the zip again. A commit alone changes nothing that is running.", "meta": {"from": "journal"}}
{"content": "your command ran 31s in the foreground and was moved to the background \u2014 carry on with other work; you are told when it ends. Start a command you expect to take long in the background yourself", "meta": {"from": "journal"}}
{"content": "chat etiquette - a line from the journal is an instruction, not a message\u2026 \u2014 a turn that only handles a journal line needs no words: act on it, or say once in the chat what you wait on, then carry on; what the user needs to know still goes to the chat", "meta": {"from": "journal"}}
{"content": "your message 17105 names 404 without saying what they are \u2014 put the type before each number, like message 1712 or to-do 644, so the chat links it: journal message edit 17105 \"<the text>\"", "meta": {"from": "journal"}}
{"content": "fact 23 \u2014 Every upgrade brings system sequences and their triggers in line\u2026 \u2014 install.py runs ship_sequences after the migrations on each upgrade, so features/sequences/shipped.py is the whole source: change its wording and the next upgrade updates every journal, no migration needed. Shipped rows carry system=True and are read-only for everyone but SYSTEM (controllers/base.py _shipped).", "meta": {"from": "journal"}}
{"content": "your chat talked about the journal's workings - \"Reading it\" \u2014 the user sees replies, reactions, pills and reads themselves; say what the work is instead", "meta": {"from": "journal"}}
{"content": "fact 24 \u2014 An answer followed by tool calls can be missing from Claude's\u2026 \u2014 Seen 2026-09-24 for messages 9391-9404: text blocks opening with [!reply:n] that were followed by tool calls never appeared in the session's jsonl (only thinking and tool_use rows did), so the journal never saw them and the replies were lost. When a turn goes on after answering, send the answer with journal message reply <n> \"<text>\" instead of the tag.", "meta": {"from": "journal"}}
{"content": "the todo tag does this in one step \u2014 [!todo=\"the title\"] files it with the turn as its brief; it runs only when it opens the last text of your turn", "meta": {"from": "journal"}}
{"content": "fact 31 \u2014 The overnight branch may be merged once every to-do is done and all\u2026 \u2014 Messages 16886 and 17009 (2026-10-06): the user said to keep working the to-do list on overnight-refactor; when every to-do item is finished and the whole suite is green, the agent may merge the pull request into main, then release a new minor version (message 17008). This is the user's go for rule 57's 'before its pull request is approved'. Until both hold, nothing of the branch goes to main except the hotfixes the user asks for.; rule 46 \u2014 Only commit and push once the whole journal is proven to boot \u2014 Messages 2178 and 2179. A release that has not been started for real can crash every project that installs it, as 2.78.3 did for Codex and 2.84.0 did to project records. Before every commit and push: the full suite passes, including tests/test_it_boots.py, which installs a packed copy into a fresh project, launches Claude and Codex from it, writes a project record, upgrades again and checks the record survives. When a change touches launching, installing or upgrading, also start a real journal in a scratch project and close it properly afterwards, leaving no process behind.", "meta": {"from": "journal"}}
{"content": "fact 20 \u2014 A slim supervisor holds the agent and a worker reloads on every build \u2014 Since 2.118.0 (2026-09-23). src/supervisor.py is standard library only and never reloads: journal claude hands its process over to it (os.execv), and it owns the pty and the agent process, relays the terminal, writes the printed and screen captures, listens on the typist socket, restarts the agent in the same session from a relaunch command written to its runtime folder while a restart is pending, and stops it with escalation while draining the pty (an agent cannot finish exiting on macOS while its output is unread). It starts the worker (src/worker.py, which runs runner/worker.py; engine/worker.py stays as an alias for supervisors started before 2.201) and starts it again whenever it exits: RELOAD on a new build, RELAUNCH to restart the agent, STOP to end, HEAL or a quick crash to roll back a build through journal heal. The worker holds everything else: seating the session, the start-up confirm typed through the typist, services, viewer, update check, check-in, and the one-time relaunch of sessions launched before agents/terminal.py LAUNCH. agents/terminal.py holds only journal-side helpers. The server (serve.py) still runs the engines and re-execs itself on a .py change. When the agent exits, the supervisor runs journal ended, which puts set-aside hooks back and stops the server when no session is left.; fact 25 \u2014 A designer's install packs the whole tree, half-done server edits\u2026 \u2014 2026-09-25: Eames and Saul run python3 src/journal.py --root .journal upgrade after their viewer builds; it packs every file in src, so a server handler I was halfway through writing went live and raised on every PostToolUse hook. While designers work in parallel, keep server edits whole between tool calls (write and test in the scratchpad first), and reinstall after reverting anything.; rule 45 \u2014 No prose words as names in code - said, says, heard, spoke, told\u2026 \u2014 Messages 1360 and 1698. The user has said more than once that code must not read like prose: a variable, attribute, property or function is named for what it holds or does (text, command, labels, lines), never with a verb from a story. 'says' on the Design type (1360) and 'said = call.said.lower()' in features/recital.py (1698) are the examples. Rule 27 states the naming rule; this one carries the words, so writing one of them whispers it. Before writing a name, ask whether a reader who has never seen the code would know what it holds.; rule 54 \u2014 Settings and feature switches are read at boot and on change, never\u2026 \u2014 The user, message 13349: the application boots, determines every feature and setting once, and re-evaluates only when something changes, such as a setting or a plugin. Never lazy-load settings.; rule 55 \u2014 Always dispatch Codex helpers on gpt-6-sol \u2014 The user's word, message 13431: switch the codex agents to GPT-6-Sol and make it their default. ~/.codex/config.toml names it as the default model too.", "meta": {"from": "journal"}}
{"content": "Code Commandments \u2014 before you wrap up \u2014 you've changed 2 judged files since th\u2026 \u2014 Code Commandments \u2014 before you wrap up: you've changed 2 judged files since the last commit. Consider running `commandments judge --changes` to confirm they conform, and fix any sin at its SOURCE (don't launder a finding with a default/cast/null-check). This is a one-time nudge for this batch \u2014 if you've already judged, or these changes aren't worth a scan, just say so and carry on.", "meta": {"from": "journal"}}
{"content": "check 27 passed and 4508c3d40 The tunnel cause says the tunnel is open when\u2026 \u2014 check 27 passed and 4508c3d40 The tunnel cause says the tunnel is open when its address answers, never that it does not answer yet is committed; then ran boot guard: installs, serves and launches claude, codex in 5.4s", "meta": {"from": "journal"}}
{"content": "the suite gate for to-do 3022, before the merge and release came back - Wait\u2026", "meta": {"from": "journal"}}
{"content": "check 27 passed and ea8a350a5 2.252.0 - the overnight refactor lands, and the\u2026 \u2014 check 27 passed and ea8a350a5 2.252.0: the overnight refactor lands, and the phone tunnel keeps itself up is committed; then ran boot guard: installs, serves and launches claude, codex in 5.5s", "meta": {"from": "journal"}}
{"content": "fact 30 \u2014 The tunler server refuses TLS for any subdomain without a tunnel \u2014 Seen 2026-10-04 in the server's docker logs (ssh root@tunler.jessegall.nl, container tunler): 'TLS handshake error ... host \"journal-probe.tunler.jessegall.nl\" not allowed'. A made-up subdomain never answers even when the server is healthy; probe https://tunler.jessegall.nl/ for the server itself. Root SSH to the server works.", "meta": {"from": "journal"}}
{"content": "fact 27 \u2014 Running src/journal.py against the live .journal root starts a\u2026 \u2014 Seen 2026-10-01: with VERSION bumped in the tree, src/journal.py --root .journal saw the live server as another build and started a new one on a new port (8431, 8432), and the user's tabs kept losing connection. Run source builds against a throwaway or demo root (~/projects/demo-crumb/.journal), never the live one, until the release is installed.; rule 57 \u2014 Never merge the overnight refactor into main before its pull request\u2026 \u2014 Messages 15005, 15006, 15109, 15110 (2026-10-04): all refactor work goes on branch overnight-refactor and reaches the user as one pull request, which they read in the morning; nothing of it is merged into main until they say so. Hotfixes the user explicitly asks for go to main at once and are merged into the branch.", "meta": {"from": "journal"}}
{"content": "law L5 \u2014 Every subagent dispatch names the agent - a human name, a little\u2026 \u2014 A name is how the user and the chat tell subagents apart and how they are messaged later; an id or a task line is not a name. Start the dispatch's description with the name, a colon, then the task, such as \"Dr. Einstein: profile the slow hooks\" or \"Coco Rams: draw the plan card\". A designer can borrow from famous designers, a researcher from famous scientists, mixed up for fun.", "meta": {"from": "journal"}}
{"content": "rule 37 \u2014 Close every to-do explicitly with todo done or a Journal commit\u2026 \u2014 Ending work does not close its row. A to-do is closed by journal todo done <n> --how, or by a commit whose message carries Journal: todos done <n> at column 0, several numbers separated by commas. A row left open after its work landed misleads the next session and auto mode.", "meta": {"from": "journal"}}
{"content": "your last message offers choices in prose \u2014 ask through journal question ask \"<one line>\" --set options='[{\"title\": \u2026, \"description\": \u2026}]' --set pick=<n>, so the viewer renders it; your writes wait until you do", "meta": {"from": "journal"}}
{"content": "rule 27 \u2014 Name a declaration with the word a reader already knows \u2014 An attribute, a variable or a field gets the ordinary programming word for what it holds, not an evocative one. was, heard and alone were poetry; aliases, notify_actions and urgent_actions are what they are. The test: could a reader who has never seen this codebase guess what it holds from the name alone? Prose belongs in the help text and the abstract, where it is read as prose. This does not license abbreviations \u2014 a plain word in full, not a short one.; rule 41 \u2014 Keep moving, run the whole suite before every commit, never wait \u2014 The full suite runs in about seven seconds: .venv/bin/python -m pytest -q --timeout=300 -n auto. Run it before every commit instead of picking tests by name. Group rows that sit in the same code into one sitting: write them all, test once, commit once. And never wait, not for a subagent, a build, or an answer you can carry on without. Dispatch it and keep working. If you truly are waiting on something, say so in the work log.; rule 48 \u2014 The viewer is built from its component library, and pages only\u2026 \u2014 Message 4258. Every visual piece the viewer shows more than once, or that a user would recognise as the same kind of thing (a dialog, a side panel or inspector, a dropdown, a list row, a switch, a button), is one component in web/src/kit, extracted aggressively, and every page composes those components instead of building its own copy. Before writing markup or styles in a page, look for the kit component that already does it and extend it with a prop; a second hand-built version is a bug. The side panel that animated in but not out, while a separate skill panel did both, is the example.", "meta": {"from": "journal"}}
{"content": "question 203 completed", "meta": {"from": "journal"}}
{"content": "law L3 \u2014 Read narrowly - grep for the line, sed a range, head the file; never\u2026 \u2014 Everything a tool returns stays in the context for good and is paid for on every turn after it. Search before you read, read the range you need, and cap output with grep, head or tail. Read a whole file only when you need all of it.", "meta": {"from": "journal"}}
{"content": "rule 38 \u2014 Never change the git branch until the user says so, by name \u2014 The work happens on the branch the user named. That was main until message 5929 and question 80 (2026-09-23), which moved the sins work to the branch sins. Do not create, switch to or merge any other branch unless the user names it in their own words.; rule 60 \u2014 A hotfix is done by a dispatched agent in a worktree of main \u2014 Message 16836 (2026-10-06): the orchestrator cut a worktree under .claude/worktrees for a Codex hotfix, its session moved to a new environment and the user's messages stopped reaching it. The user: when working on a branch and a hotfix comes in, create a worktree of main and dispatch an agent to do that work. The orchestrator stays on its branch and in its environment, and never cds into another checkout.", "meta": {"from": "journal"}}
{"content": "1 new message 17118 - answer by opening your turn with [!reply:17118]", "meta": {"from": "journal"}}
{"content": "Is rule 61 a ruling for the whole project? \u2014 rule 61, \"Features wait as pull requests until approved; only hotfixes merge at once\", binds every environment of the project. Keep it only if it is a ruling for all of them, worded as one (\"Always ...\", \"Never ...\"). If it is about this environment or its current work, strike it with journal rule strike 61 --how \"<why>\" and file it here as a fact or a reminder instead.", "meta": {"from": "journal"}}
{"content": "rule 61 \u2014 Features wait as pull requests until approved; only hotfixes merge\u2026 \u2014 Message 17118 (2026-10-06), after the overnight refactor merged as 2.252.0: start new work in a new branch, do not merge, write the pull request. Every pull request or new feature is parked until the user approves it. Hotfixes can be merged into main immediately (by a dispatched agent in a worktree of main, rule 60).", "meta": {"from": "journal"}}
{"content": "fact 9 \u2014 Every public method on a controller becomes a journal command \u2014 The CLI is generated from the controllers: each public method of Controller, or of a typed controller, turns into journal <noun> <method>. A helper added to the base class therefore becomes a command on every type \u2014 which is how journal <type> handled and journal <type> refuse came to exist, from the CRUD funnel and the refusal funnel. An internal helper on a controller is named with a leading underscore, as _shaped and _status already are, or it ships as a command nobody meant.", "meta": {"from": "journal"}}
{"content": "rule 40 \u2014 A feature is named for what it is, never for its machinery \u2014 Messages 599, 600 and 703. A feature is a capability the user would name and would think of switching off. File tracking, a write gate, a phrase bank, a tree diff are services used inside a feature, not features of their own: they live in the feature they serve. Before adding a directory under features/, say what the user would call it; if the answer names a mechanism, it belongs inside something else. Report 16 holds the grouping this implies.", "meta": {"from": "journal"}}
{"content": "rule 35 \u2014 Write clean code - one funnel per kind of operation, never the same\u2026 \u2014 Every kind of operation has one funnel: one method that creates, one that saves, one that refuses, one that formats. A second method that does the same thing under another name splits the behaviour, and the two drift apart. Before writing a method, search for the one that already does it and extend that. scripts/checks/funnels.py finds bodies written twice.; rule 56 \u2014 Helpers are for work that writes; subagents read, research and design \u2014 The user, message 13464: there must be a clear distinction. A subagent can be dispatched for anything read-only: research, review, design. A helper is for actual work that writes, best in its own worktree when the work is separate. Dieter designing in Claude Design should have been a subagent, not a helper.", "meta": {"from": "journal"}}
{"content": "fact 23 \u2014 Every upgrade brings system sequences and their triggers in line\u2026 \u2014 install.py runs ship_sequences after the migrations on each upgrade, so features/sequences/shipped.py is the whole source: change its wording and the next upgrade updates every journal, no migration needed. Shipped rows carry system=True and are read-only for everyone but SYSTEM (controllers/base.py _shipped).; rule 42 \u2014 Every user-facing text passes the formatters before it leaves the\u2026 \u2014 Not only a brief. A title, an abstract, an outcome and every section body are read by a person, so each goes through the same formatters on its way to the viewer \u2014 chat turns, activity items, to-do rows, inspector pages, docs alike. One field formatted out of five is not a rule, it is an accident, and it is how a raw tag ended up in the activity list after the tags feature had been stripping them for weeks. When a new field carries words a person reads, it joins the list in the same place.", "meta": {"from": "journal"}}
{"content": "fact 31 \u2014 The overnight branch may be merged once every to-do is done and all\u2026 \u2014 Messages 16886 and 17009 (2026-10-06): the user said to keep working the to-do list on overnight-refactor; when every to-do item is finished and the whole suite is green, the agent may merge the pull request into main, then release a new minor version (message 17008). This is the user's go for rule 57's 'before its pull request is approved'. Until both hold, nothing of the branch goes to main except the hotfixes the user asks for.", "meta": {"from": "journal"}}
{"content": "the phone's address did not answer 1 times, so its tunnel was restarted", "meta": {"from": "journal"}}
{"content": "work 2165 in hand \u2014 A to-do a helper finished waits as done, pending its merge \u2014 if this is not what you are doing, end it or park it and start the work you are in; rule 36 \u2014 Clean, DRY, idiomatic before it is committed, never after it is\u2026 \u2014 The user should never be the one who finds duplication, dead code, a clumsy name or a pattern the codebase does not use. Read the diff before every commit as a reviewer would, and fix what is not clean then, not in a follow-up after a complaint.; rule 47 \u2014 The journal sets itself up once, when the server starts, never per\u2026 \u2014 Messages 2220 and 2224. Discovering features and their handlers, seating the feature rows and the rename sweep happen once, at server boot, and again only when a feature is switched on or off, a plugin changes or an environment is added: features.load keeps a set-up generation per journal (SEATED) and redoes the work only when that generation moves. A command, a request or a hook uses what is already there; nothing in their path may rediscover handlers or rescan folders. A cost that repeats per call is a bug to fix, not a budget to raise.", "meta": {"from": "journal"}}
{"content": "rule 50 \u2014 Everything the user does is doable in the viewer \u2014 Message 6710 (2026-09-23): the user never uses the CLI, only the UI; everything should be doable from the viewer. The journal commands are for agents; any action meant for the user (making boards, confirming, accepting, hosting, watching an agent) needs its place in the viewer.", "meta": {"from": "journal"}}
{"content": "your command ran 33s in the foreground and was moved to the background \u2014 carry on with other work; you are told when it ends. Start a command you expect to take long in the background yourself", "meta": {"from": "journal"}}
{"content": "Code Commandments \u2014 before you wrap up \u2014 you've changed 10 judged files since t\u2026 \u2014 Code Commandments \u2014 before you wrap up: you've changed 10 judged files since the last commit. Consider running `commandments judge --changes` to confirm they conform, and fix any sin at its SOURCE (don't launder a finding with a default/cast/null-check). This is a one-time nudge for this batch \u2014 if you've already judged, or these changes aren't worth a scan, just say so and carry on.", "meta": {"from": "journal"}}
{"content": "check 27 passed and 86923047f To-dos handed to a helper are its alone, wait as\u2026 \u2014 check 27 passed and 86923047f To-dos handed to a helper are its alone, wait as done until its work is taken, and come back when it stops or crashes is committed; then ran boot guard: installs, serves and launches claude, codex in 6.7s remote: remote: Create a pull request for 'helper-todos-wait-for-merge' on GitHub by visiting: remote:      https://github.com/jessegall/agent-journal/pull/new/helper-todos-wait-for-merge remote:", "meta": {"from": "journal"}}
{"content": "commit 86923047f closed to-do 3015 and ended work 2165 \u2014 The rows and the work are done; take the next one.", "meta": {"from": "journal"}}
{"content": "1 new message 17135 - answer by opening your turn with [!reply:17135]", "meta": {"from": "journal"}}
{"content": "fact 24 \u2014 An answer followed by tool calls can be missing from Claude's\u2026 \u2014 Seen 2026-09-24 for messages 9391-9404: text blocks opening with [!reply:n] that were followed by tool calls never appeared in the session's jsonl (only thinking and tool_use rows did), so the journal never saw them and the replies were lost. When a turn goes on after answering, send the answer with journal message reply <n> \"<text>\" instead of the tag.", "meta": {"from": "journal"}}
{"content": "fact 28 \u2014 The designer agent type exists, so design work goes to a subagent \u2014 Since 2026-10-01 .claude/agents/designer.md (Dieter, Opus, Claude Design tools, read-only on the repository) is an agent type; rule 56 says design is a subagent's job, never a helper's.; rule 58 \u2014 The user tests a design's clickable prototype and approves it before\u2026 \u2014 Message 15725 (2026-10-05): 'ask Dieter to create an interactive prototype! I want to test it first and give feedback before giving it my go', and remove any fact or rule that conflicts. Replaces rule 53's 'the designer decides'. The designer still runs one critique round (messages 12800, 13475) and revises before showing the prototype; then the user clicks through it, gives feedback, and only the user's go starts the build.", "meta": {"from": "journal"}}
{"content": "1 new message 17136 - answer by opening your turn with [!reply:17136]", "meta": {"from": "journal"}}
{"content": "1 new message 17137 - answer by opening your turn with [!reply:17137]", "meta": {"from": "journal"}}
{"content": "Code Commandments \u2014 the files changed since the last check (`types.py`, `todos.\u2026 \u2014 Code Commandments \u2014 the files changed since the last check (`types.py`, `todos.py`) breaks a rule. Fix it now, at its SOURCE, while the code is still in front of you: \u00b7 \u2022 python-member-after-method at /Users/jessegall/projects/agent-journal/src/resources/types.py:79 \u00b7 LOAD the skill `commandments-python-class-layout` before fixing \u2014 load it even if you believe you already have. \u00b7 \u2022 python-blank-string-default at /Users/jessegall/projects/agent-journal/src/controllers/todos.py:23 \u00b7 LOAD the skill `commandments-python-absence` before fixing \u2014 load it even if you believe you already have. \u00b7 Run `commandments info <sin>` if a rule is not one you recognise. This check reads a file at a time, so it is not the whole picture \u2014 `judge` still is.", "meta": {"from": "journal"}}
{"content": "work 2167 in hand \u2014 Review pull request 8 with two agents and merge it when it\u2026 \u2014 if this is not what you are doing, end it or park it and start the work you are in", "meta": {"from": "journal"}}
{"content": "chat etiquette - a line from the journal is an instruction, not a message\u2026 \u2014 a turn that only handles a journal line needs no words: act on it, or say once in the chat what you wait on, then carry on; what the user needs to know still goes to the chat", "meta": {"from": "journal"}}
{"content": "the log tag does this in one step \u2014 [!log:N] makes the turn itself the log entry; it runs only when it opens the last text of your turn", "meta": {"from": "journal"}}
{"content": "Code Commandments \u2014 before you wrap up \u2014 you've changed 10 judged files since t\u2026 \u2014 Code Commandments \u2014 before you wrap up: you've changed 10 judged files since the last commit. Consider running `commandments judge --changes` to confirm they conform, and fix any sin at its SOURCE (don't launder a finding with a default/cast/null-check). This is a one-time nudge for this batch \u2014 if you've already judged, or these changes aren't worth a scan, just say so and carry on.", "meta": {"from": "journal"}}
{"content": "check 27 passed and f6d23a783 2.253.0 - to-dos handed to a helper are its\u2026 \u2014 check 27 passed and f6d23a783 2.253.0: to-dos handed to a helper are its alone; the review findings on pull request 8 are fixed is committed; then ran boot guard: installs, serves and launches claude, codex in 8.5s", "meta": {"from": "journal"}}
{"content": "your command ran 33s in the foreground and was moved to the background \u2014 carry on with other work; you are told when it ends. Start a command you expect to take long in the background yourself", "meta": {"from": "journal"}}
{"content": "Code Commandments \u2014 before you wrap up \u2014 you've changed 4 judged files since th\u2026 \u2014 Code Commandments \u2014 before you wrap up: you've changed 4 judged files since the last commit. Consider running `commandments judge --changes` to confirm they conform, and fix any sin at its SOURCE (don't launder a finding with a default/cast/null-check). This is a one-time nudge for this batch \u2014 if you've already judged, or these changes aren't worth a scan, just say so and carry on.", "meta": {"from": "journal"}}
{"content": "check 27 passed and f898b88ce A helper's waiting row cannot be unmarked by the\u2026 \u2014 check 27 passed and f898b88ce A helper's waiting row cannot be unmarked by the agent, its rows are assigned before it starts and given back if the launch fails, and the last wording points are tidied is committed; then ran boot guard: installs, serves and launches claude, codex in 6.6s", "meta": {"from": "journal"}}
{"content": "the suite gate for the last fixes on pull request 8, then the merge came back\u2026", "meta": {"from": "journal"}}
{"content": "fact 13 \u2014 This live session runs the installed copy in .journal/journal.pyz \u2014 The running journal (server, hooks, CLI) runs from .journal/journal.pyz with its viewer and skills in .journal/src, never from the repo. A change in the repo reaches it only through python3 src/journal.py --root .journal upgrade, which packs the zip again. A commit alone changes nothing that is running.; fact 25 \u2014 A designer's install packs the whole tree, half-done server edits\u2026 \u2014 2026-09-25: Eames and Saul run python3 src/journal.py --root .journal upgrade after their viewer builds; it packs every file in src, so a server handler I was halfway through writing went live and raised on every PostToolUse hook. While designers work in parallel, keep server edits whole between tool calls (write and test in the scratchpad first), and reinstall after reverting anything.; fact 27 \u2014 Running src/journal.py against the live .journal root starts a\u2026 \u2014 Seen 2026-10-01: with VERSION bumped in the tree, src/journal.py --root .journal saw the live server as another build and started a new one on a new port (8431, 8432), and the user's tabs kept losing connection. Run source builds against a throwaway or demo root (~/projects/demo-crumb/.journal), never the live one, until the release is installed.; rule 39 \u2014 Use only registered exclamation response tags \u2014 A tag like [!reply:12] runs a command, and only the tags in the tags.runs setting are registered. An invented tag does nothing and shows as raw text in the chat. Use the registered ones (reply, log, end, todo, fact, rule) and nothing else.", "meta": {"from": "journal"}}
{"content": "todo 3023 next; fact 28 \u2014 The designer agent type exists, so design work goes to a subagent \u2014 Since 2026-10-01 .claude/agents/designer.md (Dieter, Opus, Claude Design tools, read-only on the repository) is an agent type; rule 56 says design is a subagent's job, never a helper's.; rule 60 \u2014 A hotfix is done by a dispatched agent in a worktree of main \u2014 Message 16836 (2026-10-06): the orchestrator cut a worktree under .claude/worktrees for a Codex hotfix, its session moved to a new environment and the user's messages stopped reaching it. The user: when working on a branch and a hotfix comes in, create a worktree of main and dispatch an agent to do that work. The orchestrator stays on its branch and in its environment, and never cds into another checkout.", "meta": {"from": "journal"}}
{"content": "rule 40 \u2014 A feature is named for what it is, never for its machinery \u2014 Messages 599, 600 and 703. A feature is a capability the user would name and would think of switching off. File tracking, a write gate, a phrase bank, a tree diff are services used inside a feature, not features of their own: they live in the feature they serve. Before adding a directory under features/, say what the user would call it; if the answer names a mechanism, it belongs inside something else. Report 16 holds the grouping this implies.", "meta": {"from": "journal"}}
{"content": "your command ran 34s in the foreground and was moved to the background \u2014 carry on with other work; you are told when it ends. Start a command you expect to take long in the background yourself", "meta": {"from": "journal"}}
{"content": "the boot tests under the new coverage config came back - Write the coverage\u2026", "meta": {"from": "journal"}}
{"content": "your command ran 32s in the foreground and was moved to the background \u2014 carry on with other work; you are told when it ends. Start a command you expect to take long in the background yourself", "meta": {"from": "journal"}}
{"content": "reading where the boot tests' coverage data landed came back - See the result\u2026", "meta": {"from": "journal"}}
{"content": "journal.py names 2 files in the project \u2014 write the path so the chat can link it: src/features/journal.py, src/journal.py", "meta": {"from": "journal"}}
{"content": "My earlier `journal.py` means `src/journal.py`, the entry point.", "meta": {"from": "journal"}}
{"content": "fact 9 \u2014 Every public method on a controller becomes a journal command \u2014 The CLI is generated from the controllers: each public method of Controller, or of a typed controller, turns into journal <noun> <method>. A helper added to the base class therefore becomes a command on every type \u2014 which is how journal <type> handled and journal <type> refuse came to exist, from the CRUD funnel and the refusal funnel. An internal helper on a controller is named with a leading underscore, as _shaped and _status already are, or it ships as a command nobody meant.", "meta": {"from": "journal"}}
{"content": "rule 35 \u2014 Write clean code - one funnel per kind of operation, never the same\u2026 \u2014 Every kind of operation has one funnel: one method that creates, one that saves, one that refuses, one that formats. A second method that does the same thing under another name splits the behaviour, and the two drift apart. Before writing a method, search for the one that already does it and extend that. scripts/checks/funnels.py finds bodies written twice.; rule 56 \u2014 Helpers are for work that writes; subagents read, research and design \u2014 The user, message 13464: there must be a clear distinction. A subagent can be dispatched for anything read-only: research, review, design. A helper is for actual work that writes, best in its own worktree when the work is separate. Dieter designing in Claude Design should have been a subagent, not a helper.", "meta": {"from": "journal"}}
{"content": "fact 24 \u2014 An answer followed by tool calls can be missing from Claude's\u2026 \u2014 Seen 2026-09-24 for messages 9391-9404: text blocks opening with [!reply:n] that were followed by tool calls never appeared in the session's jsonl (only thinking and tool_use rows did), so the journal never saw them and the replies were lost. When a turn goes on after answering, send the answer with journal message reply <n> \"<text>\" instead of the tag.", "meta": {"from": "journal"}}
{"content": "your chat talked about the journal's workings - \"Reading it\" \u2014 the user sees replies, reactions, pills and reads themselves; say what the work is instead", "meta": {"from": "journal"}}
{"content": "fact 23 \u2014 Every upgrade brings system sequences and their triggers in line\u2026 \u2014 install.py runs ship_sequences after the migrations on each upgrade, so features/sequences/shipped.py is the whole source: change its wording and the next upgrade updates every journal, no migration needed. Shipped rows carry system=True and are read-only for everyone but SYSTEM (controllers/base.py _shipped).; rule 42 \u2014 Every user-facing text passes the formatters before it leaves the\u2026 \u2014 Not only a brief. A title, an abstract, an outcome and every section body are read by a person, so each goes through the same formatters on its way to the viewer \u2014 chat turns, activity items, to-do rows, inspector pages, docs alike. One field formatted out of five is not a rule, it is an accident, and it is how a raw tag ended up in the activity list after the tags feature had been stripping them for weeks. When a new field carries words a person reads, it joins the list in the same place.", "meta": {"from": "journal"}}
{"content": "check 27 passed and 6a661b884 Test coverage is measured with child processes\u2026 \u2014 check 27 passed and 6a661b884 Test coverage is measured with child processes counted, at 91 percent, and a floor keeps it from falling is committed; then ran boot guard: installs, serves and launches claude, codex in 7.5s remote: remote: Create a pull request for 'test-coverage' on GitHub by visiting: remote:      https://github.com/jessegall/agent-journal/pull/new/test-coverage remote:", "meta": {"from": "journal"}}
{"content": "rule 36 \u2014 Clean, DRY, idiomatic before it is committed, never after it is\u2026 \u2014 The user should never be the one who finds duplication, dead code, a clumsy name or a pattern the codebase does not use. Read the diff before every commit as a reviewer would, and fix what is not clean then, not in a follow-up after a complaint.", "meta": {"from": "journal"}}
{"content": "Code Commandments \u2014 before you wrap up \u2014 you've changed 1 judged file since the\u2026 \u2014 Code Commandments \u2014 before you wrap up: you've changed 1 judged file since the last commit. Consider running `commandments judge --changes` to confirm they conform, and fix any sin at its SOURCE (don't launder a finding with a default/cast/null-check). This is a one-time nudge for this batch \u2014 if you've already judged, or these changes aren't worth a scan, just say so and carry on.", "meta": {"from": "journal"}}
{"content": "check 27 passed and bcd4a0d03 Plugins answering events are tested - by command\u2026 \u2014 check 27 passed and bcd4a0d03 Plugins answering events are tested: by command and by HTTP post, a plugin that keeps failing is named once and left alone a while, and recovery clears it is committed; then ran boot guard: installs, serves and launches claude, codex in 6.0s", "meta": {"from": "journal"}}
{"content": "the plugin host gate, and your choice on pace came back - Wait for the plugin\u2026", "meta": {"from": "journal"}}
{"content": "rule 52 \u2014 A chat mark for something the user did sits on the user's side \u2014 Message 10960 (2026-09-25): marks for the user's own actions, such as answering a question, are right-aligned like the user's messages. A mark is put there by giving its card side=user.", "meta": {"from": "journal"}}
{"content": "a full coverage run that records every missed line came back - Rerun full\u2026", "meta": {"from": "journal"}}
{"content": "rule 47 \u2014 The journal sets itself up once, when the server starts, never per\u2026 \u2014 Messages 2220 and 2224. Discovering features and their handlers, seating the feature rows and the rename sweep happen once, at server boot, and again only when a feature is switched on or off, a plugin changes or an environment is added: features.load keeps a set-up generation per journal (SEATED) and redoes the work only when that generation moves. A command, a request or a hook uses what is already there; nothing in their path may rediscover handlers or rescan folders. A cost that repeats per call is a bug to fix, not a budget to raise.", "meta": {"from": "journal"}}
{"content": "fact 13 \u2014 This live session runs the installed copy in .journal/journal.pyz \u2014 The running journal (server, hooks, CLI) runs from .journal/journal.pyz with its viewer and skills in .journal/src, never from the repo. A change in the repo reaches it only through python3 src/journal.py --root .journal upgrade, which packs the zip again. A commit alone changes nothing that is running.", "meta": {"from": "journal"}}
{"content": "fact 25 \u2014 A designer's install packs the whole tree, half-done server edits\u2026 \u2014 2026-09-25: Eames and Saul run python3 src/journal.py --root .journal upgrade after their viewer builds; it packs every file in src, so a server handler I was halfway through writing went live and raised on every PostToolUse hook. While designers work in parallel, keep server edits whole between tool calls (write and test in the scratchpad first), and reinstall after reverting anything.", "meta": {"from": "journal"}}
{"content": "Code Commandments \u2014 before you wrap up \u2014 you've changed 1 judged file since the\u2026 \u2014 Code Commandments \u2014 before you wrap up: you've changed 1 judged file since the last commit. Consider running `commandments judge --changes` to confirm they conform, and fix any sin at its SOURCE (don't launder a finding with a default/cast/null-check). This is a one-time nudge for this batch \u2014 if you've already judged, or these changes aren't worth a scan, just say so and carry on.", "meta": {"from": "journal"}}
{"content": "check 27 passed and 71e65df89 Every way a plugin manifest can be malformed is\u2026 \u2014 check 27 passed and 71e65df89 Every way a plugin manifest can be malformed is refused in its own words, and the test proves each one is committed; then ran boot guard: installs, serves and launches claude, codex in 5.1s", "meta": {"from": "journal"}}
{"content": "The judge still can't run here, and this change is a test table only.", "meta": {"from": "journal"}}
{"content": "your command ran 34s in the foreground and was moved to the background \u2014 carry on with other work; you are told when it ends. Start a command you expect to take long in the background yourself", "meta": {"from": "journal"}}
{"content": "Code Commandments \u2014 before you wrap up \u2014 you've changed 1 judged file since the\u2026 \u2014 Code Commandments \u2014 before you wrap up: you've changed 1 judged file since the last commit. Consider running `commandments judge --changes` to confirm they conform, and fix any sin at its SOURCE (don't launder a finding with a default/cast/null-check). This is a one-time nudge for this batch \u2014 if you've already judged, or these changes aren't worth a scan, just say so and carry on.", "meta": {"from": "journal"}}
{"content": "check 27 passed and 9fe88ed82 A plugin's install and upgrade show what they\u2026 \u2014 check 27 passed and 9fe88ed82 A plugin's install and upgrade show what they would do first, an upgrade with nothing new says so, and a removed plugin's data can be purged; all tested is committed; then ran boot guard: installs, serves and launches claude, codex in 5.8s", "meta": {"from": "journal"}}
{"content": "The judge can't run on this machine, and the change is a test only.", "meta": {"from": "journal"}}
{"content": "fact 9 \u2014 Every public method on a controller becomes a journal command \u2014 The CLI is generated from the controllers: each public method of Controller, or of a typed controller, turns into journal <noun> <method>. A helper added to the base class therefore becomes a command on every type \u2014 which is how journal <type> handled and journal <type> refuse came to exist, from the CRUD funnel and the refusal funnel. An internal helper on a controller is named with a leading underscore, as _shaped and _status already are, or it ships as a command nobody meant.", "meta": {"from": "journal"}}
{"content": "Code Commandments \u2014 before you wrap up \u2014 you've changed 1 judged file since the\u2026 \u2014 Code Commandments \u2014 before you wrap up: you've changed 1 judged file since the last commit. Consider running `commandments judge --changes` to confirm they conform, and fix any sin at its SOURCE (don't launder a finding with a default/cast/null-check). This is a one-time nudge for this batch \u2014 if you've already judged, or these changes aren't worth a scan, just say so and carry on.", "meta": {"from": "journal"}}
{"content": "chat etiquette - a line from the journal is an instruction, not a message\u2026 \u2014 a turn that only handles a journal line needs no words: act on it, or say once in the chat what you wait on, then carry on; what the user needs to know still goes to the chat", "meta": {"from": "journal"}}
{"content": "check 27 passed and 6fe792042 A service a plugin declares gets its port and\u2026 \u2014 check 27 passed and 6fe792042 A service a plugin declares gets its port and folder filled into its command, and one that stops is told once and cleared when it runs again; tested is committed; then ran boot guard: installs, serves and launches claude, codex in 5.7s", "meta": {"from": "journal"}}
{"content": "the plugin services gate came back - Wait for the plugin services gate\u2026", "meta": {"from": "journal"}}
{"content": "fact 29 \u2014 Codex's transcript records the end of every exec session, polled or\u2026 \u2014 Seen 2026-10-03 in the Passkey rollout (2026-10-02T22-40-17), Codex 0.160: 118 sessions opened (an exec output carrying \"session_id\":N), 118 item_completed events of type CommandExecution with process_id N, status completed or failed, exit_code and completed_at_ms, including the 7 never polled with write_stdin. A run's end comes from the transcript; no process check is needed.", "meta": {"from": "journal"}}
{"content": "law L5 \u2014 Every subagent dispatch names the agent - a human name, a little\u2026 \u2014 A name is how the user and the chat tell subagents apart and how they are messaged later; an id or a task line is not a name. Start the dispatch's description with the name, a colon, then the task, such as \"Dr. Einstein: profile the slow hooks\" or \"Coco Rams: draw the plan card\". A designer can borrow from famous designers, a researcher from famous scientists, mixed up for fun.", "meta": {"from": "journal"}}
{"content": "fact 24 \u2014 An answer followed by tool calls can be missing from Claude's\u2026 \u2014 Seen 2026-09-24 for messages 9391-9404: text blocks opening with [!reply:n] that were followed by tool calls never appeared in the session's jsonl (only thinking and tool_use rows did), so the journal never saw them and the replies were lost. When a turn goes on after answering, send the answer with journal message reply <n> \"<text>\" instead of the tag.", "meta": {"from": "journal"}}
{"content": "rule 50 \u2014 Everything the user does is doable in the viewer \u2014 Message 6710 (2026-09-23): the user never uses the CLI, only the UI; everything should be doable from the viewer. The journal commands are for agents; any action meant for the user (making boards, confirming, accepting, hosting, watching an agent) needs its place in the viewer.; law L3 \u2014 Read narrowly - grep for the line, sed a range, head the file; never\u2026 \u2014 Everything a tool returns stays in the context for good and is paid for on every turn after it. Search before you read, read the range you need, and cap output with grep, head or tail. Read a whole file only when you need all of it.; rule 41 \u2014 Keep moving, run the whole suite before every commit, never wait \u2014 The full suite runs in about seven seconds: .venv/bin/python -m pytest -q --timeout=300 -n auto. Run it before every commit instead of picking tests by name. Group rows that sit in the same code into one sitting: write them all, test once, commit once. And never wait, not for a subagent, a build, or an answer you can carry on without. Dispatch it and keep working. If you truly are waiting on something, say so in the work log.", "meta": {"from": "journal"}}
{"content": "rule 48 \u2014 The viewer is built from its component library, and pages only\u2026 \u2014 Message 4258. Every visual piece the viewer shows more than once, or that a user would recognise as the same kind of thing (a dialog, a side panel or inspector, a dropdown, a list row, a switch, a button), is one component in web/src/kit, extracted aggressively, and every page composes those components instead of building its own copy. Before writing markup or styles in a page, look for the kit component that already does it and extend it with a prop; a second hand-built version is a bug. The side panel that animated in but not out, while a separate skill panel did both, is the example.", "meta": {"from": "journal"}}
{"content": "rule 54 \u2014 Settings and feature switches are read at boot and on change, never\u2026 \u2014 The user, message 13349: the application boots, determines every feature and setting once, and re-evaluates only when something changes, such as a setting or a plugin. Never lazy-load settings.; rule 61 \u2014 Features wait as pull requests until approved; only hotfixes merge\u2026 \u2014 Message 17118 (2026-10-06), after the overnight refactor merged as 2.252.0: start new work in a new branch, do not merge, write the pull request. Every pull request or new feature is parked until the user approves it. Hotfixes can be merged into main immediately (by a dispatched agent in a worktree of main, rule 60).", "meta": {"from": "journal"}}
{"content": "fact 27 \u2014 Running src/journal.py against the live .journal root starts a\u2026 \u2014 Seen 2026-10-01: with VERSION bumped in the tree, src/journal.py --root .journal saw the live server as another build and started a new one on a new port (8431, 8432), and the user's tabs kept losing connection. Run source builds against a throwaway or demo root (~/projects/demo-crumb/.journal), never the live one, until the release is installed.; rule 57 \u2014 Never merge the overnight refactor into main before its pull request\u2026 \u2014 Messages 15005, 15006, 15109, 15110 (2026-10-04): all refactor work goes on branch overnight-refactor and reaches the user as one pull request, which they read in the morning; nothing of it is merged into main until they say so. Hotfixes the user explicitly asks for go to main at once and are merged into the branch.", "meta": {"from": "journal"}}
{"content": "fact 20 \u2014 A slim supervisor holds the agent and a worker reloads on every build \u2014 Since 2.118.0 (2026-09-23). src/supervisor.py is standard library only and never reloads: journal claude hands its process over to it (os.execv), and it owns the pty and the agent process, relays the terminal, writes the printed and screen captures, listens on the typist socket, restarts the agent in the same session from a relaunch command written to its runtime folder while a restart is pending, and stops it with escalation while draining the pty (an agent cannot finish exiting on macOS while its output is unread). It starts the worker (src/worker.py, which runs runner/worker.py; engine/worker.py stays as an alias for supervisors started before 2.201) and starts it again whenever it exits: RELOAD on a new build, RELAUNCH to restart the agent, STOP to end, HEAL or a quick crash to roll back a build through journal heal. The worker holds everything else: seating the session, the start-up confirm typed through the typist, services, viewer, update check, check-in, and the one-time relaunch of sessions launched before agents/terminal.py LAUNCH. agents/terminal.py holds only journal-side helpers. The server (serve.py) still runs the engines and re-execs itself on a .py change. When the agent exits, the supervisor runs journal ended, which puts set-aside hooks back and stops the server when no session is left.", "meta": {"from": "journal"}}
{"content": "fact 30 \u2014 The tunler server refuses TLS for any subdomain without a tunnel \u2014 Seen 2026-10-04 in the server's docker logs (ssh root@tunler.jessegall.nl, container tunler): 'TLS handshake error ... host \"journal-probe.tunler.jessegall.nl\" not allowed'. A made-up subdomain never answers even when the server is healthy; probe https://tunler.jessegall.nl/ for the server itself. Root SSH to the server works.; rule 49 \u2014 A dialog whose content grows keeps one fixed height, and its content\u2026 \u2014 Message 5361, after asking more than once: a dialog that shows output as it arrives (install, update, logs) opens at its final height and never jumps; only its content scrolls.", "meta": {"from": "journal"}}
{"content": "check 27 passed and 93c3e5fdc The viewer's plugin pages list and upgrade\u2026 \u2014 check 27 passed and 93c3e5fdc The viewer's plugin pages list and upgrade preview are tested is committed; then ran boot guard: installs, serves and launches claude, codex in 7.7s", "meta": {"from": "journal"}}
{"content": "fact 28 \u2014 The designer agent type exists, so design work goes to a subagent \u2014 Since 2026-10-01 .claude/agents/designer.md (Dieter, Opus, Claude Design tools, read-only on the repository) is an agent type; rule 56 says design is a subagent's job, never a helper's.; law L1 \u2014 Every subagent dispatch names its model and chooses the least\u2026 \u2014 Use a fast, economical model for mechanical work with a known answer, a capable general model for careful implementation, and the strongest model only when the task turns on difficult judgement. Inheriting the orchestrator's model is not a model choice. If the dispatch API cannot accept a model, that operation is exempt.; rule 58 \u2014 The user tests a design's clickable prototype and approves it before\u2026 \u2014 Message 15725 (2026-10-05): 'ask Dieter to create an interactive prototype! I want to test it first and give feedback before giving it my go', and remove any fact or rule that conflicts. Replaces rule 53's 'the designer decides'. The designer still runs one critique round (messages 12800, 13475) and revises before showing the prototype; then the user clicks through it, gives feedback, and only the user's go starts the build.", "meta": {"from": "journal"}}
{"content": "your command ran 33s in the foreground and was moved to the background \u2014 carry on with other work; you are told when it ends. Start a command you expect to take long in the background yourself", "meta": {"from": "journal"}}
{"content": "Code Commandments \u2014 before you wrap up \u2014 you've changed 2 judged files since th\u2026 \u2014 Code Commandments \u2014 before you wrap up: you've changed 2 judged files since the last commit. Consider running `commandments judge --changes` to confirm they conform, and fix any sin at its SOURCE (don't launder a finding with a default/cast/null-check). This is a one-time nudge for this batch \u2014 if you've already judged, or these changes aren't worth a scan, just say so and carry on.", "meta": {"from": "journal"}}
{"content": "question 204 completed", "meta": {"from": "journal"}}
{"content": "check 27 passed and 5f8e1b91f The conversation a summary replaced, your own\u2026 \u2014 check 27 passed and 5f8e1b91f The conversation a summary replaced, your own words, and a search across transcripts are read back from a real transcript; tested is committed; then ran boot guard: installs, serves and launches claude, codex in 7.1s", "meta": {"from": "journal"}}
{"content": "The judge can't run on this machine; both changes are tests.", "meta": {"from": "journal"}}
{"content": "the todo tag does this in one step \u2014 [!todo=\"the title\"] files it with the turn as its brief; it runs only when it opens the last text of your turn; fact 13 \u2014 This live session runs the installed copy in .journal/journal.pyz \u2014 The running journal (server, hooks, CLI) runs from .journal/journal.pyz with its viewer and skills in .journal/src, never from the repo. A change in the repo reaches it only through python3 src/journal.py --root .journal upgrade, which packs the zip again. A commit alone changes nothing that is running.", "meta": {"from": "journal"}}
{"content": "rule 27 \u2014 Name a declaration with the word a reader already knows \u2014 An attribute, a variable or a field gets the ordinary programming word for what it holds, not an evocative one. was, heard and alone were poetry; aliases, notify_actions and urgent_actions are what they are. The test: could a reader who has never seen this codebase guess what it holds from the name alone? Prose belongs in the help text and the abstract, where it is read as prose. This does not license abbreviations \u2014 a plain word in full, not a short one.; rule 45 \u2014 No prose words as names in code - said, says, heard, spoke, told\u2026 \u2014 Messages 1360 and 1698. The user has said more than once that code must not read like prose: a variable, attribute, property or function is named for what it holds or does (text, command, labels, lines), never with a verb from a story. 'says' on the Design type (1360) and 'said = call.said.lower()' in features/recital.py (1698) are the examples. Rule 27 states the naming rule; this one carries the words, so writing one of them whispers it. Before writing a name, ask whether a reader who has never seen the code would know what it holds.; rule 55 \u2014 Always dispatch Codex helpers on gpt-6-sol \u2014 The user's word, message 13431: switch the codex agents to GPT-6-Sol and make it their default. ~/.codex/config.toml names it as the default model too.; rule 60 \u2014 A hotfix is done by a dispatched agent in a worktree of main \u2014 Message 16836 (2026-10-06): the orchestrator cut a worktree under .claude/worktrees for a Codex hotfix, its session moved to a new environment and the user's messages stopped reaching it. The user: when working on a branch and a hotfix comes in, create a worktree of main and dispatch an agent to do that work. The orchestrator stays on its branch and in its environment, and never cds into another checkout.", "meta": {"from": "journal"}}
{"content": "Code Commandments \u2014 before you wrap up \u2014 you've changed 1 judged file since the\u2026 \u2014 Code Commandments \u2014 before you wrap up: you've changed 1 judged file since the last commit. Consider running `commandments judge --changes` to confirm they conform, and fix any sin at its SOURCE (don't launder a finding with a default/cast/null-check). This is a one-time nudge for this batch \u2014 if you've already judged, or these changes aren't worth a scan, just say so and carry on.", "meta": {"from": "journal"}}
{"content": "check 27 passed and 5edc64860 Claude's transcript readers are tested - a\u2026 \u2014 check 27 passed and 5edc64860 Claude's transcript readers are tested: a background task's end and failure, typed commands with their output, and the links worth opening is committed; then ran boot guard: installs, serves and launches claude, codex in 8.2s", "meta": {"from": "journal"}}
{"content": "The judge can't run here, but a hand check caught one thing - in the\u2026", "meta": {"from": "journal"}}
{"content": "request GET /api/main/dashboard is slower than its budget \u2014 90ms last (60ms of it working, then 1ms more after it answered), against a budget of 50ms. Seen 148 times.", "meta": {"from": "journal"}}
{"content": "fact 25 \u2014 A designer's install packs the whole tree, half-done server edits\u2026 \u2014 2026-09-25: Eames and Saul run python3 src/journal.py --root .journal upgrade after their viewer builds; it packs every file in src, so a server handler I was halfway through writing went live and raised on every PostToolUse hook. While designers work in parallel, keep server edits whole between tool calls (write and test in the scratchpad first), and reinstall after reverting anything.", "meta": {"from": "journal"}}
{"content": "1 new message 17202 - answer by opening your turn with [!reply:17202]", "meta": {"from": "journal"}}
{"content": "message 17202 file IMG_1155.png needs tags \u2014 inspect the attachment, then journal message tag 17202 \"IMG_1155.png\" \"<a few words describing what it shows>\"; message 17202 updated", "meta": {"from": "journal"}}
{"content": "fact 18 \u2014 cProfile inflates the slow-request profiles about tenfold \u2014 The faults feature writes a profile when a request passes its budget, and the profile is taken with cProfile, which adds per-call overhead. On 2026-09-22 /api/summary profiled at 58ms with 48ms inside Resource.fork's deep copy; with the profiler off the same call ran in 2 to 7ms. Read the profile for where the time goes in relative terms, then time the call with curl before changing anything.; fact 26 \u2014 Claude Code reads agent profiles when a session starts \u2014 Seen 2026-09-26: after the board-filler's profile in .claude/agents gained its steps and the Grep rule, dispatches from the running session still used the old profile (a 3.5-minute first question, shell grep refused); after the session restarted, the same request took 21 seconds with 4 calls. A change to an agent type reaches only sessions started after it is written.; rule 43 \u2014 A request or hook over its budget is fixed before the next release \u2014 Comment 1151 on this rule. When the faults feature reports a request, a hook or a command slower than its budget, file it as a to-do at once. It does not jump ahead of the work in hand, but no version is published while one is still open: profile it, fix it, and verify the new time before the release goes out. The budget is 50ms, because everything runs locally against files.; rule 46 \u2014 Only commit and push once the whole journal is proven to boot \u2014 Messages 2178 and 2179. A release that has not been started for real can crash every project that installs it, as 2.78.3 did for Codex and 2.84.0 did to project records. Before every commit and push: the full suite passes, including tests/test_it_boots.py, which installs a packed copy into a fresh project, launches Claude and Codex from it, writes a project record, upgrades again and checks the record survives. When a change touches launching, installing or upgrading, also start a real journal in a scratch project and close it properly afterwards, leaving no process behind.; rule 51 \u2014 Every finished feature is committed, pushed and released with a new\u2026 \u2014 Message 9207 (2026-09-24): when a new feature is ready, commit, push and publish a new tag. This is the user's standing word for releasing, so rule 44's only-when-the-user-says is met by it for finished features; fixes in between wait for the next feature or a patch the user asks for.", "meta": {"from": "journal"}}
{"content": "rule 39 \u2014 Use only registered exclamation response tags \u2014 A tag like [!reply:12] runs a command, and only the tags in the tags.runs setting are registered. An invented tag does nothing and shows as raw text in the chat. Use the registered ones (reply, log, end, todo, fact, rule) and nothing else.; to-do 3042 came from message 17202? \u2014 link it: journal message process 17202 \"<their words>\" todo:3042", "meta": {"from": "journal"}}
{"content": "fact 9 \u2014 Every public method on a controller becomes a journal command \u2014 The CLI is generated from the controllers: each public method of Controller, or of a typed controller, turns into journal <noun> <method>. A helper added to the base class therefore becomes a command on every type \u2014 which is how journal <type> handled and journal <type> refuse came to exist, from the CRUD funnel and the refusal funnel. An internal helper on a controller is named with a leading underscore, as _shaped and _status already are, or it ships as a command nobody meant.", "meta": {"from": "journal"}}
{"content": "fact 24 \u2014 An answer followed by tool calls can be missing from Claude's\u2026 \u2014 Seen 2026-09-24 for messages 9391-9404: text blocks opening with [!reply:n] that were followed by tool calls never appeared in the session's jsonl (only thinking and tool_use rows did), so the journal never saw them and the replies were lost. When a turn goes on after answering, send the answer with journal message reply <n> \"<text>\" instead of the tag.", "meta": {"from": "journal"}}
{"content": "check 27 passed and 5896b5533 The transcript rows in the long-commands test\u2026 \u2014 check 27 passed and 5896b5533 The transcript rows in the long-commands test are named for what they are is committed; then failed boot guard: slower than 15s boot guard: installs, serves and launches claude, codex in 16.5s", "meta": {"from": "journal"}}
{"content": "rule 36 \u2014 Clean, DRY, idiomatic before it is committed, never after it is\u2026 \u2014 The user should never be the one who finds duplication, dead code, a clumsy name or a pattern the codebase does not use. Read the diff before every commit as a reviewer would, and fix what is not clean then, not in a follow-up after a complaint.", "meta": {"from": "journal"}}
{"content": "waiting: 3 unread worktrees 76, 77, 78", "meta": {"from": "journal"}}
{"content": "1 new message 17206 - answer by opening your turn with [!reply:17206]", "meta": {"from": "journal"}}
{"content": "1 new message 17207 - answer by opening your turn with [!reply:17207]", "meta": {"from": "journal"}}
{"content": "1 new message 17208 - answer by opening your turn with [!reply:17208]", "meta": {"from": "journal"}}
{"content": "1 new comment 2928; report 70 commented", "meta": {"from": "journal"}}
{"content": "the phone's address did not answer 2 times, so its tunnel was restarted", "meta": {"from": "journal"}}
{"content": "helper 102, Edsger Branchstra, reported in message 17212 \u2014 read it, then journal helper finish 102 once its work is taken or dropped", "meta": {"from": "journal"}}
{"content": "chat etiquette - a line from the journal is an instruction, not a message\u2026 \u2014 a turn that only handles a journal line needs no words: act on it, or say once in the chat what you wait on, then carry on; what the user needs to know still goes to the chat", "meta": {"from": "journal"}}
{"content": "helper 104, Grace Pollworth, reported in message 17213 \u2014 read it, then journal helper finish 104 once its work is taken or dropped", "meta": {"from": "journal"}}
{"content": "journal 2.253.1 is out, this project runs 2.253.0 - run journal upgrade to install it", "meta": {"from": "journal"}}
{"content": "check 27 failed - check 27 ran out of time - stopped after 600 seconds\u2026 \u2014 journal check show 27 says why; fix it, then journal check run 27", "meta": {"from": "journal"}}
{"content": "1 new message 17221 - answer by opening your turn with [!reply:17221]", "meta": {"from": "journal"}}
{"content": "message 17221 updated", "meta": {"from": "journal"}}
{"content": "the reply tag does this in one step \u2014 [!reply:N] makes the turn itself the reply; it runs only when it opens the last text of your turn", "meta": {"from": "journal"}}
{"content": "1 new message 17225 - answer by opening your turn with [!reply:17225]", "meta": {"from": "journal"}}
{"content": "I'm trying to reproduce Roban's problem here - a scratch project with two\u2026", "meta": {"from": "journal"}}
{"content": "rule 46 \u2014 Only commit and push once the whole journal is proven to boot \u2014 Messages 2178 and 2179. A release that has not been started for real can crash every project that installs it, as 2.78.3 did for Codex and 2.84.0 did to project records. Before every commit and push: the full suite passes, including tests/test_it_boots.py, which installs a packed copy into a fresh project, launches Claude and Codex from it, writes a project record, upgrades again and checks the record survives. When a change touches launching, installing or upgrading, also start a real journal in a scratch project and close it properly afterwards, leaving no process behind.; rule 51 \u2014 Every finished feature is committed, pushed and released with a new\u2026 \u2014 Message 9207 (2026-09-24): when a new feature is ready, commit, push and publish a new tag. This is the user's standing word for releasing, so rule 44's only-when-the-user-says is met by it for finished features; fixes in between wait for the next feature or a patch the user asks for.", "meta": {"from": "journal"}}
{"content": "journal 2.253.1 is out, this project runs 2.253.0 - run journal upgrade to install it", "meta": {"from": "journal"}}
{"content": "to-do 3047 came from message 17225? \u2014 link it: journal message process 17225 \"<their words>\" todo:3047", "meta": {"from": "journal"}}
{"content": "helper 103, Barbara Liskovered, reported in message 17227 \u2014 read it, then journal helper finish 103 once its work is taken or dropped", "meta": {"from": "journal"}}
{"content": "1 new message 17228 - answer by opening your turn with [!reply:17228]", "meta": {"from": "journal"}}
{"content": "1 new message 17229 - answer by opening your turn with [!reply:17229]", "meta": {"from": "journal"}}
{"content": "message 17229 updated", "meta": {"from": "journal"}}
{"content": "answer message 17237 before you write anything \u2014 answer by opening your turn with [!reply:17237]. a reply, a reaction, or journal message processed <n>", "meta": {"from": "journal"}}
{"content": "helper 101, Ada Coverlace, reported in message 17241 \u2014 read it, then journal helper finish 101 once its work is taken or dropped", "meta": {"from": "journal"}}
{"content": "your command ran 33s in the foreground and was moved to the background \u2014 carry on with other work; you are told when it ends. Start a command you expect to take long in the background yourself", "meta": {"from": "journal"}}
{"content": "chat etiquette - a line from the journal is an instruction, not a message\u2026 \u2014 a turn that only handles a journal line needs no words: act on it, or say once in the chat what you wait on, then carry on; what the user needs to know still goes to the chat", "meta": {"from": "journal"}}
{"content": "the two suspect boot tests on the merged branch came back - Run the two\u2026", "meta": {"from": "journal"}}
{"content": "helper 105, Quentin Quotewell, reported in message 17244 \u2014 read it, then journal helper finish 105 once its work is taken or dropped", "meta": {"from": "journal"}}
{"content": "rule 40 \u2014 A feature is named for what it is, never for its machinery \u2014 Messages 599, 600 and 703. A feature is a capability the user would name and would think of switching off. File tracking, a write gate, a phrase bank, a tree diff are services used inside a feature, not features of their own: they live in the feature they serve. Before adding a directory under features/, say what the user would call it; if the answer names a mechanism, it belongs inside something else. Report 16 holds the grouping this implies.", "meta": {"from": "journal"}}
{"content": "Code Commandments \u2014 before you wrap up \u2014 you've changed 3 judged files since th\u2026 \u2014 Code Commandments \u2014 before you wrap up: you've changed 3 judged files since the last commit. Consider running `commandments judge --changes` to confirm they conform, and fix any sin at its SOURCE (don't launder a finding with a default/cast/null-check). This is a one-time nudge for this batch \u2014 if you've already judged, or these changes aren't worth a scan, just say so and carry on.", "meta": {"from": "journal"}}
{"content": "1 new message 17246 - answer by opening your turn with [!reply:17246]", "meta": {"from": "journal"}}
{"content": "message 17246 updated", "meta": {"from": "journal"}}
{"content": "1 new message 17247 - answer by opening your turn with [!reply:17247]", "meta": {"from": "journal"}}
{"content": "helper 108, Gus Gitchip, reported in message 17250 \u2014 read it, then journal helper finish 108 once its work is taken or dropped", "meta": {"from": "journal"}}
{"content": "check 27 passed and feb53ddcc The newest release is looked up where the\u2026 \u2014 check 27 passed and feb53ddcc The newest release is looked up where the journal is told to look, and no test or boot check reaches GitHub, so a new release can never break the suite is committed; then ran boot guard: installs, serves and launches claude, codex in 12.4s", "meta": {"from": "journal"}}
{"content": "helper 107, Ingrid Installwright, reported in message 17254 \u2014 read it, then journal helper finish 107 once its work is taken or dropped", "meta": {"from": "journal"}}
{"content": "helper 106, Edith Endwell, reported in message 17256 \u2014 read it, then journal helper finish 106 once its work is taken or dropped", "meta": {"from": "journal"}}
{"content": "This journal now runs the merged branch at 2.253.2, live.", "meta": {"from": "journal"}}
{"content": "auto mode is on and work 2168 stands still while todo 3036 is ready \u2014 if work 2168 waits on the user, decide it yourself when you can; otherwise put the question on its row with journal todo ask, end or park the work, and start todo 3036. Stop only when nothing ready is left.; Edith's note also gives the most likely cause of the hang. The old supervisor\u2026", "meta": {"from": "journal"}}
{"content": "your message 17257 names 404 without saying what they are \u2014 put the type before each number, like message 1712 or to-do 644, so the chat links it: journal message edit 17257 \"<the text>\"; fact 24 \u2014 An answer followed by tool calls can be missing from Claude's\u2026 \u2014 Seen 2026-09-24 for messages 9391-9404: text blocks opening with [!reply:n] that were followed by tool calls never appeared in the session's jsonl (only thinking and tool_use rows did), so the journal never saw them and the replies were lost. When a turn goes on after answering, send the answer with journal message reply <n> \"<text>\" instead of the tag.", "meta": {"from": "journal"}}
{"content": "request GET /api/main/dashboard is slower than its budget \u2014 1359ms last (883ms of it working, 9ms collecting garbage), against a budget of 50ms. Seen 152 times.", "meta": {"from": "journal"}}
{"content": "rule 43 \u2014 A request or hook over its budget is fixed before the next release \u2014 Comment 1151 on this rule. When the faults feature reports a request, a hook or a command slower than its budget, file it as a to-do at once. It does not jump ahead of the work in hand, but no version is published while one is still open: profile it, fix it, and verify the new time before the release goes out. The budget is 50ms, because everything runs locally against files.", "meta": {"from": "journal"}}
{"content": "fact 18 \u2014 cProfile inflates the slow-request profiles about tenfold \u2014 The faults feature writes a profile when a request passes its budget, and the profile is taken with cProfile, which adds per-call overhead. On 2026-09-22 /api/summary profiled at 58ms with 48ms inside Resource.fork's deep copy; with the profiler off the same call ran in 2 to 7ms. Read the profile for where the time goes in relative terms, then time the call with curl before changing anything.", "meta": {"from": "journal"}}
{"content": "fact 26 \u2014 Claude Code reads agent profiles when a session starts \u2014 Seen 2026-09-26: after the board-filler's profile in .claude/agents gained its steps and the Grep rule, dispatches from the running session still used the old profile (a 3.5-minute first question, shell grep refused); after the session restarted, the same request took 21 seconds with 4 calls. A change to an agent type reaches only sessions started after it is written.", "meta": {"from": "journal"}}
{"content": "rule 47 \u2014 The journal sets itself up once, when the server starts, never per\u2026 \u2014 Messages 2220 and 2224. Discovering features and their handlers, seating the feature rows and the rename sweep happen once, at server boot, and again only when a feature is switched on or off, a plugin changes or an environment is added: features.load keeps a set-up generation per journal (SEATED) and redoes the work only when that generation moves. A command, a request or a hook uses what is already there; nothing in their path may rediscover handlers or rescan folders. A cost that repeats per call is a bug to fix, not a budget to raise.; rule 61 \u2014 Features wait as pull requests until approved; only hotfixes merge\u2026 \u2014 Message 17118 (2026-10-06), after the overnight refactor merged as 2.252.0: start new work in a new branch, do not merge, write the pull request. Every pull request or new feature is parked until the user approves it. Hotfixes can be merged into main immediately (by a dispatched agent in a worktree of main, rule 60).", "meta": {"from": "journal"}}
{"content": "rule 57 \u2014 Never merge the overnight refactor into main before its pull request\u2026 \u2014 Messages 15005, 15006, 15109, 15110 (2026-10-04): all refactor work goes on branch overnight-refactor and reaches the user as one pull request, which they read in the morning; nothing of it is merged into main until they say so. Hotfixes the user explicitly asks for go to main at once and are merged into the branch.", "meta": {"from": "journal"}}
{"content": "rule 42 \u2014 Every user-facing text passes the formatters before it leaves the\u2026 \u2014 Not only a brief. A title, an abstract, an outcome and every section body are read by a person, so each goes through the same formatters on its way to the viewer \u2014 chat turns, activity items, to-do rows, inspector pages, docs alike. One field formatted out of five is not a rule, it is an accident, and it is how a raw tag ended up in the activity list after the tags feature had been stripping them for weeks. When a new field carries words a person reads, it joins the list in the same place.", "meta": {"from": "journal"}}
{"content": "rule 50 \u2014 Everything the user does is doable in the viewer \u2014 Message 6710 (2026-09-23): the user never uses the CLI, only the UI; everything should be doable from the viewer. The journal commands are for agents; any action meant for the user (making boards, confirming, accepting, hosting, watching an agent) needs its place in the viewer.", "meta": {"from": "journal"}}
{"content": "rule 60 \u2014 A hotfix is done by a dispatched agent in a worktree of main \u2014 Message 16836 (2026-10-06): the orchestrator cut a worktree under .claude/worktrees for a Codex hotfix, its session moved to a new environment and the user's messages stopped reaching it. The user: when working on a branch and a hotfix comes in, create a worktree of main and dispatch an agent to do that work. The orchestrator stays on its branch and in its environment, and never cds into another checkout.", "meta": {"from": "journal"}}
{"content": "the reading pass over every rule and fact is owed \u2014 journal rule reread", "meta": {"from": "journal"}}
{"content": "todo 3049, Write Roban's apology once the quit fix is out and checked, is\u2026 \u2014 journal todo start 3049 when it is next", "meta": {"from": "journal"}}
{"content": "helper 107, Ingrid Installwright, reported in message 17262 \u2014 read it, then journal helper finish 107 once its work is taken or dropped", "meta": {"from": "journal"}}
{"content": "rule 55 \u2014 Always dispatch Codex helpers on gpt-6-sol \u2014 The user's word, message 13431: switch the codex agents to GPT-6-Sol and make it their default. ~/.codex/config.toml names it as the default model too.", "meta": {"from": "journal"}}
{"content": "fact 13 \u2014 This live session runs the installed copy in .journal/journal.pyz \u2014 The running journal (server, hooks, CLI) runs from .journal/journal.pyz with its viewer and skills in .journal/src, never from the repo. A change in the repo reaches it only through python3 src/journal.py --root .journal upgrade, which packs the zip again. A commit alone changes nothing that is running.; law L3 \u2014 Read narrowly - grep for the line, sed a range, head the file; never\u2026 \u2014 Everything a tool returns stays in the context for good and is paid for on every turn after it. Search before you read, read the range you need, and cap output with grep, head or tail. Read a whole file only when you need all of it.; rule 46 \u2014 Only commit and push once the whole journal is proven to boot \u2014 Messages 2178 and 2179. A release that has not been started for real can crash every project that installs it, as 2.78.3 did for Codex and 2.84.0 did to project records. Before every commit and push: the full suite passes, including tests/test_it_boots.py, which installs a packed copy into a fresh project, launches Claude and Codex from it, writes a project record, upgrades again and checks the record survives. When a change touches launching, installing or upgrading, also start a real journal in a scratch project and close it properly afterwards, leaving no process behind.; rule 51 \u2014 Every finished feature is committed, pushed and released with a new\u2026 \u2014 Message 9207 (2026-09-24): when a new feature is ready, commit, push and publish a new tag. This is the user's standing word for releasing, so rule 44's only-when-the-user-says is met by it for finished features; fixes in between wait for the next feature or a patch the user asks for.", "meta": {"from": "journal"}}
{"content": "rule 41 \u2014 Keep moving, run the whole suite before every commit, never wait \u2014 The full suite runs in about seven seconds: .venv/bin/python -m pytest -q --timeout=300 -n auto. Run it before every commit instead of picking tests by name. Group rows that sit in the same code into one sitting: write them all, test once, commit once. And never wait, not for a subagent, a build, or an answer you can carry on without. Dispatch it and keep working. If you truly are waiting on something, say so in the work log.", "meta": {"from": "journal"}}
{"content": "the reply tag does this in one step \u2014 [!reply:N] makes the turn itself the reply; it runs only when it opens the last text of your turn", "meta": {"from": "journal"}}
{"content": "helper 108, Gus Gitchip, reported in message 17267 \u2014 read it, then journal helper finish 108 once its work is taken or dropped", "meta": {"from": "journal"}}
{"content": "law L5 \u2014 Every subagent dispatch names the agent - a human name, a little\u2026 \u2014 A name is how the user and the chat tell subagents apart and how they are messaged later; an id or a task line is not a name. Start the dispatch's description with the name, a colon, then the task, such as \"Dr. Einstein: profile the slow hooks\" or \"Coco Rams: draw the plan card\". A designer can borrow from famous designers, a researcher from famous scientists, mixed up for fun.", "meta": {"from": "journal"}}
{"content": "fact 9 \u2014 Every public method on a controller becomes a journal command \u2014 The CLI is generated from the controllers: each public method of Controller, or of a typed controller, turns into journal <noun> <method>. A helper added to the base class therefore becomes a command on every type \u2014 which is how journal <type> handled and journal <type> refuse came to exist, from the CRUD funnel and the refusal funnel. An internal helper on a controller is named with a leading underscore, as _shaped and _status already are, or it ships as a command nobody meant.", "meta": {"from": "journal"}}
{"content": "your command ran 32s in the foreground and was moved to the background \u2014 carry on with other work; you are told when it ends. Start a command you expect to take long in the background yourself", "meta": {"from": "journal"}}
{"content": "Code Commandments \u2014 before you wrap up \u2014 you've changed 2 judged files since th\u2026 \u2014 Code Commandments \u2014 before you wrap up: you've changed 2 judged files since the last commit. Consider running `commandments judge --changes` to confirm they conform, and fix any sin at its SOURCE (don't launder a finding with a default/cast/null-check). This is a one-time nudge for this batch \u2014 if you've already judged, or these changes aren't worth a scan, just say so and carry on.", "meta": {"from": "journal"}}
{"content": "The judge can't run on this machine. The two changes are a cache decorator and\u2026", "meta": {"from": "journal"}}
{"content": "auto mode is on and work 2168 stands still while todo 3042 is ready \u2014 if work 2168 waits on the user, decide it yourself when you can; otherwise put the question on its row with journal todo ask, end or park the work, and start todo 3042. Stop only when nothing ready is left.; Once this gate passes, I'll merge main's three newest hotfixes into the\u2026", "meta": {"from": "journal"}}
{"content": "journal 2.253.5 is out, this project runs 2.253.2 - run journal upgrade to install it", "meta": {"from": "journal"}}
{"content": "check 27 passed and 94b16846f A cold dashboard formats its rows a third faster\u2026 \u2014 check 27 passed and 94b16846f A cold dashboard formats its rows a third faster: a controller's actions are looked up once per class, and text that names no row skips the environment lookup is committed; then ran boot guard: installs, serves and launches claude, codex in 4.7s", "meta": {"from": "journal"}}
{"content": "chat etiquette - a line from the journal is an instruction, not a message\u2026 \u2014 a turn that only handles a journal line needs no words: act on it, or say once in the chat what you wait on, then carry on; what the user needs to know still goes to the chat", "meta": {"from": "journal"}}
{"content": "Code Commandments \u2014 the files changed since the last check (`supervisor.py`, `t\u2026 \u2014 Code Commandments \u2014 the files changed since the last check (`supervisor.py`, `test.py`, `actions.py`, `test.py`, `test.py`) breaks a rule. Fix it now, at its SOURCE, while the code is still in front of you: \u00b7 \u2022 python-conditional-statement at /Users/jessegall/projects/agent-journal/src/features/agent_sessions/test.py:89 \u00b7 LOAD the skill `commandments-python-flow` before fixing \u2014 load it even if you believe you already have. \u00b7 Run `commandments info <sin>` if a rule is not one you recognise. This check reads a file at a time, so it is not the whole picture \u2014 `judge` still is.", "meta": {"from": "journal"}}
{"content": "the dashboard gate, then the merge of 2.253.3 to 2.253.5 and the live install\u2026", "meta": {"from": "journal"}}
{"content": "Code Commandments \u2014 before you commit \u2014 you've changed 11 judged files since th\u2026 \u2014 Code Commandments \u2014 before you commit: you've changed 11 judged files since the last commit. Consider running `commandments judge --changes` to confirm they conform, and fix any sin at its SOURCE (don't launder a finding with a default/cast/null-check). This is a one-time nudge for this batch \u2014 if you've already judged, or these changes aren't worth a scan, just say so and carry on.; rule 36 \u2014 Clean, DRY, idiomatic before it is committed, never after it is\u2026 \u2014 The user should never be the one who finds duplication, dead code, a clumsy name or a pattern the codebase does not use. Read the diff before every commit as a reviewer would, and fix what is not clean then, not in a follow-up after a complaint.", "meta": {"from": "journal"}}
{"content": "the merged branch's suite, then push, live install and a fresh coverage\u2026", "meta": {"from": "journal"}}
{"content": "the coverage measurement on the merged branch came back - Measure coverage on\u2026", "meta": {"from": "journal"}}
{"content": "fact 20 \u2014 A slim supervisor holds the agent and a worker reloads on every build \u2014 Since 2.118.0 (2026-09-23). src/supervisor.py is standard library only and never reloads: journal claude hands its process over to it (os.execv), and it owns the pty and the agent process, relays the terminal, writes the printed and screen captures, listens on the typist socket, restarts the agent in the same session from a relaunch command written to its runtime folder while a restart is pending, and stops it with escalation while draining the pty (an agent cannot finish exiting on macOS while its output is unread). It starts the worker (src/worker.py, which runs runner/worker.py; engine/worker.py stays as an alias for supervisors started before 2.201) and starts it again whenever it exits: RELOAD on a new build, RELAUNCH to restart the agent, STOP to end, HEAL or a quick crash to roll back a build through journal heal. The worker holds everything else: seating the session, the start-up confirm typed through the typist, services, viewer, update check, check-in, and the one-time relaunch of sessions launched before agents/terminal.py LAUNCH. agents/terminal.py holds only journal-side helpers. The server (serve.py) still runs the engines and re-execs itself on a .py change. When the agent exits, the supervisor runs journal ended, which puts set-aside hooks back and stops the server when no session is left.; fact 23 \u2014 Every upgrade brings system sequences and their triggers in line\u2026 \u2014 install.py runs ship_sequences after the migrations on each upgrade, so features/sequences/shipped.py is the whole source: change its wording and the next upgrade updates every journal, no migration needed. Shipped rows carry system=True and are read-only for everyone but SYSTEM (controllers/base.py _shipped).", "meta": {"from": "journal"}}
{"content": "check 27 passed and 9f2d76a2f The coverage floor rises to 97 percent, where\u2026 \u2014 check 27 passed and 9f2d76a2f The coverage floor rises to 97 percent, where the suite now stands is committed; then ran boot guard: installs, serves and launches claude, codex in 5.8s", "meta": {"from": "journal"}}
{"content": "the coverage floor gate, then the second round of coverage helpers came back\u2026", "meta": {"from": "journal"}}
{"content": "law L1 \u2014 Every subagent dispatch names its model and chooses the least\u2026 \u2014 Use a fast, economical model for mechanical work with a known answer, a capable general model for careful implementation, and the strongest model only when the task turns on difficult judgement. Inheriting the orchestrator's model is not a model choice. If the dispatch API cannot accept a model, that operation is exempt.; law L2 \u2014 Every subagent is bound to a concrete job; never dispatch a generic\u2026 \u2014 Use the most specific available agent type whose declared purpose matches the assignment. On providers without agent types, give the dispatch a concrete task name and bounded prompt. If no suitable specialization exists, keep the work in the main agent instead of manufacturing an unscoped helper.; law L4 \u2014 Follow-up work goes back to the subagent that did the first part\u2026 \u2014 A subagent that drew a design, wrote the code or ran the research keeps what it learned. When the user asks for a change to its work, continue that subagent with a message rather than dispatching a new one that has to rediscover everything; start fresh only when the earlier one is gone or the new work is unrelated.; rule 35 \u2014 Write clean code - one funnel per kind of operation, never the same\u2026 \u2014 Every kind of operation has one funnel: one method that creates, one that saves, one that refuses, one that formats. A second method that does the same thing under another name splits the behaviour, and the two drift apart. Before writing a method, search for the one that already does it and extend that. scripts/checks/funnels.py finds bodies written twice.; rule 38 \u2014 Never change the git branch until the user says so, by name \u2014 The work happens on the branch the user named. That was main until message 5929 and question 80 (2026-09-23), which moved the sins work to the branch sins. Do not create, switch to or merge any other branch unless the user names it in their own words.; rule 56 \u2014 Helpers are for work that writes; subagents read, research and design \u2014 The user, message 13464: there must be a clear distinction. A subagent can be dispatched for anything read-only: research, review, design. A helper is for actual work that writes, best in its own worktree when the work is separate. Dieter designing in Claude Design should have been a subagent, not a helper.", "meta": {"from": "journal"}}
{"content": "waiting: 2 unread worktrees 79, 80", "meta": {"from": "journal"}}
{"content": "1 new message 17275 - answer by opening your turn with [!reply:17275]", "meta": {"from": "journal"}}
{"content": "1 new message 17276 - answer by opening your turn with [!reply:17276]", "meta": {"from": "journal"}}
{"content": "1 new message 17281 - answer by opening your turn with [!reply:17281]", "meta": {"from": "journal"}}
{"content": "1 new message 17282 - answer by opening your turn with [!reply:17282]", "meta": {"from": "journal"}}
{"content": "your command ran 33s in the foreground and was moved to the background \u2014 carry on with other work; you are told when it ends. Start a command you expect to take long in the background yourself", "meta": {"from": "journal"}}
{"content": "1 new message 17283 - answer by opening your turn with [!reply:17283]", "meta": {"from": "journal"}}
{"content": "1 new message 17285 - answer by opening your turn with [!reply:17285]", "meta": {"from": "journal"}}
{"content": "1 new message 17286 - answer by opening your turn with [!reply:17286]", "meta": {"from": "journal"}}
{"content": "1 new message 17287 - answer by opening your turn with [!reply:17287]", "meta": {"from": "journal"}}
{"content": "check 27 passed and b1c6245b6 A design goes through three critique rounds by\u2026 \u2014 check 27 passed and b1c6245b6 A design goes through three critique rounds by separate critic agents, then the user tries the prototype is committed; then ran boot guard: installs, serves and launches claude, codex in 7.0s", "meta": {"from": "journal"}}
{"content": "1 new message 17288 - answer by opening your turn with [!reply:17288]", "meta": {"from": "journal"}}
{"content": "1 new message 17289 - answer by opening your turn with [!reply:17289]", "meta": {"from": "journal"}}
{"content": "check 27 passed and 1753cb4c2 After its three critique rounds a design is\u2026 \u2014 check 27 passed and 1753cb4c2 After its three critique rounds a design is built on a branch, with no approval of the design itself is committed; then ran boot guard: installs, serves and launches claude, codex in 11.5s", "meta": {"from": "journal"}}
{"content": "1 new message 17290 - answer by opening your turn with [!reply:17290]", "meta": {"from": "journal"}}
{"content": "message 17290 updated", "meta": {"from": "journal"}}
{"content": "chat etiquette - a line from the journal is an instruction, not a message\u2026 \u2014 a turn that only handles a journal line needs no words: act on it, or say once in the chat what you wait on, then carry on; what the user needs to know still goes to the chat", "meta": {"from": "journal"}}
{"content": "1 new message 17291 - answer by opening your turn with [!reply:17291]", "meta": {"from": "journal"}}
{"content": "message 17291 updated", "meta": {"from": "journal"}}
{"content": "the reply tag does this in one step \u2014 [!reply:N] makes the turn itself the reply; it runs only when it opens the last text of your turn", "meta": {"from": "journal"}}
{"content": "helper 111, Pippa Thumbsworth, reported in message 17293 \u2014 read it, then journal helper finish 111 once its work is taken or dropped", "meta": {"from": "journal"}}
{"content": "1 new message 17294 - answer by opening your turn with [!reply:17294]", "meta": {"from": "journal"}}
{"content": "helper 109, Ken Pseudoterm, reported in message 17295 \u2014 read it, then journal helper finish 109 once its work is taken or dropped", "meta": {"from": "journal"}}
{"content": "your message 17296 names 120 without saying what they are \u2014 put the type before each number, like message 1712 or to-do 644, so the chat links it: journal message edit 17296 \"<the text>\"", "meta": {"from": "journal"}}
{"content": "1 new message 17297 - answer by opening your turn with [!reply:17297]", "meta": {"from": "journal"}}
{"content": "message 17297 updated", "meta": {"from": "journal"}}
{"content": "1 new message 17299 - answer by opening your turn with [!reply:17299]", "meta": {"from": "journal"}}
{"content": "1 new message 17300 - answer by opening your turn with [!reply:17300]", "meta": {"from": "journal"}}
{"content": "message 17300 updated", "meta": {"from": "journal"}}
{"content": "helper 112, Gus Gitchip Junior, reported in message 17301 \u2014 read it, then journal helper finish 112 once its work is taken or dropped", "meta": {"from": "journal"}}
{"content": "1 new message 17302 - answer by opening your turn with [!reply:17302]", "meta": {"from": "journal"}}
{"content": "message 17302 updated", "meta": {"from": "journal"}}
{"content": "message 17302 updated", "meta": {"from": "journal"}}
{"content": "1 new message 17303 - answer by opening your turn with [!reply:17303]", "meta": {"from": "journal"}}
{"content": "1 new message 17304 - answer by opening your turn with [!reply:17304]", "meta": {"from": "journal"}}
{"content": "message 17304 updated", "meta": {"from": "journal"}}
{"content": "chat etiquette - a line from the journal is an instruction, not a message\u2026 \u2014 a turn that only handles a journal line needs no words: act on it, or say once in the chat what you wait on, then carry on; what the user needs to know still goes to the chat", "meta": {"from": "journal"}}
{"content": "1 new message 17305 - answer by opening your turn with [!reply:17305]", "meta": {"from": "journal"}}
{"content": "the reply tag does this in one step \u2014 [!reply:N] makes the turn itself the reply; it runs only when it opens the last text of your turn", "meta": {"from": "journal"}}
{"content": "helper 110, Margaret Fixturewood, reported in message 17307 \u2014 read it, then journal helper finish 110 once its work is taken or dropped", "meta": {"from": "journal"}}
{"content": "Sir Jesse, **2.253.7** is out - no git chip shows shell syntax any more. That\u2026", "meta": {"from": "journal"}}
{"content": "your command ran 34s in the foreground and was moved to the background \u2014 carry on with other work; you are told when it ends. Start a command you expect to take long in the background yourself", "meta": {"from": "journal"}}
{"content": "answer message 17302 before you write anything \u2014 answer by opening your turn with [!reply:17302]. a reply, a reaction, or journal message processed <n>", "meta": {"from": "journal"}}
{"content": "the rogue-agent reproduction with a direct process check came back - Rerun\u2026", "meta": {"from": "journal"}}
{"content": "rule 36 \u2014 Clean, DRY, idiomatic before it is committed, never after it is\u2026 \u2014 The user should never be the one who finds duplication, dead code, a clumsy name or a pattern the codebase does not use. Read the diff before every commit as a reviewer would, and fix what is not clean then, not in a follow-up after a complaint.", "meta": {"from": "journal"}}
{"content": "rule 54 \u2014 Settings and feature switches are read at boot and on change, never\u2026 \u2014 The user, message 13349: the application boots, determines every feature and setting once, and re-evaluates only when something changes, such as a setting or a plugin. Never lazy-load settings.", "meta": {"from": "journal"}}
{"content": "law L2 \u2014 Every subagent is bound to a concrete job; never dispatch a generic\u2026 \u2014 Use the most specific available agent type whose declared purpose matches the assignment. On providers without agent types, give the dispatch a concrete task name and bounded prompt. If no suitable specialization exists, keep the work in the main agent instead of manufacturing an unscoped helper.", "meta": {"from": "journal"}}
{"content": "fact 25 \u2014 A designer's install packs the whole tree, half-done server edits\u2026 \u2014 2026-09-25: Eames and Saul run python3 src/journal.py --root .journal upgrade after their viewer builds; it packs every file in src, so a server handler I was halfway through writing went live and raised on every PostToolUse hook. While designers work in parallel, keep server edits whole between tool calls (write and test in the scratchpad first), and reinstall after reverting anything.; law L4 \u2014 Follow-up work goes back to the subagent that did the first part\u2026 \u2014 A subagent that drew a design, wrote the code or ran the research keeps what it learned. When the user asks for a change to its work, continue that subagent with a message rather than dispatching a new one that has to rediscover everything; start fresh only when the earlier one is gone or the new work is unrelated.; rule 42 \u2014 Every user-facing text passes the formatters before it leaves the\u2026 \u2014 Not only a brief. A title, an abstract, an outcome and every section body are read by a person, so each goes through the same formatters on its way to the viewer \u2014 chat turns, activity items, to-do rows, inspector pages, docs alike. One field formatted out of five is not a rule, it is an accident, and it is how a raw tag ended up in the activity list after the tags feature had been stripping them for weeks. When a new field carries words a person reads, it joins the list in the same place.; rule 56 \u2014 Helpers are for work that writes; subagents read, research and design \u2014 The user, message 13464: there must be a clear distinction. A subagent can be dispatched for anything read-only: research, review, design. A helper is for actual work that writes, best in its own worktree when the work is separate. Dieter designing in Claude Design should have been a subagent, not a helper.", "meta": {"from": "journal"}}
{"content": "rule 58 \u2014 A design runs three critique rounds, then is built on a branch \u2014 Messages 17276 and 17281 (2026-10-06): the norm is a three-round cycle. Round by round, the designer designs (or revises), separate critic agents review the design through their lenses (journal critique round; read-only subagents, one per lens), and the designer adjusts it to their findings; three rounds in all. The three rounds stand in for the user's approval of the design: the user does not approve it. After the third round the design is built on a branch of its own, which ends in a pull request that waits for the user's approval (rule 61). Replaces message 15725's prototype approval.", "meta": {"from": "journal"}}
{"content": "rule 48 \u2014 The viewer is built from its component library, and pages only\u2026 \u2014 Message 4258. Every visual piece the viewer shows more than once, or that a user would recognise as the same kind of thing (a dialog, a side panel or inspector, a dropdown, a list row, a switch, a button), is one component in web/src/kit, extracted aggressively, and every page composes those components instead of building its own copy. Before writing markup or styles in a page, look for the kit component that already does it and extend it with a prop; a second hand-built version is a bug. The side panel that animated in but not out, while a separate skill panel did both, is the example.; rule 59 \u2014 Every viewer heading and label says plainly what it is about \u2014 The user, messages 16499, 16839, 16844, 16989, 16992 and 16993 (2026-10-06), after 'Where the words count', 'Watch for the words in', 'This project', 'This browser' and 'Stop the journal' as tab names: viewer text reads like Linear, GitHub or Vercel. A place (page, tab, group, sidebar item) is a short noun: Settings, Project, Browser, Services, Updates, Plugins; never 'This project' or a phrase. A button is a verb for what happens: Stop, Install, Copy link, Pause the plan. A heading names what the reader looks at, and its options finish its sentence: 'Trigger when' / 'A word is written'. Plain literal words: no metaphor or whimsy ('kettle on, waiting'), no app speaking as I, none of the journal's internal words (row, hook, nudge, engine, slate). One word for one thing everywhere, sentence case, as short as it can be while clear. Applies to designers' prototypes, helpers' builds, the viewer's JavaScript lists, feature details, and shipped sequence and trigger titles alike.", "meta": {"from": "journal"}}
{"content": "fact 26 \u2014 Claude Code reads agent profiles when a session starts \u2014 Seen 2026-09-26: after the board-filler's profile in .claude/agents gained its steps and the Grep rule, dispatches from the running session still used the old profile (a 3.5-minute first question, shell grep refused); after the session restarted, the same request took 21 seconds with 4 calls. A change to an agent type reaches only sessions started after it is written.", "meta": {"from": "journal"}}
{"content": "law L1 \u2014 Every subagent dispatch names its model and chooses the least\u2026 \u2014 Use a fast, economical model for mechanical work with a known answer, a capable general model for careful implementation, and the strongest model only when the task turns on difficult judgement. Inheriting the orchestrator's model is not a model choice. If the dispatch API cannot accept a model, that operation is exempt.", "meta": {"from": "journal"}}
{"content": "check 27 passed and bbbc10cdb A critic agent type critiques a design through\u2026 \u2014 check 27 passed and bbbc10cdb A critic agent type critiques a design through one lens in its three rounds is committed; then ran boot guard: installs, serves and launches claude, codex in 6.6s", "meta": {"from": "journal"}}
{"content": "helper 113, Rosa Roundup, reported in message 17318 \u2014 read it, then journal helper finish 113 once its work is taken or dropped", "meta": {"from": "journal"}}
{"content": "helper 114, Theo Typewell, reported in message 17319 \u2014 read it, then journal helper finish 114 once its work is taken or dropped", "meta": {"from": "journal"}}
{"content": "the todo tag does this in one step \u2014 [!todo=\"the title\"] files it with the turn as its brief; it runs only when it opens the last text of your turn", "meta": {"from": "journal"}}
{"content": "helper 115, Dora Donewell, reported in message 17325 \u2014 read it, then journal helper finish 115 once its work is taken or dropped", "meta": {"from": "journal"}}
{"content": "work 2168 in hand \u2014 Measure test coverage and raise it towards 100 percent \u2014 if this is not what you are doing, end it or park it and start the work you are in; Code Commandments \u2014 before you commit \u2014 you've changed 17 judged files since th\u2026 \u2014 Code Commandments \u2014 before you commit: you've changed 17 judged files since the last commit. Consider running `commandments judge --changes` to confirm they conform, and fix any sin at its SOURCE (don't launder a finding with a default/cast/null-check). This is a one-time nudge for this batch \u2014 if you've already judged, or these changes aren't worth a scan, just say so and carry on.", "meta": {"from": "journal"}}
{"content": "auto mode is on and work 2168 stands still while todo 3046 is ready \u2014 if work 2168 waits on the user, decide it yourself when you can; otherwise put the question on its row with journal todo ask, end or park the work, and start todo 3046. Stop only when nothing ready is left.; The third and last critique round on the phone design is running. When it's\u2026", "meta": {"from": "journal"}}
{"content": "work 2168, Measure test coverage and raise it towards 100 percent, is still\u2026 \u2014 it was parked because: Coverage at about 98% in pull request 9, waiting for the user's approval; the last gaps need fixtures for terminals and restarts. journal work resume 2168 picks it up again.; fact 9 \u2014 Every public method on a controller becomes a journal command \u2014 The CLI is generated from the controllers: each public method of Controller, or of a typed controller, turns into journal <noun> <method>. A helper added to the base class therefore becomes a command on every type \u2014 which is how journal <type> handled and journal <type> refuse came to exist, from the CRUD funnel and the refusal funnel. An internal helper on a controller is named with a leading underscore, as _shaped and _status already are, or it ships as a command nobody meant.; rule 37 \u2014 Close every to-do explicitly with todo done or a Journal commit\u2026 \u2014 Ending work does not close its row. A to-do is closed by journal todo done <n> --how, or by a commit whose message carries Journal: todos done <n> at column 0, several numbers separated by commas. A row left open after its work landed misleads the next session and auto mode.; rule 61 \u2014 Features wait as pull requests until approved; only hotfixes merge\u2026 \u2014 Message 17118 (2026-10-06), after the overnight refactor merged as 2.252.0: start new work in a new branch, do not merge, write the pull request. Every pull request or new feature is parked until the user approves it. Hotfixes can be merged into main immediately (by a dispatched agent in a worktree of main, rule 60).", "meta": {"from": "journal"}}
{"content": "check 1 failed - features/session_briefing/test.py has 11 tests, over 10; what n \u2014 journal check show 1 says why; fix it, then journal check run 1", "meta": {"from": "journal"}}
{"content": "the todo tag does this in one step \u2014 [!todo=\"the title\"] files it with the turn as its brief; it runs only when it opens the last text of your turn", "meta": {"from": "journal"}}
{"content": "Code Commandments \u2014 before you wrap up \u2014 you've changed 1 judged file since the\u2026 \u2014 Code Commandments \u2014 before you wrap up: you've changed 1 judged file since the last commit. Consider running `commandments judge --changes` to confirm they conform, and fix any sin at its SOURCE (don't launder a finding with a default/cast/null-check). This is a one-time nudge for this batch \u2014 if you've already judged, or these changes aren't worth a scan, just say so and carry on.", "meta": {"from": "journal"}}
{"content": "check 27 passed and ecc730d18 The follow-up delivery test joins the delivery\u2026 \u2014 check 27 passed and ecc730d18 The follow-up delivery test joins the delivery test, so the session briefing keeps its ten tests is committed; then ran boot guard: installs, serves and launches claude, codex in 9.9s", "meta": {"from": "journal"}}
{"content": "work 2168, Measure test coverage and raise it towards 100 percent, is still\u2026 \u2014 it was parked because: Coverage at about 98% in pull request 9, waiting for the user's approval; the last gaps need fixtures for terminals and restarts. journal work resume 2168 picks it up again.", "meta": {"from": "journal"}}
{"content": "helper 116, Paloma Pluginfit, reported in message 17338 \u2014 read it, then journal helper finish 116 once its work is taken or dropped", "meta": {"from": "journal"}}
{"content": "chat etiquette - a line from the journal is an instruction, not a message\u2026 \u2014 a turn that only handles a journal line needs no words: act on it, or say once in the chat what you wait on, then carry on; what the user needs to know still goes to the chat", "meta": {"from": "journal"}}
{"content": "the await tag does this in one step \u2014 [!await] makes the rest of the turn what you wait for; [!await on=(\"<id>\", \"helper:<n>\")] waits on those; it runs only when it opens the last text of your turn", "meta": {"from": "journal"}}
{"content": "your last message offers choices in prose \u2014 ask through journal question ask \"<one line>\" --set options='[{\"title\": \u2026, \"description\": \u2026}]' --set pick=<n>, so the viewer renders it; your writes wait until you do", "meta": {"from": "journal"}}
{"content": "your chat talked about the journal's workings - \"I'm still waiting\" \u2014 the user sees replies, reactions, pills and reads themselves; say what the work is instead", "meta": {"from": "journal"}}
{"content": "the phone's address did not answer 2 times, so its tunnel was restarted", "meta": {"from": "journal"}}
{"content": "helper 117, Fernando Foundwell, reported in message 17365 \u2014 read it, then journal helper finish 117 once its work is taken or dropped", "meta": {"from": "journal"}}
{"content": "helper 117, Fernando Foundwell, reported in message 17367 \u2014 read it, then journal helper finish 117 once its work is taken or dropped", "meta": {"from": "journal"}}
{"content": "work 2168, Measure test coverage and raise it towards 100 percent, is still\u2026 \u2014 it was parked because: Coverage at about 98% in pull request 9, waiting for the user's approval; the last gaps need fixtures for terminals and restarts. journal work resume 2168 picks it up again.", "meta": {"from": "journal"}}
{"content": "waiting: 3 unread worktrees 82, 83, 84", "meta": {"from": "journal"}}
{"content": "helper 121, Sergei Settingsby, reported in message 17371 \u2014 read it, then journal helper finish 121 once its work is taken or dropped", "meta": {"from": "journal"}}
{"content": "helper 121, Sergei Settingsby, reported in message 17375 \u2014 read it, then journal helper finish 121 once its work is taken or dropped", "meta": {"from": "journal"}}
{"content": "work 2168, Measure test coverage and raise it towards 100 percent, is still\u2026 \u2014 it was parked because: Coverage at about 98% in pull request 9, waiting for the user's approval; the last gaps need fixtures for terminals and restarts. journal work resume 2168 picks it up again.", "meta": {"from": "journal"}}
{"content": "your chat talked about the journal's workings - \"to-do 3068 is closed\" \u2014 the user sees replies, reactions, pills and reads themselves; say what the work is instead", "meta": {"from": "journal"}}
{"content": "1 new message 17378 - answer by opening your turn with [!reply:17378]", "meta": {"from": "journal"}}
{"content": "your last message ran its paragraphs together \u2014 a blank line between parts is what makes a message readable: one thought to a paragraph", "meta": {"from": "journal"}}
{"content": "question 205 completed", "meta": {"from": "journal"}}
{"content": "1 new message 17380 - answer by opening your turn with [!reply:17380]", "meta": {"from": "journal"}}
{"content": "message 17380 updated", "meta": {"from": "journal"}}
{"content": "1 new message 17388 - answer by opening your turn with [!reply:17388]", "meta": {"from": "journal"}}
{"content": "helper 119, Tilda Taskwell, reported in message 17389 \u2014 read it, then journal helper finish 119 once its work is taken or dropped", "meta": {"from": "journal"}}
{"content": "helper 120, Evert Everywhere, reported in message 17393 \u2014 read it, then journal helper finish 120 once its work is taken or dropped", "meta": {"from": "journal"}}
{"content": "work 2168, Measure test coverage and raise it towards 100 percent, is still\u2026 \u2014 it was parked because: Coverage at about 98% in pull request 9, waiting for the user's approval; the last gaps need fixtures for terminals and restarts. journal work resume 2168 picks it up again.", "meta": {"from": "journal"}}
{"content": "1 new message 17396 - answer by opening your turn with [!reply:17396]", "meta": {"from": "journal"}}
{"content": "1 new message 17397 - answer by opening your turn with [!reply:17397]", "meta": {"from": "journal"}}
{"content": "message 17397 updated", "meta": {"from": "journal"}}
{"content": "the todo tag does this in one step \u2014 [!todo=\"the title\"] files it with the turn as its brief; it runs only when it opens the last text of your turn", "meta": {"from": "journal"}}
{"content": "Hector's fix on main, the three phone screen helpers, and Ingo building the\u2026", "meta": {"from": "journal"}}
{"content": "law L5 \u2014 Every subagent dispatch names the agent - a human name, a little\u2026 \u2014 A name is how the user and the chat tell subagents apart and how they are messaged later; an id or a task line is not a name. Start the dispatch's description with the name, a colon, then the task, such as \"Dr. Einstein: profile the slow hooks\" or \"Coco Rams: draw the plan card\". A designer can borrow from famous designers, a researcher from famous scientists, mixed up for fun.; rule 38 \u2014 Never change the git branch until the user says so, by name \u2014 The work happens on the branch the user named. That was main until message 5929 and question 80 (2026-09-23), which moved the sins work to the branch sins. Do not create, switch to or merge any other branch unless the user names it in their own words.; rule 56 \u2014 Helpers are for work that writes; subagents read, research and design \u2014 The user, message 13464: there must be a clear distinction. A subagent can be dispatched for anything read-only: research, review, design. A helper is for actual work that writes, best in its own worktree when the work is separate. Dieter designing in Claude Design should have been a subagent, not a helper.", "meta": {"from": "journal"}}
{"content": "fact 25 \u2014 A designer's install packs the whole tree, half-done server edits\u2026 \u2014 2026-09-25: Eames and Saul run python3 src/journal.py --root .journal upgrade after their viewer builds; it packs every file in src, so a server handler I was halfway through writing went live and raised on every PostToolUse hook. While designers work in parallel, keep server edits whole between tool calls (write and test in the scratchpad first), and reinstall after reverting anything.; fact 28 \u2014 The designer agent type exists, so design work goes to a subagent \u2014 Since 2026-10-01 .claude/agents/designer.md (Dieter, Opus, Claude Design tools, read-only on the repository) is an agent type; rule 56 says design is a subagent's job, never a helper's.; rule 59 \u2014 Every viewer heading and label says plainly what it is about \u2014 The user, messages 16499, 16839, 16844, 16989, 16992 and 16993 (2026-10-06), after 'Where the words count', 'Watch for the words in', 'This project', 'This browser' and 'Stop the journal' as tab names: viewer text reads like Linear, GitHub or Vercel. A place (page, tab, group, sidebar item) is a short noun: Settings, Project, Browser, Services, Updates, Plugins; never 'This project' or a phrase. A button is a verb for what happens: Stop, Install, Copy link, Pause the plan. A heading names what the reader looks at, and its options finish its sentence: 'Trigger when' / 'A word is written'. Plain literal words: no metaphor or whimsy ('kettle on, waiting'), no app speaking as I, none of the journal's internal words (row, hook, nudge, engine, slate). One word for one thing everywhere, sentence case, as short as it can be while clear. Applies to designers' prototypes, helpers' builds, the viewer's JavaScript lists, feature details, and shipped sequence and trigger titles alike.; rule 49 \u2014 A dialog whose content grows keeps one fixed height, and its content\u2026 \u2014 Message 5361, after asking more than once: a dialog that shows output as it arrives (install, update, logs) opens at its final height and never jumps; only its content scrolls.; rule 60 \u2014 A hotfix is done by a dispatched agent in a worktree of main \u2014 Message 16836 (2026-10-06): the orchestrator cut a worktree under .claude/worktrees for a Codex hotfix, its session moved to a new environment and the user's messages stopped reaching it. The user: when working on a branch and a hotfix comes in, create a worktree of main and dispatch an agent to do that work. The orchestrator stays on its branch and in its environment, and never cds into another checkout.; rule 58 \u2014 A design runs three critique rounds, then is built on a branch \u2014 Messages 17276 and 17281 (2026-10-06): the norm is a three-round cycle. Round by round, the designer designs (or revises), separate critic agents review the design through their lenses (the critic agent type, .claude/agents/critic.md: read-only, with a browser; one per lens, such as first-time, native, words and parity), and the designer adjusts it to their findings; three rounds in all. The three rounds stand in for the user's approval of the design: the user does not approve it. After the third round the design is built on a branch of its own, which ends in a pull request that waits for the user's approval (rule 61). Replaces message 15725's prototype approval.", "meta": {"from": "journal"}}
{"content": "request GET /api/manifest is slower than its budget \u2014 258ms last (63ms of it working, then 2ms more after it answered), against a budget of 50ms. Seen 24 times.", "meta": {"from": "journal"}}
{"content": "answer message 17397 before you write anything \u2014 answer by opening your turn with [!reply:17397]. a reply, a reaction, or journal message processed <n>", "meta": {"from": "journal"}}
{"content": "1 new message 17401 - answer by opening your turn with [!reply:17401]", "meta": {"from": "journal"}}
{"content": "1 new message 17402 - answer by opening your turn with [!reply:17402]", "meta": {"from": "journal"}}
{"content": "the user put \u2764\ufe0f on comment 2965 - act on it if it asks for something, such as a go-ahead. It needs no reply, and the chat never mentions it", "meta": {"from": "journal"}}
{"content": "journal 2.253.12 is out, this project runs 2.253.10 - run journal upgrade to install it", "meta": {"from": "journal"}}
{"content": "your command ran 31s in the foreground and was moved to the background \u2014 carry on with other work; you are told when it ends. Start a command you expect to take long in the background yourself", "meta": {"from": "journal"}}
{"content": "work 2168, Measure test coverage and raise it towards 100 percent, is still\u2026 \u2014 it was parked because: Coverage at about 98% in pull request 9, waiting for the user's approval; the last gaps need fixtures for terminals and restarts. journal work resume 2168 picks it up again.", "meta": {"from": "journal"}}
{"content": "work 2168, Measure test coverage and raise it towards 100 percent, is still\u2026 \u2014 it was parked because: Coverage at about 98% in pull request 9, waiting for the user's approval; the last gaps need fixtures for terminals and restarts. journal work resume 2168 picks it up again.", "meta": {"from": "journal"}}
{"content": "helper 126, Ingo Invite, reported in message 17413 \u2014 read it, then journal helper finish 126 once its work is taken or dropped", "meta": {"from": "journal"}}
{"content": "chat etiquette - a line from the journal is an instruction, not a message\u2026 \u2014 a turn that only handles a journal line needs no words: act on it, or say once in the chat what you wait on, then carry on; what the user needs to know still goes to the chat", "meta": {"from": "journal"}}
{"content": "the end tag does this in one step \u2014 [!end:N] makes the turn itself what landed; it runs only when it opens the last text of your turn", "meta": {"from": "journal"}}
{"content": "check 1 failed - features/session_briefing/test.py has 11 tests, over 10; what n \u2014 journal check show 1 says why; fix it, then journal check run 1", "meta": {"from": "journal"}}
{"content": "the todo tag does this in one step \u2014 [!todo=\"the title\"] files it with the turn as its brief; it runs only when it opens the last text of your turn", "meta": {"from": "journal"}}
{"content": "waiting: 1 unread worktree 85", "meta": {"from": "journal"}}
{"content": "helper 132, Gita Gitwise, reported in message 17439 \u2014 read it, then journal helper finish 132 once its work is taken or dropped", "meta": {"from": "journal"}}
{"content": "helper 131, Morris Mergeman, reported in message 17443 \u2014 read it, then journal helper finish 131 once its work is taken or dropped", "meta": {"from": "journal"}}
{"content": "the todo tag does this in one step \u2014 [!todo=\"the title\"] files it with the turn as its brief; it runs only when it opens the last text of your turn", "meta": {"from": "journal"}}
{"content": "Hector pushing the main hotfix, Ingo building the suggestion card, and Tilda\u2026", "meta": {"from": "journal"}}
{"content": "rule 48 \u2014 The viewer is built from its component library, and pages only\u2026 \u2014 Message 4258. Every visual piece the viewer shows more than once, or that a user would recognise as the same kind of thing (a dialog, a side panel or inspector, a dropdown, a list row, a switch, a button), is one component in web/src/kit, extracted aggressively, and every page composes those components instead of building its own copy. Before writing markup or styles in a page, look for the kit component that already does it and extend it with a prop; a second hand-built version is a bug. The side panel that animated in but not out, while a separate skill panel did both, is the example.", "meta": {"from": "journal"}}
{"content": "rule 41 \u2014 Keep moving, run the whole suite before every commit, never wait \u2014 The full suite runs in about seven seconds: .venv/bin/python -m pytest -q --timeout=300 -n auto. Run it before every commit instead of picking tests by name. Group rows that sit in the same code into one sitting: write them all, test once, commit once. And never wait, not for a subagent, a build, or an answer you can carry on without. Dispatch it and keep working. If you truly are waiting on something, say so in the work log.", "meta": {"from": "journal"}}
{"content": "rule 56 \u2014 Helpers are for work that writes; subagents read, research and design \u2014 The user, message 13464: there must be a clear distinction. A subagent can be dispatched for anything read-only: research, review, design. A helper is for actual work that writes, best in its own worktree when the work is separate. Dieter designing in Claude Design should have been a subagent, not a helper.", "meta": {"from": "journal"}}
{"content": "auto mode is on and work 2170 stands still while todo 3023 is ready \u2014 if work 2170 waits on the user, decide it yourself when you can; otherwise put the question on its row with journal todo ask, end or park the work, and start todo 3023. Stop only when nothing ready is left.; fact 18 \u2014 cProfile inflates the slow-request profiles about tenfold \u2014 The faults feature writes a profile when a request passes its budget, and the profile is taken with cProfile, which adds per-call overhead. On 2026-09-22 /api/summary profiled at 58ms with 48ms inside Resource.fork's deep copy; with the profiler off the same call ran in 2 to 7ms. Read the profile for where the time goes in relative terms, then time the call with curl before changing anything.; fact 26 \u2014 Claude Code reads agent profiles when a session starts \u2014 Seen 2026-09-26: after the board-filler's profile in .claude/agents gained its steps and the Grep rule, dispatches from the running session still used the old profile (a 3.5-minute first question, shell grep refused); after the session restarted, the same request took 21 seconds with 4 calls. A change to an agent type reaches only sessions started after it is written.", "meta": {"from": "journal"}}
{"content": "rule 60 \u2014 A hotfix is done by a dispatched agent in a worktree of main \u2014 Message 16836 (2026-10-06): the orchestrator cut a worktree under .claude/worktrees for a Codex hotfix, its session moved to a new environment and the user's messages stopped reaching it. The user: when working on a branch and a hotfix comes in, create a worktree of main and dispatch an agent to do that work. The orchestrator stays on its branch and in its environment, and never cds into another checkout.", "meta": {"from": "journal"}}
{"content": "fact 13 \u2014 This live session runs the installed copy in .journal/journal.pyz \u2014 The running journal (server, hooks, CLI) runs from .journal/journal.pyz with its viewer and skills in .journal/src, never from the repo. A change in the repo reaches it only through python3 src/journal.py --root .journal upgrade, which packs the zip again. A commit alone changes nothing that is running.; fact 31 \u2014 The overnight branch may be merged once every to-do is done and all\u2026 \u2014 Messages 16886 and 17009 (2026-10-06): the user said to keep working the to-do list on overnight-refactor; when every to-do item is finished and the whole suite is green, the agent may merge the pull request into main, then release a new minor version (message 17008). This is the user's go for rule 57's 'before its pull request is approved'. Until both hold, nothing of the branch goes to main except the hotfixes the user asks for.; law L5 \u2014 Every subagent dispatch names the agent - a human name, a little\u2026 \u2014 A name is how the user and the chat tell subagents apart and how they are messaged later; an id or a task line is not a name. Start the dispatch's description with the name, a colon, then the task, such as \"Dr. Einstein: profile the slow hooks\" or \"Coco Rams: draw the plan card\". A designer can borrow from famous designers, a researcher from famous scientists, mixed up for fun.; rule 38 \u2014 Never change the git branch until the user says so, by name \u2014 The work happens on the branch the user named. That was main until message 5929 and question 80 (2026-09-23), which moved the sins work to the branch sins. Do not create, switch to or merge any other branch unless the user names it in their own words.", "meta": {"from": "journal"}}
{"content": "rule 40 \u2014 A feature is named for what it is, never for its machinery \u2014 Messages 599, 600 and 703. A feature is a capability the user would name and would think of switching off. File tracking, a write gate, a phrase bank, a tree diff are services used inside a feature, not features of their own: they live in the feature they serve. Before adding a directory under features/, say what the user would call it; if the answer names a mechanism, it belongs inside something else. Report 16 holds the grouping this implies.", "meta": {"from": "journal"}}
{"content": "fact 25 \u2014 A designer's install packs the whole tree, half-done server edits\u2026 \u2014 2026-09-25: Eames and Saul run python3 src/journal.py --root .journal upgrade after their viewer builds; it packs every file in src, so a server handler I was halfway through writing went live and raised on every PostToolUse hook. While designers work in parallel, keep server edits whole between tool calls (write and test in the scratchpad first), and reinstall after reverting anything.; rule 27 \u2014 Name a declaration with the word a reader already knows \u2014 An attribute, a variable or a field gets the ordinary programming word for what it holds, not an evocative one. was, heard and alone were poetry; aliases, notify_actions and urgent_actions are what they are. The test: could a reader who has never seen this codebase guess what it holds from the name alone? Prose belongs in the help text and the abstract, where it is read as prose. This does not license abbreviations \u2014 a plain word in full, not a short one.; rule 49 \u2014 A dialog whose content grows keeps one fixed height, and its content\u2026 \u2014 Message 5361, after asking more than once: a dialog that shows output as it arrives (install, update, logs) opens at its final height and never jumps; only its content scrolls.", "meta": {"from": "journal"}}
{"content": "auto mode is on and work 2171 stands still while todo 3063 is ready \u2014 if work 2171 waits on the user, decide it yourself when you can; otherwise put the question on its row with journal todo ask, end or park the work, and start todo 3063. Stop only when nothing ready is left.", "meta": {"from": "journal"}}
{"content": "law L3 \u2014 Read narrowly - grep for the line, sed a range, head the file; never\u2026 \u2014 Everything a tool returns stays in the context for good and is paid for on every turn after it. Search before you read, read the range you need, and cap output with grep, head or tail. Read a whole file only when you need all of it.", "meta": {"from": "journal"}}
{"content": "work 2170, The phone app offers everything the desktop viewer does, is still\u2026 \u2014 it was parked because: Waiting on the three checks of pull request 13: security review, rules audit and the parity check-off. journal work resume 2170 picks it up again.; fact 24 \u2014 An answer followed by tool calls can be missing from Claude's\u2026 \u2014 Seen 2026-09-24 for messages 9391-9404: text blocks opening with [!reply:n] that were followed by tool calls never appeared in the session's jsonl (only thinking and tool_use rows did), so the journal never saw them and the replies were lost. When a turn goes on after answering, send the answer with journal message reply <n> \"<text>\" instead of the tag.; rule 54 \u2014 Settings and feature switches are read at boot and on change, never\u2026 \u2014 The user, message 13349: the application boots, determines every feature and setting once, and re-evaluates only when something changes, such as a setting or a plugin. Never lazy-load settings.; rule 58 \u2014 A design runs three critique rounds, then is built on a branch \u2014 Messages 17276 and 17281 (2026-10-06): the norm is a three-round cycle. Round by round, the designer designs (or revises), separate critic agents review the design through their lenses (the critic agent type, .claude/agents/critic.md: read-only, with a browser; one per lens, such as first-time, native, words and parity), and the designer adjusts it to their findings; three rounds in all. The three rounds stand in for the user's approval of the design: the user does not approve it. After the third round the design is built on a branch of its own, which ends in a pull request that waits for the user's approval (rule 61). Replaces message 15725's prototype approval.", "meta": {"from": "journal"}}
{"content": "law L1 \u2014 Every subagent dispatch names its model and chooses the least\u2026 \u2014 Use a fast, economical model for mechanical work with a known answer, a capable general model for careful implementation, and the strongest model only when the task turns on difficult judgement. Inheriting the orchestrator's model is not a model choice. If the dispatch API cannot accept a model, that operation is exempt.; rule 35 \u2014 Write clean code - one funnel per kind of operation, never the same\u2026 \u2014 Every kind of operation has one funnel: one method that creates, one that saves, one that refuses, one that formats. A second method that does the same thing under another name splits the behaviour, and the two drift apart. Before writing a method, search for the one that already does it and extend that. scripts/checks/funnels.py finds bodies written twice.", "meta": {"from": "journal"}}
{"content": "auto mode is on and work 2170 stands still while todo 3072 is ready \u2014 if work 2170 waits on the user, decide it yourself when you can; otherwise put the question on its row with journal todo ask, end or park the work, and start todo 3072. Stop only when nothing ready is left.; rule 45 \u2014 No prose words as names in code - said, says, heard, spoke, told\u2026 \u2014 Messages 1360 and 1698. The user has said more than once that code must not read like prose: a variable, attribute, property or function is named for what it holds or does (text, command, labels, lines), never with a verb from a story. 'says' on the Design type (1360) and 'said = call.said.lower()' in features/recital.py (1698) are the examples. Rule 27 states the naming rule; this one carries the words, so writing one of them whispers it. Before writing a name, ask whether a reader who has never seen the code would know what it holds.", "meta": {"from": "journal"}}
{"content": "hook POST /api/hook/claude is slower than its budget \u2014 271ms last (51ms of it working, 11ms collecting garbage, 1ms waiting on locks, then 1232ms more after it answered), against a budget of 50ms. Seen 3070 times.", "meta": {"from": "journal"}}
{"content": "rule 36 \u2014 Clean, DRY, idiomatic before it is committed, never after it is\u2026 \u2014 The user should never be the one who finds duplication, dead code, a clumsy name or a pattern the codebase does not use. Read the diff before every commit as a reviewer would, and fix what is not clean then, not in a follow-up after a complaint.; rule 39 \u2014 Use only registered exclamation response tags \u2014 A tag like [!reply:12] runs a command, and only the tags in the tags.runs setting are registered. An invented tag does nothing and shows as raw text in the chat. Use the registered ones (reply, log, end, todo, fact, rule) and nothing else.", "meta": {"from": "journal"}}
{"content": "fact 23 \u2014 Every upgrade brings system sequences and their triggers in line\u2026 \u2014 install.py runs ship_sequences after the migrations on each upgrade, so features/sequences/shipped.py is the whole source: change its wording and the next upgrade updates every journal, no migration needed. Shipped rows carry system=True and are read-only for everyone but SYSTEM (controllers/base.py _shipped).", "meta": {"from": "journal"}}
{"content": "work 2171, Measure test coverage and raise it towards 100 percent, is still\u2026 \u2014 it was parked because: Cora Coverall is raising coverage as helper 133. journal work resume 2171 picks it up again.; todo 3064, Code Commandments declares which projects it fits in its own\u2026 \u2014 it is blocked because: waits for pull request 10 to be approved and merged. If it is not any more, journal todo unblock 3064. If it waits on a person or a decision, make it a question to them: journal todo ask 3064 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 3072, Each voice profile names its own word for helpers and subagents, is\u2026 \u2014 it is blocked because: Vera Vocabulary is finishing pull request 11 and merges it herself. If it is not any more, journal todo unblock 3072. If it waits on a person or a decision, make it a question to them: journal todo ask 3072 \"<who decides what>\", and the row waits on their answer. Otherwise tell the user in the chat what it waits on, in their terms, and propose how to clear it.; request POST /api/run (todo done) is slower than its budget \u2014 1401ms last (454ms of it working, 4ms collecting garbage, 4ms waiting on locks, then 878ms more after it answered), against a budget of 50ms. Seen 4 times.", "meta": {"from": "journal"}}
{"content": "fact 33 \u2014 Every open pull request may be merged and released once ready \u2014 The user, messages 17401 and 17402 (2026-10-06): 'see that everything is merged and deployed to main when ready'. Covers pull requests 9 (test coverage), 10 (plugins fit), 11 (voice words for helpers), the suggestion card and phone-parity: each merges once it is rebased on main, reviewed with the findings fixed, and the suite and boot guard pass; then a release goes out.", "meta": {"from": "journal"}}
{"content": "work 2171, Measure test coverage and raise it towards 100 percent, is still\u2026 \u2014 it was parked because: Cora Coverall is raising coverage as helper 133. journal work resume 2171 picks it up again.", "meta": {"from": "journal"}}
{"content": "rule 42 \u2014 Every user-facing text passes the formatters before it leaves the\u2026 \u2014 Not only a brief. A title, an abstract, an outcome and every section body are read by a person, so each goes through the same formatters on its way to the viewer \u2014 chat turns, activity items, to-do rows, inspector pages, docs alike. One field formatted out of five is not a rule, it is an accident, and it is how a raw tag ended up in the activity list after the tags feature had been stripping them for weeks. When a new field carries words a person reads, it joins the list in the same place.", "meta": {"from": "journal"}}
{"content": "the formatter <lambda> hit an error \u2014 journal: the formatter <lambda> hit an error and kept going; the last of it is below and the whole of it is in .journal/runtime/engine.log. Fix it, then say so. engine.command_line.NotWired: no command line is wired into this process: import commands.cli at its entry", "meta": {"from": "journal"}}
{"content": "rule 50 \u2014 Everything the user does is doable in the viewer \u2014 Message 6710 (2026-09-23): the user never uses the CLI, only the UI; everything should be doable from the viewer. The journal commands are for agents; any action meant for the user (making boards, confirming, accepting, hosting, watching an agent) needs its place in the viewer.", "meta": {"from": "journal"}}
{"content": "your message 17455 names 638 without saying what they are \u2014 put the type before each number, like message 1712 or to-do 644, so the chat links it: journal message edit 17455 \"<the text>\"", "meta": {"from": "journal"}}
{"content": "your last message offers choices in prose \u2014 ask through journal question ask \"<one line>\" --set options='[{\"title\": \u2026, \"description\": \u2026}]' --set pick=<n>, so the viewer renders it; your writes wait until you do", "meta": {"from": "journal"}}
{"content": "rule 57 \u2014 Never merge the overnight refactor into main before its pull request\u2026 \u2014 Messages 15005, 15006, 15109, 15110 (2026-10-04): all refactor work goes on branch overnight-refactor and reaches the user as one pull request, which they read in the morning; nothing of it is merged into main until they say so. Hotfixes the user explicitly asks for go to main at once and are merged into the branch.; rule 61 \u2014 Features wait as pull requests until approved; only hotfixes merge\u2026 \u2014 Message 17118 (2026-10-06), after the overnight refactor merged as 2.252.0: start new work in a new branch, do not merge, write the pull request. Every pull request or new feature is parked until the user approves it. Hotfixes can be merged into main immediately (by a dispatched agent in a worktree of main, rule 60).", "meta": {"from": "journal"}}
{"content": "your message 17456 names 638 without saying what they are \u2014 put the type before each number, like message 1712 or to-do 644, so the chat links it: journal message edit 17456 \"<the text>\"; your message 17457 names 638 without saying what they are \u2014 put the type before each number, like message 1712 or to-do 644, so the chat links it: journal message edit 17457 \"<the text>\"; auto mode is on and work 2170 stands still while todo 3074 is ready \u2014 if work 2170 waits on the user, decide it yourself when you can; otherwise put the question on its row with journal todo ask, end or park the work, and start todo 3074. Stop only when nothing ready is left.", "meta": {"from": "journal"}}
{"content": "work 2171, Measure test coverage and raise it towards 100 percent, is still\u2026 \u2014 it was parked because: Cora Coverall is raising coverage as helper 133. journal work resume 2171 picks it up again.", "meta": {"from": "journal"}}
{"content": "auto mode is on and work 2170 stands still while todo 3084 is ready \u2014 if work 2170 waits on the user, decide it yourself when you can; otherwise put the question on its row with journal todo ask, end or park the work, and start todo 3084. Stop only when nothing ready is left.", "meta": {"from": "journal"}}
{"content": "chat etiquette - a line from the journal is an instruction, not a message\u2026 \u2014 a turn that only handles a journal line needs no words: act on it, or say once in the chat what you wait on, then carry on; what the user needs to know still goes to the chat", "meta": {"from": "journal"}}
{"content": "todo 3114 next; fact 32 \u2014 The mobile app's pull request may be merged once it is ready \u2014 Messages 17282 and 17283 (2026-10-06): the user gave permission to merge the pull request that builds the phone app's full feature set (to-do 3054) once it is ready, without waiting for approval. Ready means: the phone app can use every feature the desktop viewer has (checked against the design's inventory of desktop places and actions, each one marked done); three critique rounds done (rule 58); built on its own branch; the whole suite and boot guard green; and reviewed by two agents with their findings fixed, as pull request 8 was. This is the user's go for rule 61 for that one pull request only.; rule 59 \u2014 Every viewer heading and label says plainly what it is about \u2014 The user, messages 16499, 16839, 16844, 16989, 16992 and 16993 (2026-10-06), after 'Where the words count', 'Watch for the words in', 'This project', 'This browser' and 'Stop the journal' as tab names: viewer text reads like Linear, GitHub or Vercel. A place (page, tab, group, sidebar item) is a short noun: Settings, Project, Browser, Services, Updates, Plugins; never 'This project' or a phrase. A button is a verb for what happens: Stop, Install, Copy link, Pause the plan. A heading names what the reader looks at, and its options finish its sentence: 'Trigger when' / 'A word is written'. Plain literal words: no metaphor or whimsy ('kettle on, waiting'), no app speaking as I, none of the journal's internal words (row, hook, nudge, engine, slate). One word for one thing everywhere, sentence case, as short as it can be while clear. Applies to designers' prototypes, helpers' builds, the viewer's JavaScript lists, feature details, and shipped sequence and trigger titles alike.", "meta": {"from": "journal"}}
{"content": "fact 9 \u2014 Every public method on a controller becomes a journal command \u2014 The CLI is generated from the controllers: each public method of Controller, or of a typed controller, turns into journal <noun> <method>. A helper added to the base class therefore becomes a command on every type \u2014 which is how journal <type> handled and journal <type> refuse came to exist, from the CRUD funnel and the refusal funnel. An internal helper on a controller is named with a leading underscore, as _shaped and _status already are, or it ships as a command nobody meant.", "meta": {"from": "journal"}}
{"content": "waiting: 4 unread worktrees 86, 87, 88, 89", "meta": {"from": "journal"}}
{"content": "nothing is ready - every open row waits \u2014 to-do 3072, Each voice profile names its own word for helpers and subagents. For each that waits on a person or a decision, put it to them now with journal todo ask <n> \"<who decides what>\"; unblock any that can go on and work it. Stop only when each one waits on a question.", "meta": {"from": "journal"}}
{"content": "work 2170, The phone app offers everything the desktop viewer does, is still\u2026 \u2014 it was parked because: Helpers 134 to 136 and 138 are closing the parity gaps and security findings on phone-parity; question 206 waits on the user. journal work resume 2170 picks it up again.; rule 37 \u2014 Close every to-do explicitly with todo done or a Journal commit\u2026 \u2014 Ending work does not close its row. A to-do is closed by journal todo done <n> --how, or by a commit whose message carries Journal: todos done <n> at column 0, several numbers separated by commas. A row left open after its work landed misleads the next session and auto mode.", "meta": {"from": "journal"}}
{"content": "fact 18 \u2014 cProfile inflates the slow-request profiles about tenfold \u2014 The faults feature writes a profile when a request passes its budget, and the profile is taken with cProfile, which adds per-call overhead. On 2026-09-22 /api/summary profiled at 58ms with 48ms inside Resource.fork's deep copy; with the profiler off the same call ran in 2 to 7ms. Read the profile for where the time goes in relative terms, then time the call with curl before changing anything.; fact 26 \u2014 Claude Code reads agent profiles when a session starts \u2014 Seen 2026-09-26: after the board-filler's profile in .claude/agents gained its steps and the Grep rule, dispatches from the running session still used the old profile (a 3.5-minute first question, shell grep refused); after the session restarted, the same request took 21 seconds with 4 calls. A change to an agent type reaches only sessions started after it is written.", "meta": {"from": "journal"}}
{"content": "helper 136, Kurt Kitwell, reported in message 17470 \u2014 read it, then journal helper finish 136 once its work is taken or dropped", "meta": {"from": "journal"}}
{"content": "helper 136, Kurt Kitwell, reported in message 17474 \u2014 read it, then journal helper finish 136 once its work is taken or dropped", "meta": {"from": "journal"}}
{"content": "request POST /api/run (helper report) is slower than its budget \u2014 805ms last (176ms of it working, then 37ms more after it answered), against a budget of 50ms. Seen 4 times.", "meta": {"from": "journal"}}
{"content": "work 2171, Measure test coverage and raise it towards 100 percent, is still\u2026 \u2014 it was parked because: Cora Coverall is raising coverage as helper 133. journal work resume 2171 picks it up again.", "meta": {"from": "journal"}}
{"content": "you stopped 5 minutes ago with work 2170, The phone app offers everything the\u2026 \u2014 carry on with it now. If it waits on something outside your hands, say journal work await \"<what you wait for>\"; if it waits on the user, put the question on its row with journal todo ask and take the next ready row; if something else goes first, journal work park 2170 \"<why>\".", "meta": {"from": "journal"}}
{"content": "the await tag does this in one step \u2014 [!await] makes the rest of the turn what you wait for; [!await on=(\"<id>\", \"helper:<n>\")] waits on those; it runs only when it opens the last text of your turn", "meta": {"from": "journal"}}
{"content": "request POST /api/run (helper finish) is slower than its budget \u2014 1062ms last (205ms of it working, then 81ms more after it answered), against a budget of 50ms. Seen 59 times.", "meta": {"from": "journal"}}
{"content": "work 2171, Measure test coverage and raise it towards 100 percent, is still\u2026 \u2014 it was parked because: Cora Coverall is raising coverage as helper 133. journal work resume 2171 picks it up again.", "meta": {"from": "journal"}}
{"content": "helper 137, Usain Quickfoot, reported in message 17477 \u2014 read it, then journal helper finish 137 once its work is taken or dropped", "meta": {"from": "journal"}}
{"content": "helper 134, Chiara Chatwell, reported in message 17481 \u2014 read it, then journal helper finish 134 once its work is taken or dropped", "meta": {"from": "journal"}}
{"content": "helper 135, Silvio Setwell, reported in message 17485 \u2014 read it, then journal helper finish 135 once its work is taken or dropped", "meta": {"from": "journal"}}
{"content": "the todo tag does this in one step \u2014 [!todo=\"the title\"] files it with the turn as its brief; it runs only when it opens the last text of your turn", "meta": {"from": "journal"}}
{"content": "helper 138, Linus Lockwood, reported in message 17490 \u2014 read it, then journal helper finish 138 once its work is taken or dropped; auto mode is on and work 2170 stands still while todo 3122 is ready \u2014 if work 2170 waits on the user, decide it yourself when you can; otherwise put the question on its row with journal todo ask, end or park the work, and start todo 3122. Stop only when nothing ready is left.; Chiara, Silvio and Linus finishing the phone gaps and security fixes; question\u2026", "meta": {"from": "journal"}}
{"content": "The phone helpers Chiara, Silvio and Linus, and question 206 came back\u2026", "meta": {"from": "journal"}}
{"content": "check Chiara, Silvio and Linus are applying their follow-ups - wording\u2026 \u2014 look at the thing itself: the background shell's output, the process, the run's status. If it is still going, say journal work await \"<what you wait for>\" again and wait. If it finished or failed, journal work log what came of it and take the next step. Never wait for something you can do without.", "meta": {"from": "journal"}}
{"content": "helper 135, Silvio Setwell, reported in message 17492 \u2014 read it, then journal helper finish 135 once its work is taken or dropped", "meta": {"from": "journal"}}
{"content": "work 2171, Measure test coverage and raise it towards 100 percent, is still\u2026 \u2014 it was parked because: Cora Coverall is raising coverage as helper 133. journal work resume 2171 picks it up again.", "meta": {"from": "journal"}}
{"content": "your wait for Chiara, Silvio and Linus are each running their test suites\u2026 \u2014 say journal work await \"<what you wait for>\" again if you are still only waiting", "meta": {"from": "journal"}}
{"content": "chat etiquette - a line from the journal is an instruction, not a message\u2026 \u2014 a turn that only handles a journal line needs no words: act on it, or say once in the chat what you wait on, then carry on; what the user needs to know still goes to the chat; fact 9 \u2014 Every public method on a controller becomes a journal command \u2014 The CLI is generated from the controllers: each public method of Controller, or of a typed controller, turns into journal <noun> <method>. A helper added to the base class therefore becomes a command on every type \u2014 which is how journal <type> handled and journal <type> refuse came to exist, from the CRUD funnel and the refusal funnel. An internal helper on a controller is named with a leading underscore, as _shaped and _status already are, or it ships as a command nobody meant.", "meta": {"from": "journal"}}
{"content": "auto mode is on and work 2170 stands still while todo 3123 is ready \u2014 if work 2170 waits on the user, decide it yourself when you can; otherwise put the question on its row with journal todo ask, end or park the work, and start todo 3123. Stop only when nothing ready is left.; Chiara and Linus rebasing onto the phone branch with Silvio's work and\u2026", "meta": {"from": "journal"}}
{"content": "fact 32 \u2014 The mobile app's pull request may be merged once it is ready \u2014 Messages 17282 and 17283 (2026-10-06): the user gave permission to merge the pull request that builds the phone app's full feature set (to-do 3054) once it is ready, without waiting for approval. Ready means: the phone app can use every feature the desktop viewer has (checked against the design's inventory of desktop places and actions, each one marked done); three critique rounds done (rule 58); built on its own branch; the whole suite and boot guard green; and reviewed by two agents with their findings fixed, as pull request 8 was. This is the user's go for rule 61 for that one pull request only.", "meta": {"from": "journal"}}
{"content": "auto mode is on and work 2170 stands still while todo 3124 is ready \u2014 if work 2170 waits on the user, decide it yourself when you can; otherwise put the question on its row with journal todo ask, end or park the work, and start todo 3124. Stop only when nothing ready is left.", "meta": {"from": "journal"}}
{"content": "rule 41 \u2014 Keep moving, run the whole suite before every commit, never wait \u2014 The full suite runs in about seven seconds: .venv/bin/python -m pytest -q --timeout=300 -n auto. Run it before every commit instead of picking tests by name. Group rows that sit in the same code into one sitting: write them all, test once, commit once. And never wait, not for a subagent, a build, or an answer you can carry on without. Dispatch it and keep working. If you truly are waiting on something, say so in the work log.", "meta": {"from": "journal"}}
{"content": "auto mode is on and work 2170 stands still while todo 3125 is ready \u2014 if work 2170 waits on the user, decide it yourself when you can; otherwise put the question on its row with journal todo ask, end or park the work, and start todo 3125. Stop only when nothing ready is left.", "meta": {"from": "journal"}}
{"content": "rule 56 \u2014 Helpers are for work that writes; subagents read, research and design \u2014 The user, message 13464: there must be a clear distinction. A subagent can be dispatched for anything read-only: research, review, design. A helper is for actual work that writes, best in its own worktree when the work is separate. Dieter designing in Claude Design should have been a subagent, not a helper.", "meta": {"from": "journal"}}
{"content": "you stopped 5 minutes ago with work 2170, The phone app offers everything the\u2026 \u2014 carry on with it now. If it waits on something outside your hands, say journal work await \"<what you wait for>\"; if it waits on the user, put the question on its row with journal todo ask and take the next ready row; if something else goes first, journal work park 2170 \"<why>\".", "meta": {"from": "journal"}}
{"content": "Chiara and Linus finishing their phone follow-ups; then the second parity\u2026", "meta": {"from": "journal"}}
{"content": "Chiara and Linus running their suites", "meta": {"from": "journal"}}
{"content": "your chat talked about the journal's workings - \"Still waiting\" \u2014 the user sees replies, reactions, pills and reads themselves; say what the work is instead", "meta": {"from": "journal"}}
{"content": "work 2171, Measure test coverage and raise it towards 100 percent, is still\u2026 \u2014 it was parked because: Cora Coverall is raising coverage as helper 133. journal work resume 2171 picks it up again.", "meta": {"from": "journal"}}
{"content": "helper 139, Hermes Hastings, reported in message 17501 \u2014 read it, then journal helper finish 139 once its work is taken or dropped", "meta": {"from": "journal"}}
{"content": "rule 38 \u2014 Never change the git branch until the user says so, by name \u2014 The work happens on the branch the user named. That was main until message 5929 and question 80 (2026-09-23), which moved the sins work to the branch sins. Do not create, switch to or merge any other branch unless the user names it in their own words.; rule 60 \u2014 A hotfix is done by a dispatched agent in a worktree of main \u2014 Message 16836 (2026-10-06): the orchestrator cut a worktree under .claude/worktrees for a Codex hotfix, its session moved to a new environment and the user's messages stopped reaching it. The user: when working on a branch and a hotfix comes in, create a worktree of main and dispatch an agent to do that work. The orchestrator stays on its branch and in its environment, and never cds into another checkout.", "meta": {"from": "journal"}}
{"content": "fact 18 \u2014 cProfile inflates the slow-request profiles about tenfold \u2014 The faults feature writes a profile when a request passes its budget, and the profile is taken with cProfile, which adds per-call overhead. On 2026-09-22 /api/summary profiled at 58ms with 48ms inside Resource.fork's deep copy; with the profiler off the same call ran in 2 to 7ms. Read the profile for where the time goes in relative terms, then time the call with curl before changing anything.", "meta": {"from": "journal"}}
{"content": "you stopped 5 minutes ago with work 2170, The phone app offers everything the\u2026 \u2014 carry on with it now. If it waits on something outside your hands, say journal work await \"<what you wait for>\"; if it waits on the user, put the question on its row with journal todo ask and take the next ready row; if something else goes first, journal work park 2170 \"<why>\".", "meta": {"from": "journal"}}
{"content": "the await tag does this in one step \u2014 [!await] makes the rest of the turn what you wait for; [!await on=(\"<id>\", \"helper:<n>\")] waits on those; it runs only when it opens the last text of your turn", "meta": {"from": "journal"}}
{"content": "Chiara and Linus finishing their phone follow-ups and suites came back\u2026", "meta": {"from": "journal"}}
{"content": "Chiara folding the two terminal pages into one; Linus's last run", "meta": {"from": "journal"}}
{"content": "helper 134, Chiara Chatwell, reported in message 17507 \u2014 read it, then journal helper finish 134 once its work is taken or dropped", "meta": {"from": "journal"}}
{"content": "rule 35 \u2014 Write clean code - one funnel per kind of operation, never the same\u2026 \u2014 Every kind of operation has one funnel: one method that creates, one that saves, one that refuses, one that formats. A second method that does the same thing under another name splits the behaviour, and the two drift apart. Before writing a method, search for the one that already does it and extend that. scripts/checks/funnels.py finds bodies written twice.", "meta": {"from": "journal"}}
{"content": "work 2171, Measure test coverage and raise it towards 100 percent, is still\u2026 \u2014 it was parked because: Cora Coverall is raising coverage as helper 133. journal work resume 2171 picks it up again.", "meta": {"from": "journal"}}
{"content": "you stopped 5 minutes ago with work 2170, The phone app offers everything the\u2026 \u2014 carry on with it now. If it waits on something outside your hands, say journal work await \"<what you wait for>\"; if it waits on the user, put the question on its row with journal todo ask and take the next ready row; if something else goes first, journal work park 2170 \"<why>\".", "meta": {"from": "journal"}}
{"content": "helper 133, Cora Coverall, reported in message 17510 \u2014 read it, then journal helper finish 133 once its work is taken or dropped", "meta": {"from": "journal"}}
{"content": "waiting: 1 unread worktree 90", "meta": {"from": "journal"}}
{"content": "helper 138, Linus Lockwood, reported in message 17515 \u2014 read it, then journal helper finish 138 once its work is taken or dropped", "meta": {"from": "journal"}}
{"content": "Linus rebasing the security fixes; Paloma running the second parity check-off", "meta": {"from": "journal"}}
{"content": "helper 133, Cora Coverall, reported in message 17518 \u2014 read it, then journal helper finish 133 once its work is taken or dropped", "meta": {"from": "journal"}}
{"content": "fact 20 \u2014 A slim supervisor holds the agent and a worker reloads on every build \u2014 Since 2.118.0 (2026-09-23). src/supervisor.py is standard library only and never reloads: journal claude hands its process over to it (os.execv), and it owns the pty and the agent process, relays the terminal, writes the printed and screen captures, listens on the typist socket, restarts the agent in the same session from a relaunch command written to its runtime folder while a restart is pending, and stops it with escalation while draining the pty (an agent cannot finish exiting on macOS while its output is unread). It starts the worker (src/worker.py, which runs runner/worker.py; engine/worker.py stays as an alias for supervisors started before 2.201) and starts it again whenever it exits: RELOAD on a new build, RELAUNCH to restart the agent, STOP to end, HEAL or a quick crash to roll back a build through journal heal. The worker holds everything else: seating the session, the start-up confirm typed through the typist, services, viewer, update check, check-in, and the one-time relaunch of sessions launched before agents/terminal.py LAUNCH. agents/terminal.py holds only journal-side helpers. The server (serve.py) still runs the engines and re-execs itself on a .py change. When the agent exits, the supervisor runs journal ended, which puts set-aside hooks back and stops the server when no session is left.", "meta": {"from": "journal"}}
{"content": "the todo tag does this in one step \u2014 [!todo=\"the title\"] files it with the turn as its brief; it runs only when it opens the last text of your turn", "meta": {"from": "journal"}}
{"content": "fact 31 \u2014 The overnight branch may be merged once every to-do is done and all\u2026 \u2014 Messages 16886 and 17009 (2026-10-06): the user said to keep working the to-do list on overnight-refactor; when every to-do item is finished and the whole suite is green, the agent may merge the pull request into main, then release a new minor version (message 17008). This is the user's go for rule 57's 'before its pull request is approved'. Until both hold, nothing of the branch goes to main except the hotfixes the user asks for.; fact 33 \u2014 Every open pull request may be merged and released once ready \u2014 The user, messages 17401 and 17402 (2026-10-06): 'see that everything is merged and deployed to main when ready'. Covers pull requests 9 (test coverage), 10 (plugins fit), 11 (voice words for helpers), the suggestion card and phone-parity: each merges once it is rebased on main, reviewed with the findings fixed, and the suite and boot guard pass; then a release goes out.", "meta": {"from": "journal"}}
{"content": "think up what the user might ask for on board 12, Orchestrator \u2014 read its goal and cards (journal board show 12), then write 3 to 5 short things the user might ask for next, each one chip of at most 60 characters, in the user's words: journal board ideas 12 \"<idea>\" \"<idea>\" \"<idea>\". They replace the board's ideas under New work.; think up what the user might ask for on board 13, New work trials \u2014 read its goal and cards (journal board show 13), then write 3 to 5 short things the user might ask for next, each one chip of at most 60 characters, in the user's words: journal board ideas 13 \"<idea>\" \"<idea>\" \"<idea>\". They replace the board's ideas under New work.", "meta": {"from": "journal"}}
{"content": "rule 42 \u2014 Every user-facing text passes the formatters before it leaves the\u2026 \u2014 Not only a brief. A title, an abstract, an outcome and every section body are read by a person, so each goes through the same formatters on its way to the viewer \u2014 chat turns, activity items, to-do rows, inspector pages, docs alike. One field formatted out of five is not a rule, it is an accident, and it is how a raw tag ended up in the activity list after the tags feature had been stripping them for weeks. When a new field carries words a person reads, it joins the list in the same place.", "meta": {"from": "journal"}}
{"content": "helper 140, Colette Colorway, reported in message 17524 \u2014 read it, then journal helper finish 140 once its work is taken or dropped", "meta": {"from": "journal"}}
{"content": "rule 57 \u2014 Never merge the overnight refactor into main before its pull request\u2026 \u2014 Messages 15005, 15006, 15109, 15110 (2026-10-04): all refactor work goes on branch overnight-refactor and reaches the user as one pull request, which they read in the morning; nothing of it is merged into main until they say so. Hotfixes the user explicitly asks for go to main at once and are merged into the branch.", "meta": {"from": "journal"}}
{"content": "rule 61 \u2014 Features wait as pull requests until approved; only hotfixes merge\u2026 \u2014 Message 17118 (2026-10-06), after the overnight refactor merged as 2.252.0: start new work in a new branch, do not merge, write the pull request. Every pull request or new feature is parked until the user approves it. Hotfixes can be merged into main immediately (by a dispatched agent in a worktree of main, rule 60).", "meta": {"from": "journal"}}
{"content": "fact 9 \u2014 Every public method on a controller becomes a journal command \u2014 The CLI is generated from the controllers: each public method of Controller, or of a typed controller, turns into journal <noun> <method>. A helper added to the base class therefore becomes a command on every type \u2014 which is how journal <type> handled and journal <type> refuse came to exist, from the CRUD funnel and the refusal funnel. An internal helper on a controller is named with a leading underscore, as _shaped and _status already are, or it ships as a command nobody meant.", "meta": {"from": "journal"}}
{"content": "fact 32 \u2014 The mobile app's pull request may be merged once it is ready \u2014 Messages 17282 and 17283 (2026-10-06): the user gave permission to merge the pull request that builds the phone app's full feature set (to-do 3054) once it is ready, without waiting for approval. Ready means: the phone app can use every feature the desktop viewer has (checked against the design's inventory of desktop places and actions, each one marked done); three critique rounds done (rule 58); built on its own branch; the whole suite and boot guard green; and reviewed by two agents with their findings fixed, as pull request 8 was. This is the user's go for rule 61 for that one pull request only.", "meta": {"from": "journal"}}
{"content": "rule 50 \u2014 Everything the user does is doable in the viewer \u2014 Message 6710 (2026-09-23): the user never uses the CLI, only the UI; everything should be doable from the viewer. The journal commands are for agents; any action meant for the user (making boards, confirming, accepting, hosting, watching an agent) needs its place in the viewer.", "meta": {"from": "journal"}}
{"content": "waiting: 1 unread worktree 91", "meta": {"from": "journal"}}
{"content": "chat etiquette - a line from the journal is an instruction, not a message\u2026 \u2014 a turn that only handles a journal line needs no words: act on it, or say once in the chat what you wait on, then carry on; what the user needs to know still goes to the chat", "meta": {"from": "journal"}}
{"content": "helper 140, Colette Colorway, reported in message 17530 \u2014 read it, then journal helper finish 140 once its work is taken or dropped", "meta": {"from": "journal"}}
{"content": "helper 142, Cora Coverall, reported in message 17532 \u2014 read it, then journal helper finish 142 once its work is taken or dropped", "meta": {"from": "journal"}}
{"content": "the todo tag does this in one step \u2014 [!todo=\"the title\"] files it with the turn as its brief; it runs only when it opens the last text of your turn", "meta": {"from": "journal"}}
{"content": "your last message ran its paragraphs together \u2014 a blank line between parts is what makes a message readable: one thought to a paragraph", "meta": {"from": "journal"}}
{"content": "helper 141, Linus Lockwood, reported in message 17536 \u2014 read it, then journal helper finish 141 once its work is taken or dropped", "meta": {"from": "journal"}}
{"content": "Colette's chat settings, Linus's allow-list rework and Cora's two fixes came\u2026", "meta": {"from": "journal"}}
{"content": "auto mode is on and work 2170 stands still while todo 3136 is ready \u2014 if work 2170 waits on the user, decide it yourself when you can; otherwise put the question on its row with journal todo ask, end or park the work, and start todo 3136. Stop only when nothing ready is left.; fact 13 \u2014 This live session runs the installed copy in .journal/journal.pyz \u2014 The running journal (server, hooks, CLI) runs from .journal/journal.pyz with its viewer and skills in .journal/src, never from the repo. A change in the repo reaches it only through python3 src/journal.py --root .journal upgrade, which packs the zip again. A commit alone changes nothing that is running.; rule 59 \u2014 Every viewer heading and label says plainly what it is about \u2014 The user, messages 16499, 16839, 16844, 16989, 16992 and 16993 (2026-10-06), after 'Where the words count', 'Watch for the words in', 'This project', 'This browser' and 'Stop the journal' as tab names: viewer text reads like Linear, GitHub or Vercel. A place (page, tab, group, sidebar item) is a short noun: Settings, Project, Browser, Services, Updates, Plugins; never 'This project' or a phrase. A button is a verb for what happens: Stop, Install, Copy link, Pause the plan. A heading names what the reader looks at, and its options finish its sentence: 'Trigger when' / 'A word is written'. Plain literal words: no metaphor or whimsy ('kettle on, waiting'), no app speaking as I, none of the journal's internal words (row, hook, nudge, engine, slate). One word for one thing everywhere, sentence case, as short as it can be while clear. Applies to designers' prototypes, helpers' builds, the viewer's JavaScript lists, feature details, and shipped sequence and trigger titles alike.", "meta": {"from": "journal"}}
{"content": "fact 30 \u2014 The tunler server refuses TLS for any subdomain without a tunnel \u2014 Seen 2026-10-04 in the server's docker logs (ssh root@tunler.jessegall.nl, container tunler): 'TLS handshake error ... host \"journal-probe.tunler.jessegall.nl\" not allowed'. A made-up subdomain never answers even when the server is healthy; probe https://tunler.jessegall.nl/ for the server itself. Root SSH to the server works.", "meta": {"from": "journal"}}
{"content": "you stopped 5 minutes ago with work 2170, The phone app offers everything the\u2026 \u2014 carry on with it now. If it waits on something outside your hands, say journal work await \"<what you wait for>\"; if it waits on the user, put the question on its row with journal todo ask and take the next ready row; if something else goes first, journal work park 2170 \"<why>\".", "meta": {"from": "journal"}}
{"content": "helper 141, Linus Lockwood, reported in message 17541 \u2014 read it, then journal helper finish 141 once its work is taken or dropped", "meta": {"from": "journal"}}
{"content": "waiting: 1 unread worktree 92", "meta": {"from": "journal"}}
{"content": "helper 143, Bootsy Steadman, reported in message 17548 \u2014 read it, then journal helper finish 143 once its work is taken or dropped; you stopped 7 minutes ago with work 2170, The phone app offers everything the\u2026 \u2014 carry on with it now. If it waits on something outside your hands, say journal work await \"<what you wait for>\"; if it waits on the user, put the question on its row with journal todo ask and take the next ready row; if something else goes first, journal work park 2170 \"<why>\".; Linus finishing the allow list, its three findings and the wording; Bootsy on\u2026", "meta": {"from": "journal"}}
{"content": "the await tag does this in one step \u2014 [!await] makes the rest of the turn what you wait for; [!await on=(\"<id>\", \"helper:<n>\")] waits on those; it runs only when it opens the last text of your turn", "meta": {"from": "journal"}}
{"content": "fact 24 \u2014 An answer followed by tool calls can be missing from Claude's\u2026 \u2014 Seen 2026-09-24 for messages 9391-9404: text blocks opening with [!reply:n] that were followed by tool calls never appeared in the session's jsonl (only thinking and tool_use rows did), so the journal never saw them and the replies were lost. When a turn goes on after answering, send the answer with journal message reply <n> \"<text>\" instead of the tag.; rule 46 \u2014 Only commit and push once the whole journal is proven to boot \u2014 Messages 2178 and 2179. A release that has not been started for real can crash every project that installs it, as 2.78.3 did for Codex and 2.84.0 did to project records. Before every commit and push: the full suite passes, including tests/test_it_boots.py, which installs a packed copy into a fresh project, launches Claude and Codex from it, writes a project record, upgrades again and checks the record survives. When a change touches launching, installing or upgrading, also start a real journal in a scratch project and close it properly afterwards, leaving no process behind.", "meta": {"from": "journal"}}
{"content": "your last message ran its paragraphs together \u2014 a blank line between parts is what makes a message readable: one thought to a paragraph; auto mode is on and work 2170 stands still while todo 3145 is ready \u2014 if work 2170 waits on the user, decide it yourself when you can; otherwise put the question on its row with journal todo ask, end or park the work, and start todo 3145. Stop only when nothing ready is left.", "meta": {"from": "journal"}}
{"content": "rule 55 \u2014 Always dispatch Codex helpers on gpt-6-sol \u2014 The user's word, message 13431: switch the codex agents to GPT-6-Sol and make it their default. ~/.codex/config.toml names it as the default model too.", "meta": {"from": "journal"}}
