ui-server: an expired turn's unknown changedFiles/steeringFiles read back as 0

Open Beginner friendly
#3,259 0 comments 0 reactions 0 assignees View on GitHub

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

agent-ready area: ui-server priority: p2 type: fix

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 changedFiles and steeringFiles exactly, including null.

Out of scope

  • keptFiles (#3255), retention policy, and what expire() stores.
  • sharedAttribution, which is a boolean and not a count.
  • UI wording.

Acceptance criteria

  • An expired summary whose stored changedFiles/steeringFiles are null reports null for both. A known stored count, including a stored 0, 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

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from schlessera/brain-kit

All issues in schlessera/brain-kit

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.