{"content": "commit d89c6a279 closed to-do 1471 \u2014 The rows and the work are done; take the next one.; commit a43fc9dfd closed to-do 1439, to-do 1446, to-do 1447 \u2014 The rows and the work are done; take the next one.; 1 new message 8727 - answer by opening your turn with [!reply:8727]", "meta": {"from": "journal"}}
{"content": "your wait for the full suite for the storage change is over, because you are\u2026 \u2014 say journal work await \"<what you wait for>\" again if you are still only waiting", "meta": {"from": "journal"}}
{"content": "commit f9c27563e closed to-do 1357, to-do 1450 \u2014 The rows and the work are done; take the next 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": "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 engine/worker.py 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 engine/terminal.py LAUNCH. engine/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": "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": "request GET /api/main/dashboard is slower than its budget \u2014 276ms last (196ms of it working), against a budget of 50ms. Seen 799 times.", "meta": {"from": "journal"}}
{"content": "work 1212, Fix the findings the new code-commandments rules raise, is still\u2026 \u2014 it was parked because: tool output in the terminal (to-do 1375) goes first. journal work resume 1212 picks it up again.", "meta": {"from": "journal"}}
{"content": "commit f46577514 closed to-do 1453, to-do 1456, to-do 1457, to-do 1458, to-do\u2026 \u2014 The rows and the work are done; take the next one.", "meta": {"from": "journal"}}
{"content": "your message 8749 names 1483, 1484, 1490 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 8749 \"<the text>\"; 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": "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": "work 1310 in hand \u2014 Worktree links are excluded from git before they are made \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": "commit b68036b6b closed to-do 1506, to-do 1483, to-do 1484, to-do 1490, to-do\u2026 \u2014 The rows and the work are done; take the next one.", "meta": {"from": "journal"}}
{"content": "commit 976f9e2ac closed to-do 1482, to-do 1485, to-do 1486, to-do 1488, to-do\u2026 \u2014 The rows and the work are done; take the next one.", "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 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": "commit 49d7039b3 closed to-do 1493 \u2014 The rows and the work are done; take the next one.", "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 wait for the full suite for the session fixes is over, because you are\u2026 \u2014 say journal work await \"<what you wait for>\" again if you are still only waiting", "meta": {"from": "journal"}}
{"content": "work 1212, Fix the findings the new code-commandments rules raise, is still\u2026 \u2014 it was parked because: tool output in the terminal (to-do 1375) goes first. journal work resume 1212 picks it up again.; commit 7bb8e01b3 closed to-do 1494, to-do 1495 \u2014 The rows and the work are done; take the next one.", "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.; 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 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": "your wait for the full suite for the session lock and switch is over, because\u2026 \u2014 say journal work await \"<what you wait for>\" again if you are still only waiting", "meta": {"from": "journal"}}
{"content": "work 1314 is still open \u2014 end it or park it before you stop: journal work end 1314 --how \"<what landed>\", or journal work park 1314 \"<why it waits>\"", "meta": {"from": "journal"}}
{"content": "commit 733a4cba5 closed to-do 1503, to-do 1504, to-do 1505 \u2014 The rows and the work are done; take the next one.", "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 engine/worker.py 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 engine/terminal.py LAUNCH. engine/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": "auto mode is on and work 1315 stands still while todo 1360 is ready \u2014 if work 1315 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 1360. Stop only when nothing ready is left.; work 1315 is still open, with nothing logged \u2014 journal work log 1315 \"<what was decided or done, and why>\" \u2014 then journal work end 1315 --how \"<what landed>\", or journal work park 1315 \"<why it waits>\"", "meta": {"from": "journal"}}
{"content": "commit 103b6c532 closed to-do 1496, to-do 1497 \u2014 The rows and the work are done; take the next one.", "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.; 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": "commit 0181a137f closed to-do 1498 \u2014 The rows and the work are done; take the next one.", "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": "commit 18c657bae closed to-do 1499, to-do 1500 \u2014 The rows and the work are done; take the next one.", "meta": {"from": "journal"}}
{"content": "commandments-python-value-objects, journal-boards 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": "commit a2978c2c2 closed to-do 1473, to-do 1474, to-do 1476, to-do 1477, to-do\u2026 \u2014 The rows and the work are done; take the next one.", "meta": {"from": "journal"}}
{"content": "auto mode is on and work 1322 stands still while todo 1442 is ready \u2014 if work 1322 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 1442. Stop only when nothing ready is left.; work 1322 is still open, with nothing logged \u2014 journal work log 1322 \"<what was decided or done, and why>\" \u2014 then journal work end 1322 --how \"<what landed>\", or journal work park 1322 \"<why it waits>\"", "meta": {"from": "journal"}}
{"content": "you ran the same check 3 times in a row - sed -n 1,110p\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": "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": "work 1322 in hand \u2014 New work never strands picked cards when the agent stays\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": "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 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 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": "you ran the same check 3 times in a row - python3 - <<'EOF' \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 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": "request GET /api/main/dashboard is slower than its budget \u2014 55ms last (53ms of it working), against a budget of 50ms. Seen 805 times.", "meta": {"from": "journal"}}
{"content": "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": "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 1322 in hand \u2014 New work never strands picked cards when the agent stays\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": "fact 22 \u2014 A shipped sequence change reaches existing journals only through a\u2026 \u2014 features/sequences/shipped.py ship() runs from migrations (m0022, m0028, m0029), and each migration runs once per record. Since 2026-09-24 ship() brings a system sequence's brief, start and steps in step with the code, but only when a migration calls it: a wording change needs a new mNNNN file that re-exports m0022's run.; 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 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 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": "work 1212, Fix the findings the new code-commandments rules raise, is still\u2026 \u2014 it was parked because: tool output in the terminal (to-do 1375) goes first. journal work resume 1212 picks it up again.; commit 6c8d9c798 closed to-do 1441, to-do 1442, to-do 1443, to-do 1444, to-do\u2026 \u2014 The rows and the work are done; take the next one.", "meta": {"from": "journal"}}
{"content": "your message 8800 names 1468, 1469 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 8800 \"<the text>\"", "meta": {"from": "journal"}}
{"content": "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 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": "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": "commit 9af737f56 closed to-do 1465, to-do 1468, to-do 1469, to-do 1470, to-do\u2026 \u2014 The rows and the work are done; take the next one.", "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": "commit 3036b53c0 closed to-do 1460, to-do 1459, to-do 1455 and ended work 1324 \u2014 The rows and the work are done; take the next one.", "meta": {"from": "journal"}}
{"content": "your message 8809 names 265 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 8809 \"<the text>\"", "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": "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": "commit aa8999dcf closed to-do 1502 and ended work 1325 \u2014 The rows and the work are done; take the next one.", "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": "work 1327 in hand \u2014 One viewer tab per environment, several environments side\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": "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 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": "commit fdf92afd7 closed to-do 1426 and ended work 1327 \u2014 The rows and the work are done; take the next one.", "meta": {"from": "journal"}}
{"content": "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": "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": "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 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 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 chat talked about the journal's workings - \"To-do 1274 was already closed\" \u2014 the user sees replies, reactions, pills and reads themselves; say what the work is instead; your message 8830 names 1425, 1405 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 8830 \"<the text>\"", "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.; 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": "POST /api/main/todo/tasks hit an error \u2014 journal: POST /api/main/todo/tasks 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. TypeError: Todos.tasks() missing 1 required positional argument: 'agent'", "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 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": "work 1212, Fix the findings the new code-commandments rules raise, is still\u2026 \u2014 it was parked because: tool output in the terminal (to-do 1375) goes first. journal work resume 1212 picks it up again.; commit 6a998c017 closed to-do 1416, to-do 1418, to-do 1507 and ended work\u2026 \u2014 The rows and the work are done; take the next one.", "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.; 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": "work 1329 in hand \u2014 GET /api/summary runs past its budget \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": "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": "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 1329 in hand \u2014 GET /api/summary runs past its budget \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": "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": "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 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": "request GET /api/main/dashboard is slower than its budget \u2014 79ms last (64ms of it working), against a budget of 50ms. Seen 806 times.", "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": "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": "commit 65197f64c closed to-do 1424, to-do 1425, to-do 1405, to-do 1383 and\u2026 \u2014 The rows and the work are done; take the next one.", "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 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 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 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": "your message 8859 names 1366, 1389 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 8859 \"<the text>\"", "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.", "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.", "meta": {"from": "journal"}}
{"content": "commit 916c79b58 closed to-do 1360 and ended work 1333 \u2014 The rows and the work are done; take the next one.", "meta": {"from": "journal"}}
{"content": "sequence 2, Building a plan, step 1 of 4 - Name the goal \u2014 Settle with the user what is true when the plan is done, and set it as the plan's goal. When it is done: journal sequence next 2 --about plan:15; plan 15 is building - add its phases \u2014 journal plan phase 15 \"<title>\" --when \"<complete when>\" for each phase, --checkpoint where the user should look; then journal plan stage 15 todos", "meta": {"from": "journal"}}
{"content": "fact 22 \u2014 A shipped sequence change reaches existing journals only through a\u2026 \u2014 features/sequences/shipped.py ship() runs from migrations (m0022, m0028, m0029), and each migration runs once per record. Since 2026-09-24 ship() brings a system sequence's brief, start and steps in step with the code, but only when a migration calls it: a wording change needs a new mNNNN file that re-exports m0022's run.", "meta": {"from": "journal"}}
{"content": "sequence 2, Building a plan, step 2 of 4 - Add the phases \u2014 Add every phase in order with journal plan phase <n> \"<title>\" --when \"<complete when>\", and --checkpoint where the user should look before it goes on. When it is done: journal sequence next 2 --about plan:15; plan 15 is at its to-dos \u2014 file each phase's rows and put them under it with journal plan todos 15 <phase> <rows...>; when every phase has rows, journal plan ready 15", "meta": {"from": "journal"}}
{"content": "sequence 2, Building a plan, step 3 of 4 - File the rows \u2014 journal plan stage <n> todos, then file the to-dos and put each under its phase with journal plan todos <n> <phase> <rows>. When it is done: journal sequence next 2 --about plan:15; every phase of plan 15 has its to-dos \u2014 journal plan ready 15 hands it to the user, who approves it; sequence 2, Building a plan, step 4 of 4 - Hand it over \u2014 When every phase has rows, journal plan ready <n>. Only the user approves it; you start it when they have. When it is done: journal sequence next 2 --about plan:15", "meta": {"from": "journal"}}
{"content": "todo 1408 next; 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.; 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.; 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 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 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 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": "your last message ran its paragraphs together \u2014 a blank line between parts is what makes a message readable: one thought to a paragraph; todo 1510 next", "meta": {"from": "journal"}}
{"content": "waiting: 1 unread sequence 5", "meta": {"from": "journal"}}
{"content": "request GET /api/main/dashboard is slower than its budget \u2014 281ms last (177ms of it working), against a budget of 50ms. Seen 808 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": "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": "work 1335 in hand \u2014 The first dashboard after a reload runs past its budget \u2014 if this is not what you are doing, end it or park it and start the work you are in; 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": "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 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 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": "work 1335 is still open \u2014 end it or park it before you stop: journal work end 1335 --how \"<what landed>\", or journal work park 1335 \"<why it waits>\"", "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; work 1212, Fix the findings the new code-commandments rules raise, is still\u2026 \u2014 it was parked because: tool output in the terminal (to-do 1375) goes first. journal work resume 1212 picks it up again.; todo 1372, Resources scoped to an environment or the whole project, is still\u2026 \u2014 it is blocked because: The scope design is iterated with the user in the chat first. If it is not any more, journal todo unblock 1372. If it is, tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 1399, Tell the code-commandments agent when a release carries the\u2026 \u2014 it is blocked because: Waits for the user's release that carries the collapsed card key. If it is not any more, journal todo unblock 1399. If it is, tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 1408, Share a journal with other users, is still blocked - is it still? \u2014 it is blocked because: Its plan, plan 15, waits for the user's approval. If it is not any more, journal todo unblock 1408. If it is, tell the user in the chat what it waits on, in their terms, and propose how to clear it.; commit f1818d3f3 closed to-do 1516 and ended work 1335 \u2014 The rows and the work are done; take the next one.", "meta": {"from": "journal"}}
{"content": "rule 44 \u2014 Release only when the user says so, never after every change \u2014 Message 5929 (2026-09-23): stop releasing constantly. Work is committed on a branch and released only when the user says so. For now nothing is released until every Code Commandments sin is fixed. This replaces message 1067's order to push and tag every update at once.", "meta": {"from": "journal"}}
{"content": "request GET /api/main/dashboard is slower than its budget \u2014 182ms last (158ms of it working), against a budget of 50ms. Seen 810 times.", "meta": {"from": "journal"}}
{"content": "work 1337 is still open, with nothing logged \u2014 journal work log 1337 \"<what was decided or done, and why>\" \u2014 then journal work end 1337 --how \"<what landed>\", or journal work park 1337 \"<why it waits>\"", "meta": {"from": "journal"}}
{"content": "your command ran 30s 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; commit 6be11d1e8 closed to-do 1517 and ended work 1337 \u2014 The rows and the work are done; take the next one.", "meta": {"from": "journal"}}
{"content": "request GET /api/summary is slower than its budget \u2014 1029ms last (154ms of it working), against a budget of 50ms. Seen 82 times.", "meta": {"from": "journal"}}
{"content": "1 new message 8910 - answer by opening your turn with [!reply:8910]", "meta": {"from": "journal"}}
{"content": "answer message 8910 before you write anything \u2014 answer by opening your turn with [!reply:8910]. a reply, a reaction, or journal message processed <n>", "meta": {"from": "journal"}}
{"content": "1 new message 8912 - answer by opening your turn with [!reply:8912]", "meta": {"from": "journal"}}
{"content": "request GET /api/main/dashboard is slower than its budget \u2014 69ms last (50ms of it working), against a budget of 50ms. Seen 812 times.", "meta": {"from": "journal"}}
{"content": "todo 1518 next", "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 1212, Fix the findings the new code-commandments rules raise, is still\u2026 \u2014 it was parked because: tool output in the terminal (to-do 1375) goes first. journal work resume 1212 picks it up again.", "meta": {"from": "journal"}}
{"content": "1 new message 8919 - answer by opening your turn with [!reply:8919]", "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 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.; 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": "1 new message 8937 - answer by opening your turn with [!reply:8937]", "meta": {"from": "journal"}}
{"content": "message 8937 deleted", "meta": {"from": "journal"}}
{"content": "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 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": "there are new messages in your inbox \u2014 journal message unread, then journal message read <n> for each; todo 1519 next; 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.; 1 new message 8938 - answer by opening your turn with [!reply:8938]", "meta": {"from": "journal"}}
{"content": "there are new messages in your inbox \u2014 journal message unread, then journal message read <n> for each; todo 1519 next", "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.", "meta": {"from": "journal"}}
{"content": "1 new message 8945 - answer by opening your turn with [!reply:8945]", "meta": {"from": "journal"}}
{"content": "1 new message 8947 - answer by opening your turn with [!reply:8947]", "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 44 \u2014 Release only when the user says so, never after every change \u2014 Message 5929 (2026-09-23): stop releasing constantly. Work is committed on a branch and released only when the user says so. For now nothing is released until every Code Commandments sin is fixed. This replaces message 1067's order to push and tag every update at once.; 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 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": "the viewer threw Cannot read properties of null (reading 'color') \u2014 Cannot read properties of null (reading 'color') / TypeError: Cannot read properties of null (reading 'color') at Proxy.<anonymous> (http://127.0.0.1:8424/assets/index-D-ER0VRl.js:46:185695) at Oc (http://127.0.0.1:8424/assets/index-D-ER0VRl.js:13:23097) at Pd.Oe [as fn] (http://127.0. Seen 1 time.", "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": "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": "request GET /api/main/dashboard is slower than its budget \u2014 64ms last (55ms of it working), against a budget of 50ms. Seen 818 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.", "meta": {"from": "journal"}}
{"content": "auto mode is on and work 1343 stands still while todo 1521 is ready \u2014 if work 1343 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 1521. Stop only when nothing ready is left.; work 1343 is still open \u2014 end it or park it before you stop: journal work end 1343 --how \"<what landed>\", or journal work park 1343 \"<why it waits>\"", "meta": {"from": "journal"}}
{"content": "1 new message 8960 - answer by opening your turn with [!reply:8960]", "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.; 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": "work 1212, Fix the findings the new code-commandments rules raise, is still\u2026 \u2014 it was parked because: tool output in the terminal (to-do 1375) goes first. journal work resume 1212 picks it up again.; todo 1408, Share a journal with other users, is still blocked - is it still? \u2014 it is blocked because: Its plan, plan 15, waits for the user's approval. If it is not any more, journal todo unblock 1408. If it is, tell the user in the chat what it waits on, in their terms, and propose how to clear it.; commit b2bf0d698 closed to-do 1519, to-do 1520, to-do 1521 and ended work\u2026 \u2014 The rows and the work are done; take the next one.", "meta": {"from": "journal"}}
{"content": "1 new message 8968 - answer by opening your turn with [!reply:8968]", "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": "1 new message 8969 - answer by opening your turn with [!reply:8969]", "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.", "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": "your message 8975 names 8395 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 8975 \"<the text>\"", "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 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": "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": "auto mode is on and work 1345 stands still while todo 1372 is ready \u2014 if work 1345 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 1372. Stop only when nothing ready is left.; work 1345 is still open \u2014 end it or park it before you stop: journal work end 1345 --how \"<what landed>\", or journal work park 1345 \"<why it waits>\"; request GET /api/main/dashboard is slower than its budget \u2014 152ms last (83ms of it working), against a budget of 50ms. Seen 821 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.; journal-facts, journal-reminders, journal-rules 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": "todo 1372 next", "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; todo 1372 next", "meta": {"from": "journal"}}
{"content": "fact 22 \u2014 A shipped sequence change reaches existing journals only through a\u2026 \u2014 features/sequences/shipped.py ship() runs from migrations (m0022, m0028, m0029), and each migration runs once per record. Since 2026-09-24 ship() brings a system sequence's brief, start and steps in step with the code, but only when a migration calls it: a wording change needs a new mNNNN file that re-exports m0022's run.", "meta": {"from": "journal"}}
{"content": "question 132 completed", "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": "todo 1372 next", "meta": {"from": "journal"}}
{"content": "1 new message 8987 - answer by opening your turn with [!reply:8987]", "meta": {"from": "journal"}}
{"content": "1 new message 8988 - answer by opening your turn with [!reply:8988]", "meta": {"from": "journal"}}
{"content": "1 new message 8990 - answer by opening your turn with [!reply:8990]", "meta": {"from": "journal"}}
{"content": "1 new message 8993 - answer by opening your turn with [!reply:8993]", "meta": {"from": "journal"}}
{"content": "your wait for Massimo's sticky Settings headers is over, because you are\u2026 \u2014 say journal work await \"<what you wait for>\" again if you are still only waiting", "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": "work 1212, Fix the findings the new code-commandments rules raise, is still\u2026 \u2014 it was parked because: tool output in the terminal (to-do 1375) goes first. journal work resume 1212 picks it up again.; todo 1372, Resources scoped to an environment or the whole project, is still\u2026 \u2014 it is blocked because: The user said to keep scopes as they are for now (message 8987). If it is not any more, journal todo unblock 1372. If it is, tell the user in the chat what it waits on, in their terms, and propose how to clear it.; todo 1408, Share a journal with other users, is still blocked - is it still? \u2014 it is blocked because: Its plan, plan 15, waits for the user's approval. If it is not any more, journal todo unblock 1408. If it is, tell the user in the chat what it waits on, in their terms, and propose how to clear it.; commit c463dce37 closed to-do 1524, to-do 1525 and ended work 1346 \u2014 The rows and the work are done; take the next one.", "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"}}
