Skip to content

Say the right thing about risk, and stop reading whole repos to draw a row - #85

Merged
heznpc merged 1 commit into
mainfrom
fix/work-screen-correctness
Aug 21, 2026
Merged

Say the right thing about risk, and stop reading whole repos to draw a row#85
heznpc merged 1 commit into
mainfrom
fix/work-screen-correctness

Conversation

@heznpc

@heznpc heznpc commented Aug 21, 2026

Copy link
Copy Markdown
Owner

Six defects from review of 69a318c, in priority order.

The warning marker was wrong in both directions, for two independent reasons

Wrong vocabulary. protectedWorktrees filtered on verdict != "reclaimable" — and reclaimable is not a value scree emits. The vocabulary is protected / rebuildable / unreadable, so the filter matched everything and every rebuildable worktree was reported as work the user must protect. unreadable now gets its own name and its own row: not safe, but calling it protected claims knowledge nobody has.

Wrong authority. Git state came from ArchiveCandidate, which rankCandidates builds by dropping .unsafe repos. Right for "what could be retired", exactly wrong as a project's git state — dirty trees, unpushed commits and missing remotes are what makes a repo unsafe:

before after
dirty / unpushed / no remote vanished, drawn as fine risks shown, no retirement offered
clean, dormant 400d ⚠ (dormancy counted as risk) no warning; dormancy is a note

assessRepos keeps every scanned repo; isRetirementEligible decides whether there is a retirement to review.

Expanding a project read every transcript in it

shown was expanded ? project.conversations : prefix(3). One click on a repo holding 2,767 sessions built 2,767 rows and handed all their paths to the title reader. The previous commit called this "bounded to what is visible" — expanded is the whole project, not the viewport. Now a page (50) at a time with 더 보기, which keeps the two-click path and bounds the read to what is on screen.

Three more of the same kind

  • Unplaceable conversations were dropped, and a test had fixed that as intended. The Gemini collector deliberately leaves the workspace empty rather than guessing — so this discovered conversations and then hid them. They group under 연결되지 않은 대화, sorted last.
  • Project identity was case-sensitive, regressing the case folding scree's lineage does for a documented reason (macOS is case-insensitive; each provider records its own casing). One folder became two projects. Keyed on the folded path, displayed with its real spelling.
  • Grouping roots came from retirement candidates, making "does /repo/subdir belong to /repo" depend on whether /repo survived the archive classifier. Roots now come from every git path the audit saw.

Retirement sheet

It was answering a retirement question with the browser's grouping. It shows the binder's own result again — binding count by confidence, plus coverage — and refuses to conclude "nothing would be lost" from an incomplete pass. Title said "은퇴하시겠습니까?" over a permanently disabled primary button; that is a confirmation dialog that cannot confirm, so it now reads as a review with a single 닫기.

Verification

  • Python 633 · Modore 261 (+14) · MothballCore 120, green with CI flags.
  • Every fix has a test, including the two verdict-vocabulary cases and both directions of the warning bug.
  • The release audit caught two local user paths in the new comments/tests — fixed, --check-only clean.
  • Not driven in the GUI this round. Screen-control approval is per-session and was re-prompting the user on every relaunch, so I stopped; covered by unit tests and the app build only.

…a row

Six defects from review, all in the 작업 screen shipped by 69a318c.

The warning marker was wrong in both directions at once, for two
independent reasons.

`protectedWorktrees` filtered on `verdict != "reclaimable"`, and
`reclaimable` is not a value scree emits -- the vocabulary is
`protected` / `rebuildable` / `unreadable`. The filter therefore matched
everything, and every rebuildable worktree was reported as work the user
must protect. `unreadable` now has its own name: it is not safe, but
calling it protected claims knowledge nobody has.

Git state came from `ArchiveCandidate`, which `rankCandidates` builds by
dropping `.unsafe` repos. That is right for "what could be retired" and
exactly wrong as a project's git state, because dirty trees, unpushed
commits and missing remotes are what make a repo unsafe -- so the repos
carrying the most valuable work disappeared and were drawn as having
nothing wrong, while clean long-dormant repos got a warning triangle for
being dormant, which is the very reason they are good candidates. Repo
assessment and retirement eligibility are now separate: every scanned
repo keeps its verdict, `isRetirementEligible` decides whether there is
a retirement to review, and dormancy is stated as a note rather than a
risk.

Expanding a project read every transcript in it. `shown` was
`expanded ? project.conversations : prefix(3)`, so one click on a repo
holding 2,767 sessions built 2,767 rows and handed all of their paths to
the title reader. The previous commit called that "bounded to what is
visible"; expanded is the whole project, not the viewport. Now a page at
a time, which keeps the two-click path and bounds the read to what is
actually shown.

Three more, smaller but the same kind of mistake:

- Conversations whose workspace could not be resolved were dropped by
  the builder, and a test had fixed that as intended. The Gemini
  collector deliberately leaves the workspace empty rather than guessing,
  so this discovered conversations and then hid them. They now group
  under 연결되지 않은 대화, sorted last.
- Project identity was case-sensitive, regressing the case folding
  scree's lineage does for a documented reason: macOS is case-insensitive
  by default and each provider records its own casing, so one folder
  became two projects. Keyed on the folded path now, displayed with its
  real spelling.
- Project grouping derived its roots from retirement candidates, which
  made "does /repo/subdir belong to /repo" depend on whether /repo
  survived the archive classifier. Roots now come from every git path the
  audit saw.

The retirement sheet was using the browser's grouping to answer a
retirement question. It shows the binder's own result again -- binding
count by confidence, and coverage -- and refuses to conclude "nothing
would be lost" from an incomplete pass. Its title said
"은퇴하시겠습니까?" over a permanently disabled primary button, which is
a confirmation dialog that cannot confirm; it reviews, and now says so.

Python 633 · Modore 261 · MothballCore 120. The release audit caught two
local user paths in the new comments and tests; fixed.
@heznpc
heznpc merged commit 112b315 into main Aug 21, 2026
8 checks passed
@heznpc
heznpc deleted the fix/work-screen-correctness branch August 21, 2026 19:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant