ui-server: an expired turn's unknown changedFiles/steeringFiles read back as 0
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 72/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Active
- Tech stack
- typescript
- Domain
- backend
Research direction
Start with the summary() function in packages/ui-server/src/brain/turn-journal.ts (around lines 251-263), where the ?? fallthrough lets a stored null for changedFiles and steeringFiles reach the live count, and check how expire() (around lines 272-283) stores those values. Make a retained summary return its stored values exactly, including null. Run packages/ui-server/tests/turn-journal.test.ts and add a file-backed case with an expired row whose stored counts are null, which should fail on the current 0.
Written by the indexing model from the issue text.
Description
Context
Found while implementing #3255. The defect is already on main. It does not depend on #3255 landing.
When the host collects an ended turn under capacity pressure, expire() stores that turn's summary counts as JSON (async function expire, packages/ui-server/src/brain/turn-journal.ts:272-283 at main 3b9f3e84b). A partial turn that recorded no changes has changedFiles: null and steeringFiles: null, and those null values are stored.
On read, summary() takes retained?.changedFiles ?? (partial && !counts.changedFiles ? null : counts.changedFiles), and the same for steeringFiles (function summary, packages/ui-server/src/brain/turn-journal.ts:251-263). A stored null falls through to the live count. The change rows were deleted on expiry, and partial is always false for an expired row (line 257), so the live count reports 0.
Observed on the 0.44.0 tree plus #3255. The probe used the native journal fixture: it stored the summary {"changedFiles":null,"steeringFiles":null,…} on an expired row, and summary() then returned changedFiles: 0, steeringFiles: 0. An unknown count therefore reads as zero. The type's own rule forbids that: "absent counts and prices are never zero" (TurnJournalSummary, packages/ui-sdk/src/turn-journal.ts:1-2). On #3255's branch, keptFiles already reads a stored null as null.
Scope
- A retained (expired) summary reports its stored
changedFilesandsteeringFilesexactly, includingnull.
Out of scope
keptFiles(#3255), retention policy, and whatexpire()stores.sharedAttribution, which is a boolean and not a count.- UI wording.
Acceptance criteria
- An expired summary whose stored
changedFiles/steeringFilesarenullreportsnullfor both. A known stored count, including a stored0, is reported unchanged. - A real file-backed test drives an empty partial turn through capacity collection, or stores the same retained JSON. It fails before the change on the
0.
Verification
Run packages/ui-server/tests/turn-journal.test.ts, and journal-kept-files.test.ts too if #3255 has landed by then. Include a mutation receipt showing the test fails with the ?? fallthrough restored.
Contract impact
None. This corrects behavior to match the existing documented rule that missing facts are unknown, never zero.
2026-11-02 triage at main 3b9f3e84b: Re-anchored the citations to main and confirmed by reading the source that the fallthrough exists on main without #3255. A stored null reaches ??, and an expired row is never partial. No local runtime repro was run; the observation above comes from the filer's native-fixture probe. Not blocked by #3255. Set priority: p2: this is an honesty-rule correctness defect with no milestone commitment.
- Dominant language
- TypeScript
- Stars
- 3
- Forks
- 0
- Avg merge
- 5h 8m
- Merged PRs (30d)
- 946
Getting set up
- No Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from schlessera/brain-kit
-
agent-ready area: backends area: ui-sdk priority: p1 type: fix
Difficulty 2/5 1-3 hours Newbie friendliness 66/100
schlessera/brain-kit#3519 · 1 comment ·
Maintainers usually reply within 1 day
-
agent-ready area: docs priority: p3 type: docs
Difficulty 1/5 Under an hour Newbie friendliness 78/100
schlessera/brain-kit#3479 ·
Maintainers usually reply within 1 day
-
agent-ready area: ci priority: p2 type: fix
Difficulty 2/5 1-3 hours Newbie friendliness 62/100
schlessera/brain-kit#3318 ·
Maintainers usually reply within 1 day
-
agent-ready area: ui-kit priority: p2 type: docs
Difficulty 1/5 Under an hour Newbie friendliness 90/100
schlessera/brain-kit#3188 ·
Maintainers usually reply within 1 day
-
agent-ready area: ui-server type: test
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
schlessera/brain-kit#3009 · 1 comment ·
Maintainers usually reply within 1 day
All issues in schlessera/brain-kit
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
vercel-labs/durable-harness#53 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
Maintainers usually reply within 1 day
-
area/docs area/ui enhancement
Difficulty 1/5 1-3 hours Newbie friendliness 88/100
melgarafael/DeskcommCRM#4098 ·
Maintainers usually reply within 1 day
-
bug ready-for-agent
Difficulty 2/5 1-3 hours Newbie friendliness 86/100
kerti/balances-v2#801 ·
Maintainers usually reply within 1 day
-
lesson-submission pending-review
Difficulty 1/5 Under an hour Newbie friendliness 84/100
Ikalus1988/MisakaNet#4510 ·
Maintainers usually reply within 1 day