Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .claude/skills/verify-t3term/features/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Read the file for a feature before you drive it, and fix the file when a drive s
| Thread details: opening, pane or dialog, tabs, the Thread tab's facts | [thread-details.md](thread-details.md) | `links` |
| Linked pull requests: the details' Pull requests tab | [linked-pull-requests.md](linked-pull-requests.md) | `links` |
| Pull request page: what a link's details read from its host, on a Summary and a Timeline | [pull-request-page.md](pull-request-page.md) | `links` |
| Pull request live refresh: the reads that keep a link's details current while you use t3term | [pull-request-live-refresh.md](pull-request-live-refresh.md) | `links` |
| Lineage: related threads, forks and agents in the details | [lineage.md](lineage.md) | `lineage` |
| CLI: commands, `--json` and exit codes against a fake server | [cli.md](cli.md) | `links` |
| Saved environments: the `environment` commands, `environment status` and the descriptor cap | [environments.md](environments.md) | `links` |
Expand Down
50 changes: 50 additions & 0 deletions .claude/skills/verify-t3term/features/pull-request-live-refresh.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Pull request live refresh

## Sub-features

- **Reading every 5 minutes.** While a link's details show, t3term reads the pull request again 5 minutes after its last read was asked for, if a key, click, wheel, mouse move or paste came in the 6 minutes before. The Summary's row reads `Refreshing from github.com…` meanwhile, as for any read again (pull-request-page.md).
- **The detail first.** Such a read sends `pullRequests.detail` alone, and `pullRequests.activity` only when the detail's `updatedAt` changed, as the desktop does. A detail that stayed the same keeps the last conversation. A read that failed is read again in full, and after a conversation that failed the next read asks for both.
- **Idle and coming back.** After 6 minutes with no input t3term asks the host nothing more, and the event loop doesn't wake for it. The first input after that reads at once, unless the last read was asked for under 10 seconds ago.

## How to get to it (user POV)

Open a link's details as pull-request-page.md describes and leave them open. Nothing to press: any key, click or wheel within 6 minutes keeps the reads going, and the first one after a longer pause reads at once.

## Driving it with t3v

Scenario `links` at 200x60, so the Summary shows `Comments (5)` without a scroll. The 5 and 6 minutes are t3term's own and can't be shortened, so the recipe takes about 6 minutes and 15 seconds. `t3v revise` changes #60's `updatedAt` and adds a remark to its conversation without a refresh number, as a change on the host that T3 didn't hear of. `t3v wait` and `t3v status` send t3term no input.

```bash
$T3V start --rows 60
$T3V click --text "Mixed: every state" && $T3V wait --text "/ Mixed: every state"
$T3V keys M-b && $T3V wait --text "Pull requests 11"
$T3V keys Tab Tab Right && $T3V wait --text "#62" --text "9 open · 11 linked"
$T3V keys End Up Enter && $T3V wait --text "10 of 11" --text "Reading from github.com…"
$T3V wait --text "#60 Merged: footer counts" --text "Read from github.com just now" --text "Comments (5)" --gone "Reading"
$T3V status --json | jq -e '.rpcRequestsByTag["pullRequests.detail"] == 1 and .rpcRequestsByTag["pullRequests.activity"] == 1'

# No input from here. 5 minutes after the read was asked for, the details read the detail alone. Its updatedAt is the same, so the conversation stays.
$T3V wait --text "Refreshing from github.com…" --gone "Read from" --timeout 320
$T3V capture live-refreshing
$T3V wait --text "Read from github.com just now" --text "Comments (5)" --gone "Refreshing from"
$T3V wait --idle 3500
$T3V status --json | jq -e '.rpcRequestsByTag["pullRequests.detail"] == 2 and .rpcRequestsByTag["pullRequests.activity"] == 1'

# The pull request changes on the host without a refresh number. Over 6 minutes after the last key nothing reads, and the first input reads at once. The detail's updatedAt changed, so the read asks for the conversation too, which gains a remark.
$T3V revise
$T3V wait --idle 65000 --timeout 80
$T3V status --json | jq -e '.rpcRequestsByTag["pullRequests.detail"] == 2 and .rpcRequestsByTag["pullRequests.activity"] == 1'
$T3V click --text "Summary" && $T3V wait --text "Refreshing from github.com…" --gone "Read from"
$T3V wait --text "Read from github.com just now" --text "Comments (6)" --gone "Refreshing from"
$T3V capture came-back
$T3V status --json | jq -e '.rpcRequestsByTag["pullRequests.detail"] == 3 and .rpcRequestsByTag["pullRequests.activity"] == 2'
jq -se '[.[] | select(.event == "pr.detail" or .event == "pr.activity")] | map(.event) == ["pr.detail", "pr.activity", "pr.detail", "pr.detail", "pr.activity"] and all(.number == 60)' "$($T3V status --json | jq -r .evidence)/events.jsonl"
```

## Gotchas

- A key or click sent to the run counts as input. One during the 65-second wait starts the 6 minutes over, and the click after it reads nothing. Leave the run alone while the recipe waits.
- The 5 minutes count from when the last read was asked for, and a refresh number's read, `r` or opening the link again starts them over. The recipe sends none of those.
- `Refreshing from github.com…` shows on the Summary only: 1.5 s for a read of the detail alone, and 4.5 s when the conversation follows.
- `Read from github.com just now` stays on screen through the 5 minutes, since nothing draws a frame while t3term idles. Wait for `Refreshing from`, not for the age.
- No step shows a failed read read again in full, or a read held back within 10 seconds of the last, since each needs another 5 or 6 minutes. The unit tests `details_whose_read_failed_read_it_again_after_five_minutes_while_in_use` and `a_read_that_keeps_details_current_reads_a_conversation_that_failed_again` cover the first, and `the_details_read_their_detail_again_after_five_minutes_while_in_use` the rest.
2 changes: 1 addition & 1 deletion .claude/skills/verify-t3term/features/pull-request-page.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
- **Summary and Timeline.** Once T3 answers with the pull request, the row above the details reads `← List Summary Timeline` with the open tab lit, and in the 32-column pane it drops `3 of 11` to fit. The details open on the Summary, which the bullets above describe. → or `l` shows the Timeline, ← or `h` goes back to the Summary and then to the list, and a click on a tab's name shows it. The status line reads `→ timeline` on the Summary and `← summary` on the Timeline. Each tab keeps its own scroll, and the Timeline keeps its order, while the details stay open. A read of the pull request that failed shows no tabs.
- **The Timeline.** Under the link's status rows a header counts the comments, the commits and the approvals that still stand, `28 comments · 2 commits · 1 approval`, with the order switch at the end of its row, or on a row of its own when they don't fit. The approvals are left out when the host cut the conversation short or t3term kept only the first 2,000 remarks or 1,000 commits T3 sent. The opening, the commits, the verdicts, the runs of other comments and the merge or close follow in one list, newest first until the switch turns it to `Oldest first`. A commit shows `○`, its headline (`Untitled commit` without one, cut with `…` to leave room for the size), its size such as `+34 -6`, then its short id, its first author and when. A verdict shows `✓ fixture-reviewer approved`, `✗ mona` with `changes requested` or `– lee` with `review dismissed`, then when and its text, and one given before the newest commit adds `, before the latest commits`. A run of other comments is one closed row, `› 11 comments` with `2 authors · 1h ago` under it, whose age is its first remark's in the order shown. Open, `⌄ 3 comments` lists each remark's author with `commented` or the review's state, when, its place and its text. `● fixture-dev` with `Pull request opened` starts the pull request, and `● Pull request merged` or `● Pull request closed` ends it. ↓ and ↑ choose the switch and the runs as they do on the Summary, with `Enter oldest first`, `Enter newest first`, `Enter show comments` or `Enter hide comments` on the status line. A conversation that failed shows `Could not load pull request activity` here too. The Timeline asks T3 for nothing more. It shows the same detail and activity answers as the Summary.
- **A failed read.** The reason shows in place of the summary and the comments: the desktop's sentence for a host T3 can't read, such as `No GitHub credential on the server.` with how to give it one, T3's words for one the host can't find, such as `Pull request #62 was not found.`, or `Couldn't read this pull request:` and the error.
- **What it asks T3.** One `pullRequests.detail` and one `pullRequests.activity` per open, sent together, each with the thread's project and the link's host, repository and number. Each answer shows as it comes. t3term keeps the answers for the link whose details opened last and reuses them for 60 seconds from when the pull request came, so opening the same link again in that minute asks nothing unless T3's refresh number changed, and opening another link drops them. A read where either answer failed is asked again on the next open, over the answers it has. One read is under way at a time, until both its answers came: a link opened during it reads `Reading from…` and is asked for once that read is over, and leaving its details first drops it. Nothing is read on an environment without `pullRequests: true` in its capabilities, and only a refresh number or `r` reads an answer again while the details show it.
- **What it asks T3.** One `pullRequests.detail` and one `pullRequests.activity` per open, sent together, each with the thread's project and the link's host, repository and number. Each answer shows as it comes. t3term keeps the answers for the link whose details opened last and reuses them for 60 seconds from when the pull request came, so opening the same link again in that minute asks nothing unless T3's refresh number changed, and opening another link drops them. A read where either answer failed is asked again on the next open, over the answers it has. One read is under way at a time, until both its answers came: a link opened during it reads `Reading from…` and is asked for once that read is over, and leaving its details first drops it. Nothing is read on an environment without `pullRequests: true` in its capabilities, and only a refresh number, `r` or the reads that keep the details current (pull-request-live-refresh.md) read an answer again while the details show it.
- **Reading again.** While the details hold a read, t3term follows `pullRequests.subscribeRefreshes`, one subscription for every link. The first number it hears is where T3 stands. A later number that differs reads the detail and the conversation again at once while the details show them, and otherwise the next time they show, even within the minute. Opening a link's details again after the minute reads again the same way. Meanwhile the Summary's row reads `Refreshing from github.com…` over the last answers, and both new answers replace the old ones once both came. A failure replaces only a failure. Where the detail failed there is no summary to show over, so the details read `Reading from github.com…` in place of the failure, as a first read does. On the Timeline a run is known by its newest remark, so a run that was open stays open when a read again adds rows above it, and a run that a newer remark joins starts closed. The subscription closes once the details hold no read, and one that T3 refuses or ends isn't asked for again.
- **Reading from the host again.** `r` in a link's details reads its pull request from the host again, as the desktop's Refresh menu item does. t3term sends `pullRequests.invalidate` with the link's project, host, repository and number, then the detail and the conversation as one read, and the details show it as any read again: `Refreshing from github.com…` over the last answers, or `Reading from github.com…` where the detail failed. `r` does nothing while a read of the link waits or is under way, and the status line offers `r refresh` only when `r` would read. The invalidate raises T3's refresh number, and the first number heard during that read reads nothing more, so one press costs one read.

Expand Down
Loading
Loading