A week in the life
A week in the life is one real feature on stockroom, taken from Monday to Friday using everything in part two. Seventeen lessons of pieces. This one is the shape they make when you are working rather than learning, on a job stockroom needs doing.
The feature: stock cannot be written off. Lesson 27 named it. MovementKind has an
adjustment, but record() refuses a quantity of zero or less and only negates a pick,
so there is no way to record ten damaged units leaving the shelf. The warehouse has been
recording write-offs as picks against a fake sales order, which is why the June stock take
had drift nobody could explain.
That is a real feature request with a real cause, and it touches the ledger, the valuation and the CLI. Let us do it properly.
Monday: understand, do not build
Clean tree, fresh session, plan mode.
Stockroom cannot record a downward stock adjustment: record() rejects a quantity of
zero or less, and NEGATIVE only contains "pick". I want to add write-offs. Before
proposing anything, tell me every place that assumes a movement's sign implies its
kind.
Two things about that prompt. It states the cause rather than the symptom, because I already did the reading in lesson 27 and there is no reason to make it rediscover that. And it asks for the blast radius before the plan, because the file list is the part of a plan worth having.
The answer should include averageCost() in src/domain/stock.ts, which branches on
movement.quantity > 0, and that is the interesting one: a write-off with a positive
quantity would be valued as a purchase. The fix is not “let quantities be negative”. It is
“stop inferring kind from sign”.
Read that answer against the source before approving anything. Lesson 13.
Monday, later: the plan
Still in plan mode:
Plan it. Adjustments carry a signed quantity; picks keep working exactly as they do.
averageCost must branch on kind rather than sign. Add a `writeoff` CLI command.
Do not touch src/server/main.ts.
The constraints are doing the work. Each one is a decision I made, in a sentence, and each one closes off an approach it would otherwise have to guess about.
Read the plan for the file list, the order, and the size. If src/reports/index.ts is in it
and you did not expect that, find out why before approving. Lesson 14.
Approve with Yes, manually approve edits, because this touches money.
Tuesday: the loop
Now it is lesson 12, repeatedly. Ask, read the diff, accept or push back.
Push back on the things that matter and let the rest go:
- “That makes the valuation branch on
kind, butreturnis still falling into the purchase branch. Handle it in the same change or say why not." - "You changed the error message for the existing quantity check. Leave it.”
Two rounds and no convergence means write it yourself. On a change to averageCost the bar
should be low, because it is nine lines and it is money.
Run the tests inside the session so the output is in the conversation. Commit at each point where things work, with a message it writes from the diff. Lesson 19.
Tuesday, still: prove it
The habit from lesson 27, applied before the feature is finished rather than after.
Write a failing test first: ten units written off at an average cost of 300 should
reduce the value by 3000 and leave the average at 300. Do not change any source until
the test fails for the right reason.
”For the right reason” is the load-bearing phrase. A test that fails because the function does not exist yet has told you nothing.
Wednesday: the guard rails
The feature works. Now make the next person’s version of it work too.
Add to CLAUDE.md, because it is a fact every session needs:
- A movement's sign does not imply its kind. Adjustments are signed; picks are always
negative. Branch on `kind`, never on the sign, when the two mean different things.
That is one line, it is specific, and it is checkable. Lesson 15.
Add to the add-report skill if the procedure changed, and to report-reviewer if there is
a new thing to check. Those are the parts of lessons 21 and 22 that keep paying.
And ask whether the rule needs a hook. This one does not: it is a convention, and conventions
belong in memory. “Nobody may edit data/seed.json” is a hook, because it is mechanical and
absolute. Knowing the difference is lesson 23.
Thursday: let the machine review it
./review.sh main
The gate from lesson 26 on the whole branch. It is looking for the thing you stopped being able to see three days ago: a behaviour change the commit message does not describe, a change with no test.
Then the second opinion, in a fresh session:
Read the diff on this branch. Make the strongest case that this change is wrong.
A fresh session, because one that helped write the change has the change in its context and will defend it. Lesson 27.
Friday: the pull request
Open a pull request against main. The body should say what was broken, why it produced
the June stock take drift, and how to verify the fix.
Check the base branch and check what it claims. A PR description assembled from the diff and the commits beats one written from memory, and it still needs reading, because it was written before the last commit landed. Lesson 19.
Then /clear, and the week is over.
What should you keep from part two?
If you keep four things from part two, keep these.
Read the diff. Every time, for as long as you are shipping the result. This is the whole job and it is the first thing to go when you get comfortable.
Make claims executable. A failing test settles in thirty seconds what a conversation cannot settle at all.
/clear between tasks. Free, invisible, and the highest-value habit in lesson 16.
Write the thing down when you have said it twice. CLAUDE.md for a fact, a skill for a
procedure, a hook for a rule. The compounding is real and it is slow enough that you have to
do it deliberately.
What to stop
Stop asking broad questions. “Explain the reports module” costs four times what “@src/reports/index.ts what does lowStock do” costs and answers worse.
Stop running everything at maximum. Lesson 17 measured it: twenty-one times the cost for one answer. Sometimes that is the right trade and usually it is not.
Stop letting a bad session run long. Six failed attempts in the context make the seventh worse. Clear, and start again with what you learned.
Stop accepting summaries. A subagent’s report, a plan’s description, a PR body, an explanation of code you have not opened. Every one is a place where a confident sentence substitutes for a fact you could check in a minute.
Stop building setup you do not use. Eleven commands, four of which you have forgotten. Delete them like you would delete a stale script.
Your turn
Build the write-off feature on a branch, using the week above as the shape.
The requirements, so you can check yourself:
record()accepts a signed quantity forkind: "adjustment". Picks are unchanged and still refuse a quantity of zero or less.averageCost()branches onkind. A negative adjustment leaves the average cost where it is and reduces the units, exactly as a pick does.- A
writeoff <sku> <qty>command exists insrc/cli/main.ts, with a--reasonflag, andUSAGEmentions it. - Tests cover a write-off after a price change, and the existing 86 still pass.
src/server/main.tsis untouched.
Check:
npm testreports 89 or more passing and none failing,npx tsc --noEmitprints nothing,git status --shortshows no change tosrc/server/main.ts, andnode src/cli/main.ts writeoff BOLT-M8 5 --reason damagedfollowed bynode src/cli/main.ts valueshows the total value going down. If it goes up, you have reproduced the original bug in a new place, which is worth knowing and is exactly why requirement 2 is written the way it is.
Then run ./review.sh main and read what it says about your own work.
There is a tag for this one, after-lesson-28, and it is the only tag in the course that
is an answer rather than a starting point. Do not open it until you have shipped your own
version or given up on it, and when you do, read it as a diff rather than a solution:
git diff after-lesson-27 after-lesson-28
Two things in there are worth arguing with. It branches averageCost on kind rather than
fixing the default in record, which is one of the two options this course said were both
two lines. And it negates the quantity inside the CLI command rather than in the domain, so
that writeoff BOLT-M8 5 reads the way somebody says it out loud. Both are choices. If you
made the other one and your tests are green, you have not done it wrong.
Recap
The week has a shape: understand before planning, plan before changing, read every diff, prove claims with tests, write down what you had to say twice, and let a fresh session argue against you at the end.
None of the individual pieces are difficult. What makes the difference is that the checking does not get dropped when the work gets comfortable, because the failure mode of this tool is not code that breaks. It is code that works and is wrong.
You have the repository, and it still has at least one bug in it that this course did not name. Go and find it.