A living record of architectural decisions, milestones, key insights, and strategic direction. Auto-maintained via claude-devlog-skill. Entries are reverse-chronological.
Category: fix
Tags: ck, review-page, gallery, do
Risk Level: low
Breaking Change: no (callers pass the same flags)
A d20mob staged plan was published as "Phase 9, the ten: staged plan" under the banner line "Code Katz · review page", so nothing on the page said d20mob, and Will could not tell it apart in his artifact list. The review page skill asked for --title "<product>: <document>", but nothing enforced it, and /ck:plan passed a title with no product. Now the renderers find the project's name themselves.
- The review page.
scripts/render-review.pyputs the project's name in the banner line (" · review page") and at the front of the<title>and the heading (": <title>"), and skips the prefix when the title already starts with the name. The name is the main checkout's folder of the git repository that holds--in(git rev-parse --path-format=absolute --git-common-dir, then its parent), so a page built in a worktree still names the project; outside a repository it is the file's folder.--projectoverrides it. Every gate (/ck:prd, /ck:plan, /ck:claude-md and the rest) gets it with no change. - The gallery pages. A
git grepacrossskills/,workflows/andscripts/found two other ways a page gets published.scripts/render-gallery.py(brand galleries, design galleries, andchosen.html) had "Code Katz · gallery review" and "Code Katz · chosen design"; it now names the project the same way, from the repository that holds the variants JSON, with the same--projectflag. The gallery contract says so. The workflows that call it need no change. - The /ck:do mockup. A persona writes
mockup.htmlby hand and the session publishes it. The step's rules now ask for the<title><project>: <what you drew>and one line above the mockup,<project> · mockup, with the session filling in the name. scripts/project_name.pyholds the lookup both renderers use. One test renders a page from a file in a temporary repository nameddemo, then with--project x.
Category: fix
Tags: ck, claude-md, sessions
Risk Level: low
Breaking Change: no (a project changes only when its How we work is updated)
In a hireling lane the session told Will "Nothing is needed from you on this record yet", and when asked, it said the merge of pull request 95 was still needed. d20mob and hireling sessions keep saying this while a merge, a "log it" and a branch deletion are still waiting. The cause was ck's own template, which since 0.1.12 said "when nothing is needed from the User, say so in those words" and, at a session's end, "If nothing else is left, say so". Will wants one of two things only: the things left to do, or "This session can be closed."
- Two endings in "The User's rules". New
templates/how-we-work/0.1.28.md, copied from 0.1.27. Every message to the User ends in one of two ways: with something left in this session (a merge, "log it", deleting the branch), it lists what is left in order and ends with the exact words for the first one ("Say merge 95"); with nothing left (the pull request merged, the records logged, the branch deleted), it ends "This session can be closed." It never says "nothing is needed" or any words that leave out work still waiting. A where-things-stand answer ends the same way. - "Finishing a session" matches. Once the branch is deleted, the session says "This session can be closed." Work outside the session is named in one line and left to the coordinator.
- A
git grepacrossskills/,profiles/,agents/,templates/andscripts/found no other place that tells a session how to end a message to the User; the "say so" lines it found are about other things, so no profile, skill or agent changed. The older templates stay as they are. The/ck:claude-mdtests read the 0.1.28 template.
- d20mob and hireling take How we work 0.1.28 with
/ck:claude-md, on their own pull requests, when Will says so.
Category: feature
Tags: ck, plan, start, tiers, effort, cost, claude-md
Risk Level: low
Breaking Change: no (a Who cell in the older form is still read, by its model's tier)
F1 of the releases page after 0.1.24, approved by Will as D1 on 2026-11-05. A stage ran on its owner's tier, so Akira worked on Fable whether the job was a design call or a rename, every stage inherited its coordinator's effort, and Will ruled on d20mob rows by hand. 45% of his spend ran on Fable and 62% at xhigh. The lanes test found one persona on the model that fits the job wrote better code in five of six blind verdicts, and the effort evidence (Anthropic's SWE-bench Pro runs, cost per solved task) set the point each kind of job runs at.
- Job words. Who reads
<Persona>, <job>, one ofdesign(Opus 5.5 at high),build,reviewandwrite(Opus at medium) andedit(Sonnet 5.5 at medium). Each is ajobline intiers.conf, so moving a job to another point is one line.<Persona>, <job>, <Model> <effort>pins any other point on the four-model, five-effort grid. The persona lines stay for/ck:do, the workflows and/ck:panel. - Older plans.
<Persona>, <Model>is read by its tier: Fable asdesign, Opus asbuild, Sonnet or Haiku asedit.plan.py checkadds one note line saying how many rows give that form. No plan file is rewritten. - The card.
plan.py cardnames the session[P2-S4] [Akira design] <title>, printsjob, the model's id andeffort, and the model check now covers both. A build card carries Will's goal line, "As much coded as necessary, as little code as possible."rowsandreadyprint the point, such asOpus high, where they printed the model word. - Opening and checking a stage.
/ck:startpassesmodelandefforton the chip. A chip cannot open above its coordinator on either axis; when the point is above, the coordinator says so and the stage's own check stops it. A session reads its own effort withget_sessionandself, checked in this build. The board's refresh sets a running stage's effort as well as its model. - The Fable rule. The plan contract and the draft workflow pin
Fable highonly for a stage that Opus at high has already fallen short on, or, on trial, for security or concurrency code, and neverxhighormaxunless the author asks. - How we work 0.1.27. The session title's tag is
[{persona} {job}], and "The stage's model" becomes "The stage's model and effort", with the five points in words for a brief that names none. - Cost by point.
cost.pykeeps each reply's effort, logs the cost by model and effort with each pull request, and/ck:cost historyadds a table of cost per point for pull requests merged from 0.1.27 on.
- d20mob and hireling take How we work 0.1.27 with
/ck:claude-md, on their own pull requests, when Will says so. Until then their own rule reads the tag's second word as a model; the card's check covers ck's cards. - Left for later: re-running a failed build stage at high, moving the six Fable personas in
tiers.conf, and job words in/ck:do.
Category: fix
Tags: ck, drawings, claude-md, kai
Risk Level: low
Breaking Change: no (a project changes only when its How we work is updated)
In d20mob's drawing lane [A31-P7-S1] [Kai Opus] The tale, drawn, the session kept sending pictures of mockup 38 and no link to the page, and Will had to ask for the HTML link again and again. Nothing in ck asked for one: "Drawings first" said only to show the frames early, Kai's skill said to screenshot a mockup before showing it, and a d20mob memory told sessions to send a picture. Will wants the link every time.
- The link in "Drawings first". New
templates/how-we-work/0.1.26.md, copied from 0.1.25 with the stamp changed and one rule added to Drawings first: every message that shows or changes a drawing gives the page's link with the picture, every time, without being asked, as a clickable markdown link to the file (file:///...), which opens in the User's browser at any time. Alocalhostaddress is used only when a page has to be served, and the message then says it works only while that session's server runs. - The same line in Kai's skill. Kai's Mockup QA Loop (
profiles/kai.md, regenerated intoskills/kai/SKILL.mdandagents/kai.md) said to screenshot a mockup and show it, with no link; it now carries the rule. Agit grepacrossskills/found no other place that shows a drawing without a link:/ck:do's draw step and/ck:design's gallery already give one. scripts/claude-md.pytakes the newest template as current, so/ck:claude-mdneeds no change. Its tests now read the 0.1.26 template.
- Nothing propagates template changes. d20mob and hireling each take the new rule with
/ck:claude-md, on their own pull requests, when Will says so.
Category: fix
Tags: ck, lanes, models, claude-md
Risk Level: low
Breaking Change: no (a project changes only when its How we work is updated)
A stage session checked its model only when its brief came from plan.py card, which puts the MODEL_CHECK paragraph in every card. A coordinator that writes its own briefs leaves it out. hireling's Phase 2 coordinator, started 2026-11-01 from a pasted prompt, did that for 15 stage sessions. A chip cannot open on a dearer model than its coordinator's, so an [Akira Fable] stage opened on Sonnet and went straight to work. d20mob's coordinators had always written their own briefs, with a line of their own ("If you are not running on Fable, say so in one line and wait"), so its stages stopped on the wrong model through P6-S3 on 2026-11-03. The A31-P6 coordinator's context was compacted twice early on 2026-11-04, and its briefs from P6-S4 on, and the A31-P7 coordinator's, have no such line: [A31-P7-S0] [Akira Opus] opened on Sonnet and started work until Will stopped it. Nothing in ck changed; the stop lived only in each brief, and a coordinator can drop it. Will wants a stage on the wrong model to stop, not to switch itself.
- "The stage's model" in the How we work template. New
templates/how-we-work/0.1.25.md, copied from 0.1.24 with the stamp changed and one bullet added after Personas, as lanes: a session whose title starts with an id and a[{persona} {model}]tag checks its own model before anything else, whoever wrote its brief. It keepsMODEL_CHECK's behaviour: stop with "This session is on , and the plan puts this stage on {model}. Pick {model} in the model menu, then say go.", carry on when the User says go, and say so in one line when it cannot tell. The rule is in the project'sCLAUDE.md, so it reaches the session whatever the brief says. MODEL_CHECKstays inplan.pycards. A project whose How we work is behind still gets the check from the card.scripts/claude-md.pytakes the newest template as current, so/ck:claude-mdneeds no change. Its tests now read the 0.1.25 template.
- Nothing propagates template changes. d20mob and hireling each get the new bullet by hand, on their own pull requests, when Will says so.
Category: fix
Tags: ck, lanes, next, claude-md
Risk Level: low
Breaking Change: no (outside a lane nothing changes)
In d20mob, lane sessions ended by suggesting the next lane and ck commands. Will expects that from the coordinator, not from the lane. Two sources, two fixes.
- Gate skills in a lane.
skills/next/SKILL.mdsection 4 now says a lane (a session whose title starts with a bracketed id, such as[A31-P6-S4]) closes with only the skill's own finished sentence: no pipeline table, no line under it, no next command, and none of the skill's other suggestions (the/devlognote, the/ck:startline). The rule is in that one place, so the ten gate skills needed no edit. - "Finishing a session" in the How we work template. New
templates/how-we-work/0.1.24.md, copied from 0.1.14 with the stamp and one clause changed: "if something is, name it in one line and leave it to the coordinator; do not suggest the next lane or a command to run."scripts/claude-md.pytakes the newest file as current, so/ck:claude-mdpicks it up with no change. The/ck:claude-mdtests now read the 0.1.24 template.
- Nothing propagates template changes. d20mob and hireling each get the one changed sentence by hand, on their own pull requests, when Will says so.
Category: fix
Tags: ck, cost, hooks
Risk Level: low
Breaking Change: no (old log rows still read; history columns change)
An assessment on 2026-11-01 found the 0.1.19 cost numbers right per session but attached to the wrong thing: 15 of 31 merges were off by more than $1. Will approved the fixes on a proof page on 2026-11-03, choosing every recommendation and the deletion of the stray comment.
- The pull request's cost, not the session's running total. The sessions that worked on the pull request's branch (found by the
gitBranchin their transcripts) are charged what they spent since their previous row in the log. A session that only merged it is shown apart, and is charged only when no session worked on that branch. In a replay of the 31 merges, hireling#13 goes from $17.65 to $60.77 and d20mob#364 from $27.61 to $2.62. - The right pull request. The hook follows a
cdbefore the merge, reads--repoand-R(including a$Rset in the same command), and accepts a URL. It does nothing unless the pull request merged in the last 10 minutes, so a wrong lookup can miss but not comment on an old pull request. Onlygh pr mergewhere a command starts counts; a mention runs nogh. This fixes the $30.62 table posted on #10 for claude-plugins#10, and the two missed merges, d20mob#365 and hireling#9. - In the session: one line after the merge, such as "ck cost for o/r#8: $4.00 (session total $19.10)". A coordinator's line names the builder and gives its own cost since its last merge. Will chose one line over the table because a hook's message in Claude Code puts a "PostToolUse:Bash says:" prefix on every line, which breaks a table.
- On the pull request: the headline, the builder's table, and a hidden
<!-- ck-cost {...} -->line with the numbers as data, so a repository keeps its own cost history (Will's ask). - Each log row also records the ck version, the first request's prompt size, and the number of requests, so a later release can be compared on what it changed. Comparing pull request dollars would need about 900 pull requests per version to see a 20% saving.
/ck:cost historylists each pull request's cost and the coordination apart, with the total, and what sessions spent after their last merge (12% of spend in the assessment)./ck:costshows the session it is typed in (${CLAUDE_SESSION_ID}), not the most recently written transcript in the repository.
~/.claude/ck-cost.jsonlwas rebuilt into the new rows from the transcripts (45 pull requests, 53 rows), with a copy inck-cost.jsonl.bak-2026-11-03.- The stray comment on #10 was deleted with Will's word.
- How the desktop app draws a message from a PostToolUse hook was not seen: a test hook in a worktree's local settings did not fire in a desktop session. The Stop hook's line is recorded the same way. The first real merge on 0.1.23 shows it.
- The cost after a pull request merges counts toward that session's next merge, or appears in
history's after-merge line. - The 28 tables posted before 0.1.23 show session totals and stay as they are.
Category: refactor
Tags: ck, tokens, listings, memory-gate
Risk Level: low
Breaking Change: no
R1 and R3 of the lean review. What ck adds to every session's listing drops from 2,549 words to 531, about 2,700 tokens saved per session. One memory-gate run reads 603 words instead of 3,014, about 3,200 tokens saved per memory; choosing "Add to CLAUDE.md" adds 205 more.
- Workflows (1,386 to 172 words): each
meta.descriptionis one sentence of 15 to 20 words. The old text moved word for word to a comment undermeta./ck:panelkeeps "type /ck:panel followed by the question", since no skill launches it when typed. - Contracts and helpers (634 to 235): about 15 words each. Agents (453 to 90): name and role only, from
scripts/generate.sh. The gate's rule (76 to 34): the sentence on Claude Code's approval prompt went, since the hook's own prompt and the skill's step 4 already say it. - Hiding workflows: not possible. Claude Code 2.1.310 has
disableModelInvocationon a workflow's command, but its plugin loader never sets it frommeta, and the docs name no such field. So the 172 words stay. - The gate: the sort moved to
skills/memory-gate/sort.md, read by the gate and by step 4 of/ck:claude-md. The steps for a CLAUDE.md change moved toskills/memory-gate/claude-md-change.md, read only on that choice. The gate no longer points at step 8 of/ck:claude-mdfor the Trash or the merge; it says them itself. - Reviewed by Fable before merge. It found nothing that breaks. Three fixes taken:
draftsays its argument defaults to prd,plan-draftsays no text means the release, and/ck:claude-mdstep 4 says to readsort.md. One change kept: in/ck:claude-md, Retire now also covers a memory that repeats another memory; step 7 still asks the User. - Tried in a real
claude -psession on a throwaway repository: the gate ran, readsort.mdand not the claude-md skill, ended "Reply 1, 2 or 3", and readclaude-md-change.mdonly after "2". That repository has no remote, so the pull request step was not reached, and no write to memory was approved.
- The 2,700 and 3,200 are words times 1.33, not measured tokens. A workflow's whole weight in the listing also depends on Claude Code's own cut when the listing is over its budget.
Category: feature
Tags: ck, team, personas, casting
Risk Level: low
Breaking Change: no (a project with no team file now casts from the core; any seat is one invite away)
Each project's ck team is the core, eight seats (River, Quinn, Akira, Sasha, Kai, Robin, Alex, Morgan), plus the changes in .claude/ck-team.conf: one invite <persona> <why> or drop <persona> <why> per line. Every session, /ck:do, /ck:opportunity, /ck:plan, and /ck:start's cards keep to it, so d20mob works with Reiner, Tracy, Travolta, and Piper and is never offered Noon. This rebuilds on main the proposal approved on 2026-10-16 (D1 to D4), re-scoped against 0.1.19 on a proof Will reviewed on 2026-10-28, where he set the goals: ck never casts a persona off the team (G1); a plan row naming one gets a note and no card (G2); a project with no file has the core (G3); and the full /ck:team invites its cast onto the team when it finishes (G4).
scripts/team.py, the one reader and writer:show,roster(the roster rows of the team only),context(the session paragraph),invite,drop. The last line about a persona wins;inviteanddropkeep only what differs from the core, so inviting a dropped core seat or dropping an invited guest removes its line. The project is the nearest folder up with the file or.git. The core is a list in the script, not a second file.- Every session: the SessionStart hook runs
team.py context, one paragraph naming the team (about 70 tokens). - Casting:
do.sh lookprintsroster:lines for the team only, and/ck:dotakes the nearest team seat when a default owner (Iris, Toni) is off it. The opportunity and plan workflows readteam.py rosterinstead of the whole roster; a seat a prompt fixes (Toni and Akira in the opportunity) still runs (D4). - Plans:
plan.py checkadds anote:line for an owner off the team, andplan.py cardrefuses that row until the persona is invited;/ck:startrelays the refusal as it is, soskills/start/and the Who column are unchanged for lanes. Outside any repository with no team file,plan.pychecks names against the roster only. /ck:team show | invite | droprun the script, offer to commit the file, and launch nothing. The full/ck:teamends by inviting each Cast seat ofdocs/TEAM.mdthat is off the team.- Cut from the proposal: the warning line in the 21 switch commands (C7;
/ck:noonstill works everywhere),core.conf,team.py has, the "Invite Noon?" question mid-workflow, and changes toteam-draft.jsandroadmap-draft.js. - Tests: section 23, ten cases on
team.pyandplan.py(no file, d20mob's file, an unknown name, invite and drop, a persona both invited and dropped, the paragraph, the hook, the note and the refusal); the plan fixture project carries d20mob's team file. 495 checks pass.
- Not yet tried in a real session. The four checks to try in d20mob are in the pull request.
- A guest (one use, asked once) leaves no line, as the proposal assumed; one core for every kind of project.
[2026-10-11] 0.1.10: /ck:do, the quick path; /ck:plan and /ck:start, a staged plan and one named session per stage
Category: feature
Tags: ck, do, plan, start, sessions, phase-two
Risk Level: medium
Breaking Change: no
Three commands that take ck past the definition pipeline, each shaped by Will on 2026-10-11. /ck:do gets one small task done in the chat: a plan of a few lines, "go", the right personas as background agents, a mockup link he OKs when he asks for one first, and a build on its own branch until he says merge ("do is meant to be more quick and scrappy in the chat"). /ck:plan writes a staged plan and /ck:start opens one named session per stage and keeps the plan's board ("CK should always arrived at a detailed staged plan like the one attached then it can open sessions with the naming convention", then, of a second table, "another example, better one", then "build it, and yes this sits besides do"). None of the three has been run for real: the claude command's sign-in on the development machine had expired, so the scripted trial could not start. They were checked by tests and by fresh readers walking scripted conversations.
- The staged plan (
skills/plan-artifact): phases, and under each a table| Stage | What | Who | State |. One row is one job for one owner, so one row is one session. Who is<Persona>, <Model>,You, orOpen. State is one of four forms:done (279),running in its session,not started; could start now,not started; follows S1 and S2. Each row has an entry (Kind, Does, Files, Reads, Follows, Done when, Hands back) that a session knowing nothing else can work from. The release plan isdocs/build-plan.md; an item plan is underdocs/plan/. scripts/plan.pyis the one reader and writer of a plan's state:find,check,rows,ready,refresh,set,approve,board,card. It was built tests-first by two agents working from one specification without seeing each other's work (90 cases, all passing on the first run), then attacked by two more, who found 24 faults (a bar inside a cell madesetoverwrite the Who cell; a wrapped Follows freed a row early; a long line took quadratic time). Each is fixed with a case; 111 cases now. It only ever rewrites a State cell or the Status, and never prints a traceback./ck:plan(skills/plan,workflows/plan-draft.js): Quinn writes the release plan from the roadmap, the architecture document, and the team document; an item plan's author is the area's lead, akira by default. A Haiku checker runsplan.py refreshandcheckand reads for what a script cannot (hours, dates, the roster's total). The author reviews on a page, approves, and is asked to commit the plan, because a session in a worktree sees only committed files. An existing plan is never overwritten unasked: a copy goes to the run folder, and a replanned plan keeps every stage's id and what is done or running./ck:start(skills/start): for a stage,plan.py cardprints the session's name,[A31-P2-S1] [Akira Fable] Make the creature tables, and its opening message, and the session offers them as a card through the desktop app's suggested-task tool. The author clicks; ck never starts a session. With no stage it first brings the board up to date from the app's session list: a session counts for a row only inside this project and only when its title starts with the row's id and owner, a merged pull request marks the row done and the session[done], and a session whose title merely mentions an id, or reads as an instruction, changes nothing. "merge", "done", "running", "back", and "save" are the author's words for a stage. In a terminal it prints the message to paste./ck:do(skills/do): the coordinator plans in chat, runs each step as a background agent on the persona's tier, publishes a mockup as a private link, and has the build run in an isolated worktree. Two faults were caught in review before any run: an isolated worktree starts from the remote's default branch, not the author's last commit, so the builder resets to the recorded commit first; and the branch and files in the report come from the session's own look, not the builder's word.- A fix to a finished stage (2026-10-12, at Will's word to proceed with the three open points below):
/ck:start fix <stage> <what is wrong>, or "fix<id>: ..." said later in the coordinator, offers a card for a session named as his own are,[A31-P1-S5 fix] [Akira Fable] Mend the scan's natural 1.plan.py card FILE ID --fix - --title TITLEreads his words from standard input, so no quoting can change them, and prints the same card shape with a prompt that names the stage, the pull request that carried it, and the one fault. A fix has no row and changes no State: the stage stays done, andmerge <number>merges the fix and renames its session[done]. A stage that is running or not started is refused in one line. - The model check: no tool can choose a new session's model before its first turn, so every card's opening message now begins by having the session check its own model against the row's and stop with one sentence when it is on another ("This session is on Sonnet 5.5, and the plan puts this stage on Fable. Pick Fable in the model menu, then say go."). The coordinator still sets a stage's model when the author says
running <id>, and then tells him to saygothere. /ck:nextgains step 10, the build plan, and once one exists its one sentence is/ck:start. It no longer says that building is the next release of ck.- Tests: sections 18 and 19, the plan script's cases, and the new skills in the house-style, gate, and pipeline-table checks. 380 checks; 461 with the fix card and the model check (191 cases for the plan script).
Three review rounds, each a workflow: fresh readers given only a skill's text walked scripted conversations (five for /ck:do, eight and then five for /ck:plan and /ck:start), really running the shell commands and the plan script on sample projects, and judges compared each walk with what must happen; reviewers with a lens each (git and the shell, the tools' own contracts, fit to what Will asked for) hunted for holes and a skeptic tried to refute each finding. That is evidence about how the text reads and whether the commands run. It is not a run: no agent was launched, no page published, no card clicked.
The fix card and the model check had a fourth round on 2026-10-12, tests first: one agent wrote 80 cases from the specification, another changed the script without seeing them (no dispute), a breaker, a reader for contradictions, and two walkers with a judge went over the result, and a skeptic let 10 of 53 findings stand, all in the skill's wording (a finished plan was left out of the search a fix needs most; a line of the author's words equal to the heredoc's marker would have run the rest as shell; a fix in another project could have been renamed here). Two fresh sessions were shown a card: one on Sonnet with a stage planned for Fable stopped with the sentence, one on Opus with a fix planned for Opus carried on. Those two are the only part of this that was observed rather than read.
- The first real use is the first run. Costs in
/ck:do's plan line are estimates. - A fix card for a check stage tells its session to change nothing and report; whether such a fix should be refused instead is not decided.
- Will's sessions also split a stage,
[A31-P2-S2b] .... Here a split takes the next free number through/ck:plan; a lettered id is not read. - The card is the desktop app's suggested-task tool, whose own description is about side findings. Will's coordinator on another project uses it this way already.
/ck:proof, planned in another session, has a document contract in which "a plan" has a steps table. That and the staged plan are two shapes with one name, written to the same folder,docs/plan/. Decided by Will on 2026-10-12: a plan is always the staged plan, and/ck:proofkeeps proposals, analyses, and notes. He keeps the way to put a plan that plan mode wrote on a page. The session that owns the/ck:proofplan has the proposed edits to it (the kinds lose "plan", its contract drops the plan's tables, its guard refuses a staged plan, its rename covers/ck:plan); they are that session's to make. Whether the staged plan should gain the sections that shape had (decisions at the top, not doing, what could go wrong, how we will know) waits for the first real/ck:planrun.- The older gate skills write
.ck/into.git/info/excludeby path, which fails inside a linked worktree. The new skills usegit rev-parse --git-path. The older ones are not changed here. - The PRD in
code-katz/.githubdoes not describe these three commands yet.
[2026-10-07] 0.1.9: /ck:next shows the whole pipeline as a table with each step's status; every pipeline command closes with it
Category: feature
Tags: ck, next, pipeline, status, readme, tests
Risk Level: low
Breaking Change: no
On a real product (2026-10-07), after /ck:opportunity and /ck:brief, Will had to ask what comes after the team step, whether the PRD was next, and whether there was a marketing brief: the one sentence from /ck:next did not give him the map. /ck:next now prints the pipeline as a table, one row per step in order, with what the step does in a sentence, the document it writes, and where this project stands, then its one next action. Every gate-owning skill closes with the same table instead of sending the reader to /ck:next.
- The table (
skills/next/SKILL.md): nine steps in the PRD's §6.1 order and the panel as "any". Status is the first that applies ofrunning,in review,stopped partway,done,next,skipped,not started, read from the documents on disk and the last run record for each command. Design is per feature ("done: checkout; in review: onboarding"). - The look is three commands with no file pattern for the shell to expand (
ls,find,grep -r --include=run.json ... | sort), so it runs as written under zsh and bash and prints nothing in an empty project. A folder under.ck/runs/with norun.jsonis not a record. - Finish lines. The nine gate-owning skills end with "close per
skills/next/SKILL.md" in place of "Next: run/ck:next", which told the reader to type a command to learn what to type. The table lives in one file; a test fails any skill that restates it. - Marketing is visible. One line under the table says no step writes a go-to-market plan or a marketing brief yet and that the marketing thinking is in steps 1, 2, 3, and 8. That is the PRD's intent:
/ck:gtmis phase two (§2.5, §10.2). - The sentence table had a gap. With an opportunity analysis and market research but no brief, no line applied. Two states are reworded and one added ("Run
/ck:brief. It starts from your opportunity analysis..."). - README. The
/ck:nextrow and step 4 of "How a run works" describe the table, and a note says to type each command, not paste it: the gate-owning skills run only when typed, so a pasted command can at most start the workflow underneath, with no run record and no review page. Will's project showed it:.ck/runs/opportunity-latest/with norun.json. Since 0.1.8, typing the command afterwards takes the finished document to its review. - Tests (section 17): the table's rows, order, and one-sentence rule; its paths against the README's; the seven statuses; that every step can be the next one; the look run under bash and zsh in an empty project and a fixture; the nine finish lines. Checked by hand as well: four deliberate breaks each failed the suite, and five fixture projects given to fresh Sonnet agents with only the skill each printed the expected table and sentence.
/ck:nextprints the table; no new/ck:status. Every finish line and the README already send the reader to/ck:next, and a second command would have to be discovered at the moment the reader does not know what to type. This relaxes the PRD's "say exactly one thing" (§6.12, Appendix F) to "show the table, then say exactly one thing"; "no more than one action" stands, since a status table is not an action.- A seventh status,
running, beyond the six asked for. A run this session launched and is still waiting on would otherwise readstopped partwaywith "run the command again", which starts a second run. skippedapplies only to steps 1 and 2. The sentences always send the reader back to a missing team document, PRD, roadmap, architecture, or brand guide, so those are never skipped.- Rejected: a script that prints the table. It would be exact, but the plugin needs no script at run time for navigation today, and the look plus the drills cover the reading of it.
- The PRD in
code-katz/.github(§6.12, Appendix F, test 11 in §9) still says "one thing"; it gets the same change in its own commit. - Seen from a second session, a run record at
draftingreadsstopped partwayeven when the workflow is still running elsewhere; the disk cannot tell the two apart. - Not yet seen in a live session:
running, the brand guide'sreview-1andreview-2, and a finish line printing the table.
[2026-10-07] Resume checks: listings that run under zsh, a finished document with no run record goes to the review, the design listing matches one feature
Category: fix
Tags: ck, resume, zsh, brand-guide, design, skills, tests
Risk Level: low
Breaking Change: no
Three faults in the resume checks of the gate-owning skills, each of which could launch a paid stage over finished work. Merged as pull request 22 and shipped in 0.1.8, with no version of its own. tests/run.sh gains sections 15 and 16.
- The resume listings in
/ck:brand-guideand/ck:designrun under zsh. Each listed what is on disk with onelswhose last arguments were file patterns under.ck/runs/. Claude Code's Bash tool on macOS runs zsh, and zsh stops a command whose pattern matches nothing beforelsruns: it prints "no matches found" and lists none of the files that do exist. With a gallery waiting for review and no review file yet, the listing was empty and the decision list fell through toproposalsorvariants. Each listing is now two exact commands: a plainlsfor the fixed paths, andfindwith a quoted-pathfor the files under.ck/runs/, sorted so the oldest run comes first. The six other exact commands in the gate-owning skills were plainlslines and needed nothing. - A finished document with no run record goes to the review. A workflow started directly keeps its files in
.ck/runs/<name>-latest/and writes norun.json, and.ck/is a cache a clone does not have. With the document on disk and no record,/ck:brief,/ck:team, and/ck:market-researchfailed every branch and launched a full redraft;/ck:opportunityfell tostartAt: framewith the idea taken from the document it was about to replace;/ck:prdand/ck:architecturechosevalidateand were then told to reuse a run that did not exist. Each of the seven skills now has one branch, third in its list: norun.jsonwith this command and the document exists, so launch nothing, mint a run, and go to the review. - Two of the seven differ.
/ck:prdand/ck:architecturealso ask that Appendix B has the premortem: a draft with the premortem still pending resumes atvalidateas before, with a run minted first./ck:roadmapapplies the branch only when.ck/runs/roadmap-latest/priorities.jsonexists and is older thanROADMAP.md, the mark of a direct run; any other existing roadmap is still updated from the PRD, as step 1 of that skill says. - "Newer than
run.json" was not one answer.[[ doc -nt missing ]]is true in bash and false in zsh, so the branch that compares ages gave a different result per shell when there was no record. The new branch is decided before that comparison. - The
/ck:designlisting matches only this feature's runs.*-<slug>-designfor the slugcheckoutalso matched20261001T000000Z-guest-checkout-design, so achosen:from another feature could send/ck:design checkouttorefine. The pattern is now*Z-<slug>-design, where theZends the timestamp step 3 puts at the front of the run id. - Tests. Section 15 pulls every exact command out of the nine gate-owning skills, refuses a file pattern outside quotes, and runs each under bash and zsh (a shell that is not installed is skipped) in an empty project and in fixtures for each state the two decision lists name. It also mints a design run the way step 3 does and checks the listing finds it, so the pattern and the run id cannot drift apart. Section 16 checks the no-run-record branch in each of the seven skills: its place in the list, the document it names, and that the two steps it names are that skill's Mint the run and The review. On the old skill text section 15 fails 6 times, all under zsh or in the pattern check. The suite went from 158 checks to 182 on the branch, and is 207 on
mainwith 0.1.7 and 0.1.8 merged. - How the second fix was checked. No real
/ck:command was run. Seven fresh readers followed the text against fixture projects and reported which branch they took: three on the old text, four on the new (a brief, a finished PRD, a draft PRD, a roadmap from a direct run). That is evidence about how the text reads, not a drill.
- Sending every document with no record to the review. For a draft PRD that finishes an unvalidated document, and for the roadmap it turns off update mode for a roadmap that predates ck.
- Asking the author what to do, as the
finalbranch does. A session that cannot ask has no answer, and the review costs nothing when the author wanted something else. - Folding the
/ck:designover-match into the zsh fix. The oldlspattern had the same fault, so the zsh fix carried it over unchanged and the tightening went in as its own commit, approved by Will.
- The first sentence of every resume check, "Read the latest
.ck/runs/*/run.json", is prose, but every reader typed it as anlswith that pattern, which errors under zsh when there are no runs. Each read the error as "no record", so nothing breaks today. The third line of the/ck:nextlook, added in 0.1.9, reads the records with no pattern; the resume checks could use the same line. - A typed idea is ignored when a document exists with no record:
/ck:brief <new idea>goes to the review of the brief that is there, as the branch that compares ages already does. - A PRD run whose own slug is
<feature>-designhas the same folder name as that feature's design run. - Not run on Linux, and not drilled in a real session.
[2026-10-06] 0.1.8: a cheap neutral trim, no false premortem failure, --panel for the architecture, Mermaid on review pages, a roadmap cap, the roster rule refined
Category: fix
Tags: ck, draft, architecture, roadmap, review-page, cost, drill
Risk Level: low
Breaking Change: no
Drills 25 (/ck:roadmap, $3.73, the first run with nothing fixed by hand) and 26 (/ck:architecture, $17.31, Akira on Fable $13.07 across five passes). Seven changes, all approved by Will.
- The trim is a neutral Sonnet editor at low effort, not the author on Fable. Drill 26's trim cost $4.14 and 53,833 output tokens to make one Edit of about 5,000 characters: reasoning, not editing. A trim only deletes repetition and moves detail, so the author's voice is not at risk.
- The pre-panel checker skips the premortem item. Appendix B is written after the panel by design; the first checker of drill 26 failed the draft on its placeholder and cost about $3 in revisions.
/ck:architecture --panel, default off, like/ck:prdsince 0.1.5. The finalize rule from 0.1.5 (no agent when the review changed nothing) now reaches the architecture skill too; the ck-test session had applied it by hand in drill 26.- Review pages draw Mermaid diagrams: a
mermaidfence becomes a diagram, with the library loaded from cdnjs only on pages that have one. The architecture contract requires a diagram, and drill 26's page showed it as code. - The roadmap is capped at 2,500 words (contract item 8); River and Quinn are told the length first, Open Questions points to the PRD's open questions by number, and the validator counts. Drill 25's roadmap ran to 4,777 words with no rule to count against.
- The roster rule, refined by Will in the roadmap review: never state the total size of the roster; a subset count, such as the seats on one tier, is fine. Every agent's preamble says so, and every validator with a checklist carries it as a house-style item.
- Not fixed, recorded: the length rules did not hold for Akira in drill 26 (a 4,191-word draft against "aim for 2,500"; the rewrite grew from 2,802 to 4,072). The cheap trim is the backstop.
[2026-10-07] 0.1.7: a note beside a good plan no longer stops the run; a stopped run can start again at research, sections, or synthesize
Category: fix
Tags: ck, market-research, roadmap, opportunity, draft, resume, tests
Risk Level: low
Breaking Change: no
A real /ck:market-research on 0.1.6 (2026-10-07) threw away a good six-question plan: the schema required stopReason, Toni filled it with a summary of the plan, and the script read any text there as a stop. The documented way to continue, startAt: "research", then threw every time, because the plan is only in memory when the plan stage ran and a script cannot read plan.json. Both are fixed, the same two shapes are fixed in the three other scripts that had them, and tests/run.sh now runs every workflow script with stub agents.
- The lists decide the stop;
stopReasononly words it. Inmarket-research-draftthe run stops when the questions list is empty, and inroadmap-draftwhen all three tiers are empty.stopReasonis the sentence shown in that case, with a default naming what to run first when it is absent. Text beside a filled list is logged as a note and the run goes on. The field is no longer inrequired, and both prompts say it belongs to the stop case only.roadmap-drafthad the identical line and would have failed the same way on the first note River left. - A run that starts after the first stage reads the saved file back.
market-research-draftatresearchandopportunity-draftatsectionseach ask one low-effort Haiku agent to returnplan.jsonorframe.jsonunchanged against the stage's own schema. A missing file or an empty list stops with the file's path and the stage to start at. The later stages (crosscheck,write,validate;assemble,validate) never needed the object: their agents read the files themselves. draftatsynthesizeno longer throws at the end.earlierMemowas declared inside the panel branch and read in the return statement outside it, so the PRD and architecture resume atsynthesizedid all its work and then failed with "earlierMemo is not defined". The declaration moved up, and a run with the panel off no longer names a memo. Found by the new tests, not by a run.tests/workflows.mjs, section 14 oftests/run.sh. Each script is loaded as the runtime loads it and run with stub agents. One check per script starts it at every step itsORDERorORDERSlists, with every agent filling every field of its schema with non-empty text: a required string read as a signal, or a step that cannot be started at, fails there. Fourteen named cases cover the two reported bugs and their neighbors. A case's own answer is checked against the script's schema, so a case cannot pass on an answer the runtime would refuse. On 0.1.6 the new section fails 15 of its 23 checks.- Skills.
skills/market-researchandskills/opportunitypickresearchorsectionsonly when the saved file lists something, so a run cannot be sent back to a step that will refuse it again.skills/opportunitysaid to take the idea fromframe.json, which does not hold it; it is inrun.json.
- Passing the plan to the workflow in
argsfrom the skill. It saves one small agent call, but it only works when the skill is the caller and copies the object faithfully; reading the file inside the script makesstartAtmean the same thing for every caller, which is what the script's own log line already claimed. - Fixing the prompt alone ("return an empty string when you planned"), or making the field optional alone. Either leaves the run depending on what a model writes in a free-text field. The list is the evidence; the text is not.
- A run started after the first step returns null or an empty list for what the skipped stages would have counted (
questions,contributors, the roadmap'sopenQuestions, the brand and designvariants). No skill reads those today. - The repository has no linter. An undefined-name rule would have caught
earlierMemowithout a test. The scripts need the same wrapping test 9 gives them fornode --checkbefore a linter can parse them.
[2026-10-05] 0.1.6: /ck:team, /ck:roadmap, and /ck:market-research become gate-owning skills; every validator counts; nominees read less; the roster is described, not counted
Category: fix
Tags: ck, team, roadmap, market-research, validators, cost, drill
Risk Level: low
Breaking Change: no
The first real /ck:team (drill 24, $10.85 against $6.29 on the fixture) passed a 2,685-word document against a 2,500 cap because the validator guessed, left no run record, and spent two thirds of its cost on eight nominees each reading the whole PRD. Three fixes, all approved by Will, and one house-style change: the roster is never counted in the plugin's own text.
- Skills own the run and the review.
skills/team,skills/roadmap, andskills/market-researchmint a timestamped run withrun.json, launchck:team-draft,ck:roadmap-draft, orck:market-research-draftwith absolute paths, and review on a page, the same shape as/ck:briefand/ck:opportunity. The workflows are renamed accordingly; typed directly they still run with defaults and no record. - Every validator counts. The team, opportunity, design-spec, and market-research validators run
wc -w(before## Sourceswhere the contract says so) and quote the count; the brief and draft validators already did. A test checks every capped workflow for it. - Nominees read less. In
team-draft, each nominee reads River's nomination and the brief (or the opportunity analysis), and a PRD requirement only when a responsibility names it. Drill 24's confirmations read 220k to 425k cached tokens each. - Gallery banner check fixed. The brand and design gallery validators still looked for
@claudein the banner, which the renderer stopped writing in 0.1.1, so every gallery check would have failed and spent its two fix rounds. They now look for the local-review sentence. Found while editing the validators; a test guards it. - Roster wording. The README,
ROADMAP.md, and the plugin description describe the roster ("the full persona roster, a complete cross-domain team", "every persona") instead of counting it, per Will's rule from the brief review. The PRD incode-katz/.githubgets the same change in its own commit; drill logs and the correction note about the proposal's count stay as history.
[2026-10-05] 0.1.5: the PRD panel is optional (--panel); finalize runs no agent when the review changed nothing
Category: decision
Tags: ck, prd, panel, cost
Risk Level: low
Breaking Change: no
Two decisions by Will after drill 23. The three-lens panel inside /ck:prd has returned "yes, with conditions" on every run and costs about half of each PRD run, so it is now opt-in: /ck:prd --panel. Without it the draft is checked, River appends the premortem with a few edits, and the review follows; /ck:panel stays as its own command for challenging a finished document. The finalize step of /ck:prd and /ck:opportunity runs no agent when the review record holds no premortem answer and no answered decision; when it does, the agent edits the passages concerned instead of rewriting the file. Drill 23's finalize cost $2.02 to change one line.
workflows/draft.js:panel: falseskips the panel stage, the rewrite, and the post-rewrite check; a${author}:premortemagent appends Appendix A (one line: the panel did not run) and Appendix B with at most four edits.paneldefaults to true so/ck:architectureis unchanged.skills/prd/SKILL.md:--panelflag;panelrecorded inrun.jsonand passed inargs; the finalize step readsreview.mdfirst and skips the agent when nothing was answered.skills/opportunity/SKILL.md: the same finalize rule.- Expected cost of
/ck:prdwithout the panel: about $7; with it, about $12 on the 0.1.4 length rules.
[2026-10-04] 0.1.4: length rules move to the front of the PRD and architecture prompts; every agent carries the roster rule
Category: fix
Tags: ck, draft, prd, cost, drill
Risk Level: low
Breaking Change: no
The first real /ck:prd (drill 23) cost $13.90 against the $8 accepted, and three of River's five Fable passes were about length: a 3,604-word draft against a 3,000 cap, two revisions, a rewrite that grew to 3,947, and a trim that stopped at 3,406. The draft workflow now states the length first and lower, forbids the rewrite from growing, gives the trim the count and a number to cut, and makes every validator count before judging. Every persona agent now carries Will's rule: describe the roster, never count it.
- Length first, and lower. Each artifact in
workflows/draft.jshas atargetWords(2,500) beside itsmaxWords(3,000). The draft prompt opens with it instead of closing with the cap. - The rewrite may not grow. The post-panel rewrite must be no longer than the draft it replaces: for every sentence the panel makes the author add, one comes out. The appendices stay separate and uncounted.
- The trim gets a number. The checker's notes (with its count) are passed in; the author cuts at least count minus nine tenths of the cap, and may count once at the end to confirm. Before, it cut blind and stopped 406 words short.
- Validators always count. The pre-panel validator runs the same
awk ... | wc -was the post-rewrite check; the third round of drill 23 had failed the document on an impression. - Roster rule. One sentence in the generator's shared preamble, regenerated into all persona agents: plain words; describe the roster and the team, never count it.
- Cost method. Drill 23 records the shared method both sessions now use: sum usage once per message id (transcripts repeat each assistant message several times), price each message at its own model's rates, cache writes at 1.25 times input for five-minute writes and 2 times for one-hour writes, per-model cache-read rate. Summing every line overstates by about three times.
- The README,
ROADMAP.md, the plugin description, and the PRD incode-katz/.githubstill count the roster. Separate cleanup, proposed to Will when between runs.
[2026-10-04] 0.1.3: /ck:brief becomes a gate-owning skill; the brief workflow checks after every revision; review pages render bold around code
Category: fix
Tags: ck, brief, review-page, drill
Risk Level: low
Breaking Change: no
The first real /ck:brief run (drill 22, on the ck Workbench project) wrote a good brief and left four things broken around it. All four are fixed here, and the fixes follow the shapes the other commands already use.
/ck:briefis now a skill (skills/brief/SKILL.md), and the workflow isck:brief-draft. The skill mints a timestamped run directory with arun.json, launches the workflow with absolute paths, and owns the review page, the same way/ck:opportunitydoes. Typed directly, the old workflow could not mint anything: the run landed in.ck/runs/brief-latestwith the run idbrief-directand a placeholder where the date should be.- The checker runs again after each revision (
validate -> revise -> validate, at most two revisions, word count first), as in the team and market-research workflows. Before, one check ran before the one revision, so a run that needed a trim always reportedvalid: falseon a valid file. - River is told the length first: about 1,000 words, never over the contract's 1,200. The cap stays; the target moved down so a normal draft lands under it instead of 200 words over and paying for a trim (drill 22: 1,403 words, then a $1.14 revision).
render-review.pylifts code spans out before it applies bold and emphasis. A bold phrase containing a code span rendered with literal asterisks because the line was split at the code span first. Test added.tests/run.shruns on macOS: the GNU-onlysed '0,/re/'form is replaced withawk, so the suite runs on the Mac where ck is now developed.
- Raising or dropping the 1,200-word cap. The content fits (1,173 words with eight sections and five sourced comparables); the hard edge was the problem, not the number.
[2026-09-09] Repository created from PRD revision 3: profiles imported, generator, four workflows, six contracts, tests
Category: milestone
Tags: ck, phase-1, skeleton, generator, workflows
Risk Level: low
Breaking Change: no
First commit of the ck plugin, built from the phase-one PRD (code-katz/.github, plans/2026-09-05-ck-plugin-prd-phase-1.md, revision 3) after Phase 0 answered seven of eight spikes. The 21 persona profiles are imported once from the old team tool at commit b4b211fbf4ec6f4d365a550b55e9981610ed7dda and owned here from now on.
- Source of truth:
profiles/<name>.mdandtiers.conf.scripts/generate.shderivesagents/<name>.md(subagent form, on its tier),skills/<name>/SKILL.md(session switch, verbatim), andprofiles/ROSTER.md. It refuses to overwrite uncommitted hand edits to generated files. - Tiers: Fable 5.1 for River, Akira, Morgan, Sage, Jordan, Reiner; Opus 5 for the eleven craft seats; Sonnet 5 for the four execution seats.
- Workflows, taken verbatim from the PRD appendices:
panel,brief,draft(serves the PRD and the architecture document),team. Nested workflows are called by name, as Phase 0 showed. - Skills:
prd,next,review-page(the one place the gate mechanics live), and the contractsbrief-artifact,prd-artifact,architecture-artifact,team-artifact,memo-artifact. - Hooks:
SubagentStarton^ck:writes the usage log;SessionStartwarns while the old team tool is installed. - Tests:
tests/run.sh, static checks 1 to 11 from PRD §9, with two fixture projects.
- Profiles are owned here. One-time import; no vendoring, no lock, no relationship to the old tool.
- Generated files are never hand-edited. The generator refuses to overwrite uncommitted changes to them unless forced.
- PRD:
code-katz/.github,plans/2026-09-05-ck-plugin-prd-phase-1.md - Phase 0 record:
code-katz/.github,plans/2026-09-09-ck-phase-0-spikes.md