Skip to content

CPLAT-12457: add Scratchpad to the daily Produced pane - #170

Merged
gavin-jeong merged 1 commit into
masterfrom
CPLAT-12457-daily-scratchpad-tab
Sep 29, 2026
Merged

gavin-jeong merged 1 commit into
masterfrom
CPLAT-12457-daily-scratchpad-tab

Conversation

@gavin-jeong

Copy link
Copy Markdown
Collaborator

JIRA: https://sendbird.atlassian.net/browse/CPLAT-12457

The daily view's Produced pane offered All / PRs / Jira / Artifacts / Plans, so the files a day's sessions actually worked in were invisible at the day level — even though OutputScratchpad already exists as a kind and the per-session Outputs digest lists it.

Two things were missing, not one

buildDayOutputRows only reads Refs and PlanSlugs, both of which the session scan already carries. Adding the tab alone would have produced a permanently empty one — the data had to be collected too.

Why it is collected asynchronously

A scratchpad is a directory walk per session. Measured across the 25 real scratchpads on this machine: 129ms total, 62ms for the worst single one. A day can hold 250+ sessions, and buildDayOutputRows runs on every cursor move, tab switch and query keystroke — collecting inline would stall the pane on every interaction.

So it is dispatched off the UI thread and cached per session ID:

  • the pane renders immediately from whatever is cached; rows fill in as walks land
  • fan-out is capped at 8 in flight, with the remainder picked up as each completion re-renders the pane — that is what lets a busy day finish collecting without dispatching hundreds of walks at once
  • results survive walking away and back, so re-visiting a date is free

collectScratchpadOutputs is exported as session.ScratchpadOutputs for this.

Notes

Rows carry Path and the session anchor, so Enter (open the conversation), e (open in $EDITOR) and the copy action all work with no extra wiring — verified in a test rather than assumed.

The walk already reports a cloned repository as one row instead of descending into it, so the 6,805-file scratchpad measured here collapses to two rows and the digest stays readable.

Test plan

  • go build ./... && go vet ./... && go test ./... green
  • Four tests, each verified by reverting the relevant part and confirming the failure:
    • TestDayPaneCollectsScratchpad — rows appear only after the walk lands (also asserts they are absent before, so the async path is real)
    • TestDayPaneScratchpadTabFilters — All interleaves kinds; the Scratchpad tab shows only scratchpad
    • TestDayPaneScratchpadRowIsActionable — Path and session anchor present, edit/copy offered
    • TestDayPaneScratchpadCollectionIsBounded — cap respected, and a later render dispatches the next batch rather than re-dispatching
  • Exercised against real on-disk scratchpads, not only fixtures (that is where the 129ms/62ms numbers come from)

One test assertion changed — please check this

TestDailyPreviewShowsDaySummary asserted cmd == nil, as a proxy for "the day pane is instant, no transcript reads". That proxy no longer holds, since background enrichment is now dispatched. The property it was protecting — the pane is fully rendered by the time the call returns — does still hold, so the test now asserts that directly.

I want a second pair of eyes on that: it is the one place where I relaxed an existing guarantee's wording, and I would rather be told I got it wrong than have it slip through.

Security checklist

  • No SecurityGroup rule changes
  • No 0.0.0.0/0 inbound
  • No public subnet resources
  • No IAM user changes
  • No secrets in code, commits, or logs

The day pane offered All / PRs / Jira / Artifacts / Plans, so the files a
day's sessions actually worked in were invisible at the day level — even
though OutputScratchpad already exists as a kind and the per-session
Outputs digest lists it.

Two things were missing, not one. buildDayOutputRows only reads Refs and
PlanSlugs, both of which the session scan already carries, so adding the
tab alone would have produced a permanently empty one.

Scratchpad is different from the other kinds: it lives on disk and costs
a directory walk per session. Measured across the 25 real scratchpads on
this machine, that is 129ms total and 62ms for the worst single one. A
day can hold 250+ sessions and buildDayOutputRows runs on every cursor
move, tab switch and query keystroke, so collecting inline would stall
the pane on every interaction.

It is therefore dispatched off the UI thread and cached per session ID:

  - the pane renders immediately from whatever is cached, and rows fill
    in as walks land
  - fan-out is capped at 8 in flight, with the remainder picked up as
    each completion re-renders the pane — that is what lets a busy day
    finish collecting without dispatching hundreds of walks at once
  - results survive walking away and back, so re-visiting a date is free

collectScratchpadOutputs is exported as session.ScratchpadOutputs for
this.

Rows carry Path and the session anchor, so Enter (open the conversation),
e (open in $EDITOR) and the copy action all work with no extra wiring.
The walk already reports a cloned repository as one row instead of
descending into it, so the 6,805-file scratchpad measured here collapses
to two rows and the digest stays readable.

Four tests, each verified by reverting the relevant part and confirming
the failure: collection and async arrival, tab filtering, row
actionability, and the fan-out bound.

TestDailyPreviewShowsDaySummary asserted cmd == nil as a proxy for "the
pane is instant". That proxy no longer holds — background enrichment is
now dispatched — but the property it was protecting does, so it asserts
the content is fully rendered on return instead.
@upwind-code-us

upwind-code-us Bot commented Sep 29, 2026 •

Copy link
Copy Markdown

Upwind Upwind Code Scan - ✅ Passed

0 newly introduced vulnerabilities · 0 resolved · 1 total in this PR vs master

Total breakdown: 🔶 1 High

View full analysis in Upwind Console

Scan completed in 7s

Scan history (1 scan)
Commit Scanned at New Resolved Net
d0583fd < 2026-09-29 07:45 UTC 0 0 0

Last scanned: d0583fd · 2026-09-29 07:45 UTC

@upwind-code-us

upwind-code-us Bot commented Sep 29, 2026 •

Copy link
Copy Markdown

Upwind Upwind IaC Scan - ✅ Passed

0 newly introduced misconfigurations · 0 resolved · 0 total in this PR vs master

View full analysis in Upwind Console →

Scan completed in 5s

Scan history (1 scan)
Commit Scanned at New Resolved Net
d0583fd < 2026-09-29 07:45 UTC 0 0 0

Last scanned: d0583fd · 2026-09-29 07:45 UTC

@Kairo-Kim Kairo-Kim added the auto-review/approved Auto-approved by the Slack auto-reviewer bot label Sep 29, 2026

@jinsekim jinsekim left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@gavin-jeong
gavin-jeong merged commit db5e224 into master Sep 29, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

auto-review/approved Auto-approved by the Slack auto-reviewer bot

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants