Skip to content

[3276 by Claude Opus 5.5] Short landscape task viewport leaves changed files covered and untappable - #3277

Merged
integry merged 3 commits into
mainfrom
3276/claude-opus-5-5-short-landscape-task-view-20261019-2225-x6v
Oct 20, 2026
Merged

integry merged 3 commits into
mainfrom
3276/claude-opus-5-5-short-landscape-task-view-20261019-2225-x6v

Conversation

@propr-dev

@propr-dev propr-dev Bot commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

AI Implementation Summary

Closes #3276

Branch: 3276/claude-opus-5-5-short-landscape-task-view-20261019-2225-x6v
Commits: ✅ Changes committed (ba5e743)


AI Processing Completed

Execution Details:

Summary:
I fixed #3276. At 844×390 touch landscape and in an 880×480 desktop window, the changed file can now be scrolled into view with a finger or the mouse wheel, tapped, its diff opened and closed. I tested this in headless Chromium against stubbed task data. It has not been run against real API data or on a real phone.

Cause. From 640px wide up, the task page uses the desktop layout. It pins the task header and gives only the area below it its own scroll. In a short window that area was too thin: about 100px in my reproduction, 58px in your measurement. The pinned Timeline and Files headings and the log bar covered nearly all of it, so the file row could never be tapped.

Fix.

  • New useShortWorkspace.ts: it measures how much height the header leaves for the timeline/files area. It counts the collapsed log bar and the pinned headings, and allows about 184px for rows. It also respects the visible area when an on-screen keyboard shrinks it, but ignores pinch zoom. The measurement doesn't depend on which layout is active, so it can't flip back and forth.
  • In TaskDetails/index.tsx, when there isn't enough room:
    • the whole task scrolls as one page, the way phones already do.
    • the header scrolls away with it, but all its metadata and actions are still there when you scroll back up.
    • the Timeline and Files headings still pin, now to the top of the page.
    • the execution-log bar stays pinned at the bottom, and opening it keeps its normal height.
    • extra scroll padding keeps a focused or revealed row clear of the pinned headings and the log bar.
  • Unchanged: tall desktop windows, portrait phones, how the timeline heading sits above its content, and returning focus to the file row when the diff closes. The diff dialog's existing scroll lock still holds the page in place.

Tests. The new e2e/task-details-short-viewport.pw.ts covers 844×390 touch landscape, 880×480 desktop, 320×640 and 390×844 portrait, and 1280×820 desktop. Each uses a completed PR task with a long two-line title and subtitle, 8 runs and one modified 121-line Markdown file. It:

  • scrolls only with real touch swipes or wheel input.
  • checks that a tap at the row's centre actually reaches the row and that the visible area is usable.
  • opens and closes the diff, then checks focus and scroll position are restored.
  • opens and closes the execution log.
  • scrolls back up and opens the header's "More task actions" menu.

On the old code the two short cases fail the way the issue describes: at 844×390 the row can't be scrolled to a tappable spot, and at 880×480 only 51px of the area is visible.

One existing test changed behaviour. In task-timeline-heading-layering.pw.ts, the case that docks the task beside the list at 1280×820 with 150% text now uses the new page-scroll layout. There, the enlarged header is 423px tall and leaves only about 97px for rows, the same problem as the issue. The test now scrolls the whole page and still checks that nothing paints over the Timeline heading.

Results. All 270 tests in the task-* browser suites pass, as do 424 TaskDetails unit tests, eslint with zero warnings and tsc. The new spec passed 3 times in a row. I didn't touch any files from #3273, #3274 or #3275, and added no dependencies.

The 844×390 and 880×480 previews show the revealed file row and the opened diff. Separately, Gmail, Google Calendar and Google Drive need authorizing in your claude.ai connector settings before they can be used. This task didn't need them.

Detailed Logs:

  • Conversation: 132 messages
  • Session: af414cd5-6b2b-49ee-ba31-ba0e9591f51d

Log files stored at:

  • conversation: /usr/src/app/logs/executions/issue-3276-2026-10-19T23-00-40-212Z-conversation.json
  • output: /usr/src/app/logs/executions/issue-3276-2026-10-19T23-00-40-212Z-output.txt
Latest Conversation Messages
ASSISTANT: [content unavailable]

ASSISTANT: I fixed #3276. At 844×390 touch landscape and in an 880×480 desktop window, the changed file can now be scrolled into view with a finger or the mouse wheel, tapped, its diff opened and closed. I teste...


This PR was created automatically by ProPR after processing issue #3276.


💡 Need changes?

Comment on this PR to request refinements — the AI agent monitors comments and will update the implementation based on your feedback. Keep iterating until you're satisfied!


Visual preview

844x390 touch landscape: diff opened by tap

844x390 touch landscape: diff opened by tap

The file's diff, opened by an ordinary tap after touch scrolling.

Original unavailable: managed storage is unavailable or the upload has expired.

880x480 short desktop window: diff

880x480 short desktop window: diff

The file's diff, opened by a click on the revealed row.

Original unavailable: managed storage is unavailable or the upload has expired.

844x390 touch landscape: changed file reachable

844x390 touch landscape: changed file reachable

The task header has scrolled away with the page. The changed Markdown file row is in open workspace between the pinned Timeline heading and the execution-log bar.

Original unavailable: managed storage is unavailable or the upload has expired.

880x480 short desktop window: changed file reachable

880x480 short desktop window: changed file reachable

A short desktop window scrolls the whole task, so the file row can be reached with the mouse wheel.

Original unavailable: managed storage is unavailable or the upload has expired.

…indow, the changed file can now be scrolled into view with a finger or the mouse wheel, tapped, its diff opened and closed. I tested this in headless Chromium against stubbed task data. It has not been run against real API data or on a real phone.

Cause. From 640px wide up, the task page uses the desktop layout. It pins the task header and gives only the area below it its own scroll. In a short window that area was too thin: about 100px in my reproduction, 58px in your measurement. The pinned Timeline and Files headings and the log bar covered nearly all of it, so the file row could never be tapped.

Fix.
- New `useShortWorkspace.ts`: it measures how much height the header leaves for the timeline/files area. It counts the collapsed log bar and the pinned headings, and allows about 184px for rows. It also respects the visible area when an on-screen keyboard shrinks it, but ignores pinch zoom. The measurement doesn't depend on which layout is active, so it can't flip back and forth.
- In `TaskDetails/index.tsx`, when there isn't enough room:
  - the whole task scrolls as one page, the way phones already do.
  - the header scrolls away with it, but all its metadata and actions are still there when you scroll back up.
  - the Timeline and Files headings still pin, now to the top of the page.
  - the execution-log bar stays pinned at the bottom, and opening it keeps its normal height.
  - extra scroll padding keeps a focused or revealed row clear of the pinned headings and the log bar.
- Unchanged: tall desktop windows, portrait phones, how the timeline heading sits above its content, and returning focus to the file row when the diff closes. The diff dialog's existing scroll lock still holds the page in place.

Tests. The new `e2e/task-details-short-viewport.pw.ts` covers 844×390 touch landscape, 880×480 desktop, 320×640 and 390×844 portrait, and 1280×820 desktop. Each uses a completed PR task with a long two-line title and subtitle, 8 runs and one modified 121-line Markdown file. It:
- scrolls only with real touch swipes or wheel input.
- checks that a tap at the row's centre actually reaches the row and that the visible area is usable.
- opens and closes the diff, then checks focus and scroll position are restored.
- opens and closes the execution log.
- scrolls back up and opens the header's "More task actions" menu.

On the old code the two short cases fail the way the issue describes: at 844×390 the row can't be scrolled to a tappable spot, and at 880×480 only 51px of the area is visible.

One existing test changed behaviour. In `task-timeline-heading-layering.pw.ts`, the case that docks the task beside the list at 1280×820 with 150% text now uses the new page-scroll layout. There, the enlarged header is 423px tall and leaves only about 97px for rows, the same problem as the issue. The test now scrolls the whole page and still checks that nothing paints over the Timeline heading.

Results. All 270 tests in the `task-*` browser suites pass, as do 424 TaskDetails unit tests, eslint with zero warnings and tsc. The new spec passed 3 times in a row. I didn't touch any files from #3273, #3274 or #3275, and added no dependencies.

The 844×390 and 880×480 previews show the revealed file row and the opened diff. Separately, Gmail, Google Calendar and Google Drive need authorizing in your claude.ai connector settings before they can be used. This task didn't need them.
@integry

integry commented Oct 19, 2026

Copy link
Copy Markdown
Owner

/review gpt-6-astra

@propr-dev

propr-dev Bot commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor Author

✅ AI Code Review Complete requested by @integry

Posted 1 review:

View Task Details

@propr-dev

propr-dev Bot commented Oct 19, 2026

Copy link
Copy Markdown
Contributor Author

🔍 AI Code Review — gpt-6-astra

Overall Evaluation

The PR addresses the cramped landscape workspace by making the whole task scroll when the measured space beneath its header is insufficient. The implementation is focused and appears merge-ready within the supplied scope, conditional on pending checks completing successfully.

✅ Adaptive layout — The hook measures the actual header and available viewport height, accommodating wrapping content and enlarged text instead of relying solely on screen width.

✅ Observer cleanup — Resize observers and viewport listeners are removed when the measured elements change or the component unmounts.

✅ Interaction-focused coverage — The new tests exercise touch and wheel scrolling, file-row hit testing, diff opening and closing, focus restoration, and execution-log controls across five viewport configurations.

This was a static review; no commands or tests were run. The issue description contains a truncation notice, so requirements beyond its supplied excerpt could not be assessed.

Merge blockers

No merge blockers.

Suggestions

These are optional follow-ups and are not sent to /fix.

S1: 🟢 Exercise live viewport transitions

The new tests initialize each viewport independently. A follow-up test could resize an already-scrolled task between tall desktop, short landscape, and portrait layouts, checking file reachability and restored scroll ownership. This would strengthen coverage of the observer-driven transitions in useShortWorkspace.ts; the supplied code does not establish a transition defect requiring a merge blocker.

S2: 🟢 Repeat authenticated mobile acceptance

The added browser tests use stubbed task data, while the original report came from authenticated testing with real data. Repeating that original scenario on a mobile browser would provide useful confirmation of header dimensions and touch behavior. This is additional acceptance evidence, not a demonstrated code defect.

Score

The change directly addresses the reported layout problem and includes substantial interaction coverage. No merge-blocking defect was established from the supplied code; the authoritative check summary reports no failures and six pending checks.

Score: 8/10


🤖 Review Details

  • Model: GPT-6 Astra
  • Time: 42s
  • Tokens: 41,686 (41,063 in / 623 out)
  • Cost: $0.33

View Task


💡 Next step: Comment /fix to address every F# merge blocker, /fix all for every pending blocker and suggestion, or name records explicitly, as in /fix F3 S5.
F# and S# IDs increment across review comments and remain permanent, so selectors such as /fix F3 F5 stay unambiguous across cycles. S# suggestions stay optional: they are implemented only when you name them or request /fix all, and they never relax a merge blocker.

Copy and edit to choose records from this review:

/fix S1 S2

🤖 Review by ProPR

@integry

integry commented Oct 19, 2026

Copy link
Copy Markdown
Owner

Independent exact-head validation at ba5e743 found a reproducibility problem in the new short-viewport browser spec. Please refine it through the existing Claude route before merge.

The production UI was built from that exact head with unchanged dependencies. All 424 TaskDetails unit tests passed. In a fresh browser run with PROPR_CAPTURE_PREVIEWS=1 and retries=0, the new 844x390 landscape case failed line154 with a 6px scroll difference after closing the diff, and the 1280x820 desktop case failed the same assertion with 4px. The other three new viewport cases and all nine timeline-heading cases passed. The file opener and diff did work in both failing cases.

An operator-only diagnostic copy changed only the scroll-settlement wait from three consecutive stable animation frames to24, retaining the <=1px assertion, normal trusted touch/wheel input, and unchanged product source. Both previously failing cases then passed: landscape scrollTop was673 before capture,673 after capture and673 after close; desktop73/73/73. This points to the pre-interaction momentum/settlement measurement rather than an established layout defect. An independent rotation probe also initially missed its first tap while using a short100ms post-swipe wait; that probe is being measured separately.

Please make the committed test reliably observe the end of touch/wheel momentum and measure the baseline at the actual pre-open position. Retain the strict scroll/focus/hit-test assertions and real input; do not loosen the1px limit, force clicks, or assign scrollTop. If investigation establishes a product restoration defect, fix that instead and explain the evidence. Repeat the five viewport cases with and without preview capture and preserve the timeline-heading coverage. No unrelated changes or permission/configuration work. Final authenticated signed-native integration remains an operator release gate.

@propr-dev

propr-dev Bot commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor Author

✅ Applied the requested follow-up changes in commit 7129482

Summary of Changes

Your exact-head failures didn't reproduce in this container, but while ruling out a product cause I found and fixed a real restoration defect in the short layout. That defect plausibly explains the 6px landscape failure. The 1280×820 failure is still unconfirmed: my best explanation is that the wheel scroll hadn't finished when the baseline was measured, and the new wait now covers that.

Product defect. In the short layout, the bottom scroll padding was scroll-pb-12 (48px), but the pinned log bar is 37px (36px plus a 1px top border). When a file row sat fully visible within about 12px above the bar, putting focus back on it as the diff closed counted it as covered and scrolled the page. A diagnostic run placed the row at fixed distances from each edge, then opened and closed the diff:

Row's gap above log bar 0px 2px 5px 10px 20px+
Scroll movement, 844×390 and 880×480 11px 9px 6px 1px 0

The top edge and every position at 1280×820 moved 0px. I set the padding in useShortWorkspace.ts to exactly the bar's height (scroll-pb-[calc(2.25rem+1px)]). After that change, every position moved 0px in all three sizes. The 1280×820 layout has no such padding, so its 4px isn't explained by this defect.

Test changes (e2e/task-details-short-viewport.pw.ts):

  • Waiting for the scroll to end: the old check was three animation frames without movement. It now waits for the scroll's scrollend event and then 300ms with nothing moving. If scrollend never fires, it falls back to 5s.
  • Baseline position: it is now measured where the row rests just before it is tapped: after the swipe's momentum, after the preview capture, with a fresh tap point.
  • New check in the 880×480 case: the mouse wheel moves the row to 1–6px above the log bar, then the diff is opened and closed. With the old padding this fails with an 8px difference; with the fix it passes.
  • Timing: I removed a duplicate wait inside the scroll-into-view step and gave these five cases a 60s timeout. Each case does many swipes and each now waits for its momentum to end, so landscape takes about 14s on an idle host and 30–32s under full CPU load, which is over the default 30s.
  • The 1px limit, the focus and tap-target checks, and real touch/wheel input are unchanged. There are no forced clicks, and the test never sets the scroll position itself.

Results:

  • Repeat runs: the five viewport cases plus the nine timeline-heading cases passed three times with preview capture and three times without, 84/84.
  • Under full CPU load: the five viewport cases passed once with capture and once without.
  • Unit tests, lint and type check: all 424 TaskDetails unit tests pass, and eslint (zero warnings) and tsc are clean.
  • One failure along the way: before the 60s timeout, an overloaded run timed out in the landscape case and in the unchanged timeline-heading enlarged-text case.

Limits:

  • Old wait never failed here. It never returned before the scroll ended in this container: not with the CPU slowed, not under load, not with smooth-scrolling Chromium. The 1280×820 explanation therefore comes from your 24-frame result, not from a failure I reproduced.
  • Edge diagnostic was not real input. It set the scroll position directly, and it is not committed.
  • Remaining gates: a real phone, real API data, and signed-native integration are still your release gates.

There are no visual previews because the change isn't visible in a still image. Separately, Gmail, Google Calendar and Google Drive need authorizing in your claude.ai connector settings before they can be used; this task didn't need them.


🤖 Implementation Details

  • Model: Claude Opus 5.5 (medium)
  • Requested By: @integry
  • Time: 58m 1s
  • Tokens: 2,831,818 (2,802,241 in / 29,577 out)
  • Cost: $1.56
  • Subscription usage: Session +2%, Weekly +1%

Undo Changes • View Task Execution


💡 ProPR Slash Commands
Command Description Example
/merge Merge target branch into this PR and resolve conflicts /merge
/review Request an AI code review /review or /review claude-sonnet
/fix Address review blockers, or blockers and suggestions with /fix all /fix, /fix all, or /fix F3 S5
/switch Change the AI model for this PR /switch claude-opus
/use Override the model for a single follow-up run /use claude-sonnet
/ultrafix Loop review→fix cycles until score goal is met /ultrafix or /ultrafix goal=8 max=10

🤖 Generated by ProPR
Processing comment ID: 6279336708✓

…, but while ruling out a product cause I found and fixed a real restoration defect in the short layout. That defect plausibly explains the 6px landscape failure. The 1280×820 failure is still unconfirmed: my best explanation is that the wheel scroll hadn't finished when the baseline was measured, and the new wait now covers that.

Your exact-head failures didn't reproduce in this container, but while ruling out a product cause I found and fixed a real restoration defect in the short layout. That defect plausibly explains the 6px landscape failure. The 1280×820 failure is still unconfirmed: my best explanation is that the wheel scroll hadn't finished when the baseline was measured, and the new wait now covers that.

**Product defect.** In the short layout, the bottom scroll padding was `scroll-pb-12` (48px), but the pinned log bar is 37px (36px plus a 1px top border). When a file row sat fully visible within about 12px above the bar, putting focus back on it as the diff closed counted it as covered and scrolled the page. A diagnostic run placed the row at fixed distances from each edge, then opened and closed the diff:

| Row's gap above log bar | 0px | 2px | 5px | 10px | 20px+ |
|---|---|---|---|---|---|
| Scroll movement, 844×390 and 880×480 | 11px | 9px | 6px | 1px | 0 |

The top edge and every position at 1280×820 moved 0px. I set the padding in `useShortWorkspace.ts` to exactly the bar's height (`scroll-pb-[calc(2.25rem+1px)]`). After that change, every position moved 0px in all three sizes. The 1280×820 layout has no such padding, so its 4px isn't explained by this defect.

**Test changes** (`e2e/task-details-short-viewport.pw.ts`):
- **Waiting for the scroll to end:** the old check was three animation frames without movement. It now waits for the scroll's `scrollend` event and then 300ms with nothing moving. If `scrollend` never fires, it falls back to 5s.
- **Baseline position:** it is now measured where the row rests just before it is tapped: after the swipe's momentum, after the preview capture, with a fresh tap point.
- **New check in the 880×480 case:** the mouse wheel moves the row to 1–6px above the log bar, then the diff is opened and closed. With the old padding this fails with an 8px difference; with the fix it passes.
- **Timing:** I removed a duplicate wait inside the scroll-into-view step and gave these five cases a 60s timeout. Each case does many swipes and each now waits for its momentum to end, so landscape takes about 14s on an idle host and 30–32s under full CPU load, which is over the default 30s.
- The 1px limit, the focus and tap-target checks, and real touch/wheel input are unchanged. There are no forced clicks, and the test never sets the scroll position itself.

**Results:**
- **Repeat runs:** the five viewport cases plus the nine timeline-heading cases passed three times with preview capture and three times without, 84/84.
- **Under full CPU load:** the five viewport cases passed once with capture and once without.
- **Unit tests, lint and type check:** all 424 TaskDetails unit tests pass, and eslint (zero warnings) and tsc are clean.
- **One failure along the way:** before the 60s timeout, an overloaded run timed out in the landscape case and in the unchanged timeline-heading enlarged-text case.

**Limits:**
- **Old wait never failed here.** It never returned before the scroll ended in this container: not with the CPU slowed, not under load, not with smooth-scrolling Chromium. The 1280×820 explanation therefore comes from your 24-frame result, not from a failure I reproduced.
- **Edge diagnostic was not real input.** It set the scroll position directly, and it is not committed.
- **Remaining gates:** a real phone, real API data, and signed-native integration are still your release gates.

There are no visual previews because the change isn't visible in a still image. Separately, Gmail, Google Calendar and Google Drive need authorizing in your claude.ai connector settings before they can be used; this task didn't need them.

PR: #3277
Comment by: @integry (ID: 6279336708)
Model: Claude Opus 5.5
@integry

integry commented Oct 20, 2026

Copy link
Copy Markdown
Owner

/review gpt-6-astra

@propr-dev

propr-dev Bot commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor Author

✅ AI Code Review Complete requested by @integry

Posted 1 review:

View Task Details

@propr-dev

propr-dev Bot commented Oct 20, 2026

Copy link
Copy Markdown
Contributor Author

🔍 AI Code Review — gpt-6-astra

Overall Evaluation

The PR addresses cramped task workspaces by allowing the header to scroll away while retaining access to the execution log. The changes are focused and appear merge-ready within the supplied review scope, conditional on pending checks and the stated operator release gate.

✅ Adaptive layout — The hook measures available space and header height, observes resizing, and leaves the existing phone layout intact.

✅ Strict interaction checks — The revised browser test measures the baseline after settlement and preview capture, preserving real input, focus restoration, hit testing, and the ≤1px scroll assertion.

✅ Layering coverage preserved — The existing enlarged-text test follows the new scroll owner while retaining its heading coverage checks.

This was a static review; no commands or tests were run. The original issue excerpt is explicitly truncated, so requirements beyond the visible excerpt could not be assessed. Current checks report no failures and six pending checks.

Merge blockers

No merge blockers.

Suggestions

These are optional follow-ups and are not sent to /fix.

S3: 🟢 Exercise live viewport transitions

Consider extending propr-ui/e2e/task-details-short-viewport.pw.ts with portrait-to-landscape and short-to-tall transitions on an already scrolled task. The five cases currently create fresh contexts, whereas the hook also changes scroll ownership during resizing. This would strengthen transition coverage; the supplied code does not establish a transition defect requiring correction.

Score

The implementation is focused, and the follow-up retains strict assertions while improving settlement and baseline measurement. No merge blocker was established from the supplied code; runtime confirmation remains subject to pending checks and the operator integration gate.

Score: 8/10


🤖 Review Details

  • Model: GPT-6 Astra
  • Time: 22s
  • Tokens: 44,453 (43,879 in / 574 out)
  • Cost: $0.36

View Task


💡 Next step: Comment /fix to address every F# merge blocker, /fix all for every pending blocker and suggestion, or name records explicitly, as in /fix F3 S5.
F# and S# IDs increment across review comments and remain permanent, so selectors such as /fix F3 F5 stay unambiguous across cycles. S# suggestions stay optional: they are implemented only when you name them or request /fix all, and they never relax a merge blocker.

Copy and edit to choose records from this review:

/fix S3

🤖 Review by ProPR

@propr-dev

propr-dev Bot commented Oct 20, 2026

Copy link
Copy Markdown
Contributor Author

CI failed: Validate Changes

Please investigate and fix this CI failure.

Failure evidence

.github:1144
Process completed with exit code 1.

propr-ui/e2e/dialog-keyboard-viewport.pw.ts:219 — e2e/dialog-keyboard-viewport.pw.ts:86:56 › Logs keeps its close
3) e2e/dialog-keyboard-viewport.pw.ts:86:56 › Logs keeps its close, search and match controls above the keyboard and restores after it closes (web fonts blocked)

Retry #1 ───────────────────────────────────────────────────────────────────────────────────────
Error: expect(received).toBe(expected) // Object.is equality

Expected: 0
Received: 1

  217 |   await expect(dialog).toHaveCount(0);
  218 |   await expect(opener).toBeFocused();
> 219 |   expect(await listenerCount(page)).toBe(idle);
      |                                     ^
  220 |
  221 |   // Reopened with the keyboard band still offset: placed from the current viewport.
  222 |   await setKeyboard(page, logsBand);
    at /home/runner/work/propr/propr/propr-ui/e2e/dialog-keyboard-viewport.pw.ts:219:37

propr-ui/e2e/dialog-keyboard-viewport.pw.ts:219 — e2e/dialog-keyboard-viewport.pw.ts:86:56 › Logs keeps its close
3) e2e/dialog-keyboard-viewport.pw.ts:86:56 › Logs keeps its close, search and match controls above the keyboard and restores after it closes (web fonts blocked)
Error: expect(received).toBe(expected) // Object.is equality

Expected: 0
Received: 1

  217 |   await expect(dialog).toHaveCount(0);
  218 |   await expect(opener).toBeFocused();
> 219 |   expect(await listenerCount(page)).toBe(idle);
      |                                     ^
  220 |
  221 |   // Reopened with the keyboard band still offset: placed from the current viewport.
  222 |   await setKeyboard(page, logsBand);
    at /home/runner/work/propr/propr/propr-ui/e2e/dialog-key…

@github-actions

Copy link
Copy Markdown

Checks Failed

Validation failed during setup, tests, CLI packaging, linting, or build checks.

View Logs
Build check diagnostics for run 39345691449, attempt 1
Checkout outcome: success

--- GitHub Actions workflow lint ---
docker.io/rhysd/actionlint@sha256:b1934ee5f1c509618f2508e6eb47ee0d3520686341fec936f3b79331f9315667: Pulling from rhysd/actionlint
589002ba0eae: Pulling fs layer
c09af8888d6a: Pulling fs layer
4ccd7d76ca98: Pulling fs layer
b6b4b7b0e257: Pulling fs layer
b6b4b7b0e257: Waiting
4ccd7d76ca98: Verifying Checksum
4ccd7d76ca98: Download complete
589002ba0eae: Download complete
c09af8888d6a: Verifying Checksum
c09af8888d6a: Download complete
589002ba0eae: Pull complete
c09af8888d6a: Pull complete
b6b4b7b0e257: Verifying Checksum
b6b4b7b0e257: Download complete
4ccd7d76ca98: Pull complete
b6b4b7b0e257: Pull complete
Digest: sha256:b1934ee5f1c509618f2508e6eb47ee0d3520686341fec936f3b79331f9315667
Status: Downloaded newer image for rhysd/actionlint@sha256:b1934ee5f1c509618f2508e6eb47ee0d3520686341fec936f3b79331f9315667
docker.io/rhysd/actionlint@sha256:b1934ee5f1c509618f2508e6eb47ee0d3520686341fec936f3b79331f9315667

--- Release shell script lint ---

--- Toolchain ---
v22.23.3
10.9.9

--- Dependency installation ---
npm warn deprecated inflight@1.0.6: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
npm warn deprecated gar@1.0.4: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.
npm warn deprecated glob@7.2.3: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me

added 1112 packages, and audited 1121 packages in 22s

317 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities

--- CLI release package ---
Verifying propr-cli release package...

> propr@0.9.0 cli:pack
> node packages/cli/scripts/build-publish.mjs


> @propr/shared@0.9.0 build
> tsc


> @propr/local-setup@0.9.0 build
> tsc


> @propr/cli@0.9.0 build
> tsc && node scripts/copy-assets.mjs

copy-assets: copied 9 file(s) into the CLI package.

Staged propr-cli@0.9.0 at /home/runner/work/propr/propr/dist-publish/propr-cli
npm notice
npm notice 📦  propr-cli@0.9.0
npm notice Tarball Contents
npm notice 26.7kB README.md
npm notice 36.3kB dist/agentSkill.js
npm notice 754B dist/api/agentRuntime.js
npm notice 7.1kB dist/api/agents.js
npm notice 2.6kB dist/api/agentTank.js
npm notice 4.0kB dist/api/automations.js
npm notice 11.7kB dist/api/client.js
npm notice 5.0kB dist/api/errors.js
npm notice 1.6kB dist/api/followupHandoffs.js
npm notice 16.6kB dist/api/goals.js
npm notice 6.0kB dist/api/implement.js
npm notice 2.6kB dist/api/index.js
npm notice 1.9kB dist/api/logs.js
npm notice 6.2kB dist/api/plans.js
npm notice 4.2kB dist/api/relay.js
npm notice 12.3kB dist/api/repos.js
npm notice 14.2kB dist/api/settings.js
npm notice 775B dist/api/stats.js
npm notice 1.6kB dist/api/syntheticPools.js
npm notice 1.8kB dist/api/system.js
npm notice 5.9kB dist/api/tasks.js
npm notice 2.9kB dist/api/todos.js
npm notice 86B dist/api/types.js
npm notice 313B dist/api/visualPreviewAuth.js
npm notice 29.7kB dist/assets/env.example.txt
npm notice 5.8kB dist/auth/githubLogin.js
npm notice 19.7kB dist/commands/agentCommands.js
npm notice 4.2kB dist/commands/agentPoolCommands.js
npm notice 4.3kB dist/commands/agentSkillCommands.js
npm notice 29.7kB dist/commands/agentValidation.js
npm notice 27.2kB dist/commands/automationCommands.js
npm notice 70.8kB dist/commands/checkCommands.js
npm notice 8.9kB dist/commands/configCommands.js
npm notice 14.6kB dist/commands/connectCommand.js
npm notice 5.5kB dist/commands/githubAppApi.js
npm notice 27.7kB dist/commands/githubAppCommands.js
npm notice 57.9kB dist/commands/goalCommands.js
npm notice 8.1kB dist/commands/handoffCommands.js
npm notice 2.4kB dist/commands/imageCommands.js
npm notice 8.0kB dist/commands/implementCommands.js
npm notice 1.8kB dist/commands/index.js
npm notice 7.3kB dist/commands/initCommands.js
npm notice 14.1kB dist/commands/initStack.js
npm notice 6.1kB dist/commands/logCommands.js
npm notice 24.9kB dist/commands/planCommands.js
npm notice 8.4kB dist/commands/relayCommands.js
npm notice 38.6kB dist/commands/repoCommands.js
npm notice 2.7kB dist/commands/repoValidate.js
npm notice 7.5kB dist/commands/runtimeCommands.js
npm notice 17.9kB dist/commands/settingCommands.js
npm notice 4.6kB dist/commands/setup/agentHostActions.js
npm notice 123B dist/commands/setup/agents.js
npm notice 4.7kB dist/commands/setup/engine.js
npm notice 51B dist/commands/setup/github.js
npm notice 37.3kB dist/commands/setup/hostActions.js
npm notice 3.2kB dist/commands/setup/imagePlatform.js
npm notice 27.3kB dist/commands/setup/sequential.js
npm notice 51B dist/commands/setup/state.js
npm notice 51B dist/commands/setup/types.js
npm notice 10.7kB dist/commands/setupCommand.js
npm notice 4.4kB dist/commands/stackCommands.js
npm notice 1.4kB dist/commands/startCommand.js
npm notice 3.7kB dist/commands/statsCommands.js
npm notice 13.5kB dist/commands/systemCommands.js
npm notice 3.5kB dist/commands/tankCommands.js
npm notice 46.3kB dist/commands/taskCommands.js
npm notice 29.7kB dist/commands/todoCommands.js
npm notice 31.0kB dist/commands/tunnelCommand.js
npm notice 2.7kB dist/commands/uiDocsCommands.js
npm notice 8.3kB dist/completion.js
npm notice 27.3kB dist/config/ConfigManager.js
npm notice 276B dist/config/index.js
npm notice 989B dist/config/rootKey.js
npm notice 345B dist/config/types.js
npm notice 46.0kB dist/connectIdentity.js
npm notice 25.0kB dist/connectRootAuthority.js
npm notice 32.5kB dist/connectWindowsAuthority.js
npm notice 2.2kB dist/desktopDiscovery.js
npm notice 13.3kB dist/desktopLocalSetup.js
npm notice 17.2kB dist/index.js
npm notice 4.5kB dist/native/darwin-authority-broker.c
npm notice 8.9kB dist/native/directory-operations.c
npm notice 50.1kB dist/native/prebuilds/darwin-arm64/connect-authority-broker
npm notice 54.2kB dist/native/prebuilds/darwin-arm64/directory-operations.node
npm notice 17.1kB dist/native/prebuilds/darwin-x64/connect-authority-broker
npm notice 24.3kB dist/native/prebuilds/darwin-x64/directory-operations.node
npm notice 28.9kB dist/native/prebuilds/linux-arm64/directory-operations.node
npm notice 17.4kB dist/native/prebuilds/linux-x64/directory-operations.node
npm notice 1.2kB dist/native/README.md
npm notice 3.1kB dist/orchestrator/format.js
npm notice 13.4kB dist/orchestrator/index.js
npm notice 302B dist/orchestrator/manifest.json
npm notice 123.7kB dist/orchestrator/orchestrator.mjs
npm notice 408B dist/orchestrator/types.js
npm notice 237B dist/skill/propr/agents/openai.yaml
npm notice 8.7kB dist/skill/propr/SKILL.md
npm notice 4.5kB dist/tui/AgentTableApp.js
npm notice 4.5kB dist/tui/app.js
npm notice 11.6kB dist/tui/CheckApp.js
npm notice 5.1kB dist/tui/render.js
npm notice 32.5kB dist/tui/SetupApp.js
npm notice 18.4kB dist/tui/SetupApp.test.js
npm notice 8.2kB dist/tui/StartApp.js
npm notice 3.6kB dist/utils/apiErrorPresentation.js
npm notice 12.0kB dist/utils/directoryDescriptor.js
npm notice 739B dist/utils/dockerPort.js
npm notice 5.0kB dist/utils/envFile.js
npm notice 520B dist/utils/index.js
npm notice 5.7kB dist/utils/io.js
npm notice 717B dist/utils/localSetupPlatform.js
npm notice 1.5kB dist/utils/nativeArtifact.js
npm notice 544B dist/utils/parseState.js
npm notice 417B dist/utils/positiveInteger.js
npm notice 4.5kB dist/utils/privateFilesystem.js
npm notice 4.2kB dist/utils/resolveProject.js
npm notice 7.2kB dist/vendor/local-setup/agents.js
npm notice 64.5kB dist/vendor/local-setup/engine.js
npm notice 5.0kB dist/vendor/local-setup/envFile.js
npm notice 11.4kB dist/vendor/local-setup/github.js
npm notice 188B dist/vendor/local-setup/index.js
npm notice 27.5kB dist/vendor/local-setup/publicInstanceIdentity.js
npm notice 14.6kB dist/vendor/local-setup/state.js
npm notice 2.8kB dist/vendor/local-setup/types.js
npm notice 1.0kB dist/vendor/shared/accountStatusTimestamp.js
npm notice 7.6kB dist/vendor/shared/activityEvents.js
npm notice 2.8kB dist/vendor/shared/agentConfigRedaction.js
npm notice 4.4kB dist/vendor/shared/agentDefinitions.js
npm notice 3.4kB dist/vendor/shared/agentLogin.js
npm notice 3.1kB dist/vendor/shared/agentTank.js
npm notice 2.8kB dist/vendor/shared/analyticsTimeframe.js
npm notice 2.6kB dist/vendor/shared/antigravityCompatibility.js
npm notice 5.1kB dist/vendor/shared/apiOrigin.js
npm notice 3.5kB dist/vendor/shared/assignment.js
npm notice 9.2kB dist/vendor/shared/automationDefinitions.js
npm notice 8.5kB dist/vendor/shared/connectDiscovery.js
npm notice 9.6kB dist/vendor/shared/cronSchedule.js
npm notice 254B dist/vendor/shared/demoMode.js
npm notice 4.3kB dist/vendor/shared/desktopPairing.js
npm notice 481B dist/vendor/shared/desktopTokenRevocation.js
npm notice 8.9kB dist/vendor/shared/events.js
npm notice 3.1kB dist/vendor/shared/extensionProfiles.js
npm notice 2.7kB dist/vendor/shared/fleetData.js
npm notice 2.5kB dist/vendor/shared/githubAppManifest.js
npm notice 1.6kB dist/vendor/shared/githubAuthMode.js
npm notice 2.0kB dist/vendor/shared/githubEventIntakeMode.js
npm notice 11.6kB dist/vendor/shared/goalBlockers.js
npm notice 6.0kB dist/vendor/shared/goalCheckpoints.js
npm notice 4.0kB dist/vendor/shared/goalCreation.js
npm notice 4.9kB dist/vendor/shared/goalWait.js
npm notice 12.7kB dist/vendor/shared/index.js
npm notice 214B dist/vendor/shared/instanceAuthorization.js
npm notice 54B dist/vendor/shared/instanceCatalog.js
npm notice 584B dist/vendor/shared/instanceStorage.js
npm notice 4.0kB dist/vendor/shared/intakeModePrerequisites.js
npm notice 2.9kB dist/vendor/shared/labelUtils.js
npm notice 17.0kB dist/vendor/shared/modelDefinitions.js
npm notice 3.5kB dist/vendor/shared/notificationLinks.js
npm notice 51.3kB dist/vendor/shared/notifications.js
npm notice 7.5kB dist/vendor/shared/previewStorage/v1.js
npm notice 866B dist/vendor/shared/projectSlug.js
npm notice 3.8kB dist/vendor/shared/proprCompatibility.js
npm notice 13.0kB dist/vendor/shared/proprServiceUrls.js
npm notice 16.6kB dist/vendor/shared/prTemplate.js
npm notice 2.2kB dist/vendor/shared/publishedVisualPreviews.js
npm notice 2.5kB dist/vendor/shared/reasoningLevels.js
npm notice 1.2kB dist/vendor/shared/repositoryIcon.js
npm notice 1.4kB dist/vendor/shared/repositoryIconUrl.js
npm notice 3.9kB dist/vendor/shared/repositoryPresentation.js
npm notice 9.5kB dist/vendor/shared/reviewContextBudget.js
npm notice 5.8kB dist/vendor/shared/reviewFeedbackIds.js
npm notice 1.7kB dist/vendor/shared/reviewPrompt.js
npm notice 907B dist/vendor/shared/runCostCap.js
npm notice 861B dist/vendor/shared/sessionSecret.js
npm notice 603B dist/vendor/shared/statusKeys.js
npm notice 7.5kB dist/vendor/shared/syntheticAgents.js
npm notice 2.2kB dist/vendor/shared/taskIdentifiers.js
npm notice 1.8kB dist/vendor/shared/taskLifecycle.js
npm notice 733B dist/vendor/shared/taskReplacement.js
npm notice 957B dist/vendor/shared/text.js
npm notice 9.8kB dist/vendor/shared/usageTips.catalog.json
npm notice 5.0kB dist/vendor/shared/usageTips.js
npm notice 335B dist/vendor/shared/usageTypes.js
npm notice 1.1kB dist/vendor/shared/userWhitelist.js
npm notice 758B dist/vendor/shared/validateRelayUrl.js
npm notice 2.2kB dist/vendor/shared/validateRoutingUrl.js
npm notice 7.1kB dist/vendor/shared/visualPreviewCapacity.js
npm notice 9.3kB dist/vendor/shared/voice.js
npm notice 222B dist/vendor/shared/workEvidence.js
npm notice 675B package.json
npm notice Tarball Details
npm notice name: propr-cli
npm notice version: 0.9.0
npm notice filename: propr-cli-0.9.0.tgz
npm notice package size: 477.3 kB
npm notice unpacked size: 2.0 MB
npm notice shasum: 5fffec213a443d4b6071d7898d30e7df0f08bb65
npm notice integrity: sha512-BOyJGfMsZYzoQ[...]U4eelqZ9Ue/Bw==
npm notice total files: 189
npm notice
propr-cli-0.9.0.tgz

Dry run only. Re-run with --publish to publish to npm.
✅ propr-cli release package verified

--- Stage outcomes ---
Workflow lint: success
Release shell lint: success
Pre-setup gate: skipped
Node setup: success
Toolchain: success
Dependency install: success
Release metadata: success
CLI packaging: success
Change detection: success
Changed-area checks: skipped

View Workflow

@propr-dev

propr-dev Bot commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor Author

✅ Applied the requested follow-up changes in commit 2eae2f8

Processed 2 comments:

  • Comment 1 by @propr-dev[bot] (ID: 6280778125✓)
  • Comment 2 by @github-actions[bot] (ID: 6280778384✓)

Summary of Changes

I fixed the Validate Changes failure. The cause was a race in this PR, not the logs dialog: the listener-leak check in e2e/dialog-keyboard-viewport.pw.ts measured its baseline before the task page had finished loading.

What went wrong. The new useShortWorkspace hook adds a resize listener on the browser's visual viewport once the task header mounts. The test records the starting (idle) listener count right after page.goto, before the task data has loaded. So that count is 0, and after the dialog closes the count is 1, the hook's listener for the page itself. The dialogs weren't leaking anything. Locally, this failed every time in the Follow Up test and in both Logs tests (fonts loaded and blocked), not only the one CI reported.

Fix (tests only, no product code changed):

  • e2e/task-logs.fixture.ts: a new taskShown(page) helper waits until the task page has rendered. It reuses the "more actions" button lookup that openTaskAction already uses.
  • e2e/dialog-keyboard-viewport.pw.ts: the Follow Up and Logs tests now call taskShown(page) before measuring idle. The baseline therefore includes the task page's own listeners. The check still fails if a dialog leaves a listener behind.

Verification:

  • dialog-keyboard-viewport, task-logs-* and task-details-short-viewport pass, each run twice with retries off (46 passed, 0 failed). Before the fix, dialog-keyboard-viewport failed 9 of 15 runs.
  • ESLint (--max-warnings 0) and tsc --noEmit pass on the changed files.

This change isn't visible in the UI, so there are no previews.


🤖 Implementation Details

  • Model: Claude Opus 5.5 (medium)
  • Requested By: @propr-dev[bot], @github-actions[bot]
  • Time: 9m 37s
  • Tokens: 607,587 (602,550 in / 5,037 out)
  • Cost: $0.46
  • Subscription usage: Session +4%, Fable +1%

Undo Changes • View Task Execution


💡 ProPR Slash Commands
Command Description Example
/merge Merge target branch into this PR and resolve conflicts /merge
/review Request an AI code review /review or /review claude-sonnet
/fix Address review blockers, or blockers and suggestions with /fix all /fix, /fix all, or /fix F3 S5
/switch Change the AI model for this PR /switch claude-opus
/use Override the model for a single follow-up run /use claude-sonnet
/ultrafix Loop review→fix cycles until score goal is met /ultrafix or /ultrafix goal=8 max=10

🤖 Generated by ProPR
Processing comment IDs: 6280778125✓, 6280778384✓

…in this PR, not the logs dialog: the listener-leak check in `e2e/dialog-keyboard-viewport.pw.ts` measured its baseline before the task page had finished loading.

I fixed the Validate Changes failure. The cause was a race in this PR, not the logs dialog: the listener-leak check in `e2e/dialog-keyboard-viewport.pw.ts` measured its baseline before the task page had finished loading.

**What went wrong.** The new `useShortWorkspace` hook adds a resize listener on the browser's visual viewport once the task header mounts. The test records the starting (`idle`) listener count right after `page.goto`, before the task data has loaded. So that count is 0, and after the dialog closes the count is 1, the hook's listener for the page itself. The dialogs weren't leaking anything. Locally, this failed every time in the Follow Up test and in both Logs tests (fonts loaded and blocked), not only the one CI reported.

**Fix (tests only, no product code changed):**
- `e2e/task-logs.fixture.ts`: a new `taskShown(page)` helper waits until the task page has rendered. It reuses the "more actions" button lookup that `openTaskAction` already uses.
- `e2e/dialog-keyboard-viewport.pw.ts`: the Follow Up and Logs tests now call `taskShown(page)` before measuring `idle`. The baseline therefore includes the task page's own listeners. The check still fails if a dialog leaves a listener behind.

**Verification:**
- `dialog-keyboard-viewport`, `task-logs-*` and `task-details-short-viewport` pass, each run twice with retries off (46 passed, 0 failed). Before the fix, `dialog-keyboard-viewport` failed 9 of 15 runs.
- ESLint (`--max-warnings 0`) and `tsc --noEmit` pass on the changed files.

This change isn't visible in the UI, so there are no previews.

PR: #3277
Comment by: @propr-dev[bot] (ID: 6280778125)
Comment by: @github-actions[bot] (ID: 6280778384)
Model: Claude Opus 5.5
@integry

integry commented Oct 20, 2026

Copy link
Copy Markdown
Owner

/review gpt-6-astra

@propr-dev

propr-dev Bot commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor Author

✅ AI Code Review Complete requested by @integry

Posted 1 review:

View Task Details

@propr-dev

propr-dev Bot commented Oct 20, 2026

Copy link
Copy Markdown
Contributor Author

🔍 AI Code Review — gpt-6-astra

Overall Evaluation

The PR addresses short viewports by letting the task header scroll away and giving the workspace its content height. The changes are focused and appear merge-ready within the reviewed scope, conditional on pending checks completing successfully.

✅ Adaptive layout — The hook measures available space and header height, preserves the existing phone layout, and cleans up its observers and listeners.

✅ Strict interaction coverage — The browser tests retain real touch/wheel input, hit testing, focus restoration, and the ≤1px scroll-restoration assertion. The baseline is now measured after settlement and preview capture.

This was a static review; no commands or tests were run. The supplied original issue is truncated, so unseen acceptance criteria could not be assessed. Current checks report no failures and six pending checks; authenticated signed-native integration remains the stated operator release gate.

Merge blockers

No merge blockers.

Suggestions

These are optional follow-ups and are not sent to /fix.

S4: 🟢 Cover live layout transitions

Consider testing portrait-to-landscape rotation and short-to-tall resizing while a file row is visible. The new cases validate initial viewport layouts, while useShortWorkspace also switches scroll ownership during resizing. Transition coverage would help detect position or reachability regressions; no concrete transition defect was established here, so this is optional.

Score

The implementation is focused, and the revised tests address the reported settlement problem without weakening assertions. Static review found no demonstrated blocker; runtime results and the remaining checks still need confirmation.

Score: 8/10


🤖 Review Details

  • Model: GPT-6 Astra
  • Time: 23s
  • Tokens: 53,855 (53,355 in / 500 out)
  • Cost: $0.45

View Task


💡 Next step: Comment /fix to address every F# merge blocker, /fix all for every pending blocker and suggestion, or name records explicitly, as in /fix F3 S5.
F# and S# IDs increment across review comments and remain permanent, so selectors such as /fix F3 F5 stay unambiguous across cycles. S# suggestions stay optional: they are implemented only when you name them or request /fix all, and they never relax a merge blocker.

Copy and edit to choose records from this review:

/fix S4

🤖 Review by ProPR

@integry
integry merged commit e7ca1a8 into main Oct 20, 2026
42 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Short landscape task viewport leaves changed files covered and untappable

1 participant