{"content": "todo 1 next", "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": "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).; 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": "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 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 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": "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 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": "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", "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 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": "that Bash call returned 27,755 characters, the largest this session \u2014 It stays in the context for good. If you were looking for one thing in it, the next read can be narrower: grep for the line, sed a range, head the file.", "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 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 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 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 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 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 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 44 \u2014 Release a new version after every significant change \u2014 The user, message 13219 (2026-10-01): 'Don't forget to release new versions every time you do something significant.' Bump VERSION, add a CHANGELOG entry, push main and the tag. Replaces message 5929's release-on-request.; 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.", "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.; 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 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": "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 1 in hand \u2014 Build personality profiles as rows, their dialog and their\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": "Code Commandments found 7 sins across 3 skills. \u2014 journal check show 29 says why; fix it, then journal check run 29", "meta": {"from": "journal"}}
{"content": "check 28 failed - 1 failed, 1 passed in 220.83s (0 -03 -40) \u2014 journal check show 28 says why; fix it, then journal check run 28; check 4 failed - 2 failed, 418 passed in 220.88s (0 -03 -40) \u2014 journal check show 4 says why; fix it, then journal check run 4", "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": "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": "check 27 failed - 1 failed, 419 passed in 250.12s (0 -04 -10) \u2014 journal check show 27 says why; fix it, then journal check run 27", "meta": {"from": "journal"}}
{"content": "waiting: 4 unread profiles 1, 2, 3, 4", "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 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": "waiting: 4 unread profiles 1, 2, 3, 4", "meta": {"from": "journal"}}
{"content": "waiting: 4 unread profiles 1, 2, 3, 4", "meta": {"from": "journal"}}
{"content": "waiting: 4 unread profiles 1, 2, 3, 4", "meta": {"from": "journal"}}
{"content": "waiting: 4 unread profiles 1, 2, 3, 4", "meta": {"from": "journal"}}
{"content": "waiting: 4 unread profiles 1, 2, 3, 4", "meta": {"from": "journal"}}
{"content": "waiting: 4 unread profiles 1, 2, 3, 4", "meta": {"from": "journal"}}
{"content": "waiting: 4 unread profiles 1, 2, 3, 4", "meta": {"from": "journal"}}
{"content": "waiting: 4 unread profiles 1, 2, 3, 4", "meta": {"from": "journal"}}
{"content": "waiting: 4 unread profiles 1, 2, 3, 4", "meta": {"from": "journal"}}
{"content": "waiting: 4 unread profiles 1, 2, 3, 4", "meta": {"from": "journal"}}
{"content": "your chat talked about the journal's workings - \"Nothing is waiting\" \u2014 the user sees replies, reactions, pills and reads themselves; say what the work is instead", "meta": {"from": "journal"}}
{"content": "Dieter checked your build against his prototype. Two are urgent because the build is live: fix them first. 1. pages/ProfilesEditor.vue line 20 reads store.settings.form_of_address before settings load, so a direct load of Settings throws 'Cannot read properties of null' and the editor never renders. Read through the guarded form() in composables/profiles.js. 2. At phone width Settings \u203a Agent opens on 'Your title and name' and the profile editor is missing: show ProfilesEditor in the phone layout. Then: 3. Rewrite the four shipped samples so each answers the sample question 'Is the fix in?' (they talk about a release now). 4. sampleOf: with no name, drop the name and the punctuation around it ('Done, ! Release\u2026' and 'Nice work, : \u2026' today). 5. Duplicate stores the copy's sample with the name filled in, not {you}. 6. FirstChoiceDialog on a phone: the hint line on top, the buttons stacked full width. 7. Butler's voice text as the user would write it: 'my title', 'when I call you sir', not 'their' and 'they'. 8. 'Your title and name' gets its own heading, the line 'Profiles that use your title and name call you \"Sir Jesse\"' (from the setting), and a gap above it. Rebase onto overnight-refactor once it holds the commit 'A UnitTextInput in the kit\u2026' (a gate is running); for the dist conflict take upstream's dist and rebuild. Full suite, commit dist last, report as before. Screenshots: /private/tmp/claude-501/-Users-jessegall-projects-agent-journal/c35e7375-7ce3-4bc3-b1ae-7cdf73bd1488/scratchpad/v3/shots", "meta": {"from": "main"}}
{"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": "you stopped 5 minutes ago with work 2, Dieter's review fixes for the profile\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 2 \"<why>\".", "meta": {"from": "journal"}}
{"content": "the full suite, queued on the shared suite lock came back - cd\u2026", "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 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", "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": "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": "From now on, never commit src/web/dist: commit only your source changes, and I build the viewer once after taking your work (your own vite build for checking in a browser stays local and uncommitted). If your branch already has a dist commit on top, drop it when you next rebase (git rebase -i is not available; use git rebase --onto or reset --soft and recommit your source). The tip of overnight-refactor moves soon with the commit 'The Documents list shows summaries in plain words'; rebase onto that when you are ready to report.", "meta": {"from": "main"}}
{"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": "work deferred in words, not parked \u2014 \"I'll do that\" is the title of a to-do: journal todo create \"<title>\" --brief, then say so", "meta": {"from": "journal"}}
{"content": "todo 2 next", "meta": {"from": "journal"}}
{"content": "nothing is ready - every open row waits \u2014 to-do 2, Rebase the profile review fixes onto the moved overnight-refactor. 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": "nothing is ready - every open row waits \u2014 to-do 2, Rebase the profile review fixes onto the moved overnight-refactor. 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": "your chat talked about the journal's workings - \"Nothing else is open on my\u2026 \u2014 the user sees replies, reactions, pills and reads themselves; say what the work is instead", "meta": {"from": "journal"}}
{"content": "nothing is ready - every open row waits \u2014 to-do 2, Rebase the profile review fixes onto the moved overnight-refactor. 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": "your chat talked about the journal's workings - \"To-do 2 is closed\" \u2014 the user sees replies, reactions, pills and reads themselves; say what the work is instead", "meta": {"from": "journal"}}
