@clipboard-health/ai-rules 2.41.0 → 2.41.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/scripts/toErrorMessage.js +1 -1
- package/skills/cb-ship/SKILL.md +14 -1
- package/skills/flaky-critic/SKILL.md +41 -2
- package/skills/flaky-critic/references/backtests/2026-07-16-b8-prior-attempts/answer-key.json +242 -0
- package/skills/flaky-critic/references/backtests/2026-07-16-b8-prior-attempts/cohort.md +37 -0
- package/skills/flaky-critic/references/backtests/2026-07-16-b8-prior-attempts/input-hashes.txt +20 -0
- package/skills/flaky-critic/references/backtests/2026-07-16-b8-prior-attempts/inputs/case-01.md +141 -0
- package/skills/flaky-critic/references/backtests/2026-07-16-b8-prior-attempts/inputs/case-02.md +115 -0
- package/skills/flaky-critic/references/backtests/2026-07-16-b8-prior-attempts/inputs/case-03.md +24 -0
- package/skills/flaky-critic/references/backtests/2026-07-16-b8-prior-attempts/inputs/case-04.md +85 -0
- package/skills/flaky-critic/references/backtests/2026-07-16-b8-prior-attempts/inputs/case-05.md +78 -0
- package/skills/flaky-critic/references/backtests/2026-07-16-b8-prior-attempts/inputs/case-06.md +82 -0
- package/skills/flaky-critic/references/backtests/2026-07-16-b8-prior-attempts/inputs/case-07.md +128 -0
- package/skills/flaky-critic/references/backtests/2026-07-16-b8-prior-attempts/inputs/case-08.md +99 -0
- package/skills/flaky-critic/references/backtests/2026-07-16-b8-prior-attempts/inputs/case-09.md +107 -0
- package/skills/flaky-critic/references/backtests/2026-07-16-b8-prior-attempts/inputs/case-10.md +141 -0
- package/skills/flaky-critic/references/backtests/2026-07-16-b8-prior-attempts/inputs/case-11.md +98 -0
- package/skills/flaky-critic/references/backtests/2026-07-16-b8-prior-attempts/inputs/case-12.md +99 -0
- package/skills/flaky-critic/references/backtests/2026-07-16-b8-prior-attempts/inputs/case-13.md +25 -0
- package/skills/flaky-critic/references/backtests/2026-07-16-b8-prior-attempts/inputs/case-14.md +111 -0
- package/skills/flaky-critic/references/backtests/2026-07-16-b8-prior-attempts/inputs/case-15.md +27 -0
- package/skills/flaky-critic/references/backtests/2026-07-16-b8-prior-attempts/inputs/case-16.md +46 -0
- package/skills/flaky-critic/references/backtests/2026-07-16-b8-prior-attempts/inputs/case-17.md +101 -0
- package/skills/flaky-critic/references/backtests/2026-07-16-b8-prior-attempts/inputs/case-18.md +88 -0
- package/skills/flaky-critic/references/backtests/2026-07-16-b8-prior-attempts/inputs/case-19.md +98 -0
- package/skills/flaky-critic/references/backtests/2026-07-16-b8-prior-attempts/inputs/case-20.md +91 -0
- package/skills/flaky-critic/references/backtests/2026-07-16-b8-prior-attempts/verdicts.jsonl +20 -0
- package/skills/flaky-critic/references/backtests/2026-07-16-b8-prior-attempts.md +170 -0
- package/skills/flaky-critic/references/rubric.md +17 -2
package/skills/flaky-critic/references/backtests/2026-07-16-b8-prior-attempts/inputs/case-08.md
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# Historical plan snapshot
|
|
2
|
+
|
|
3
|
+
## Groundcrew
|
|
4
|
+
|
|
5
|
+
Repository: `[admin frontend]`
|
|
6
|
+
Implementation workflow: use the `cb-work` skill. If unavailable, use the `core:go` skill.
|
|
7
|
+
|
|
8
|
+
Include this implementation ticket ID in the change body.
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Source Investigation
|
|
15
|
+
|
|
16
|
+
Investigation ticket: [ticket redacted]
|
|
17
|
+
Skill/mode: `flaky-debug` in plan mode. The requested `flaky-test-debugger` skill was not installed under that exact name, so this used the available Clipboard flaky-debug skill.
|
|
18
|
+
|
|
19
|
+
## Flake Details
|
|
20
|
+
|
|
21
|
+
```json
|
|
22
|
+
{
|
|
23
|
+
"repo": "[admin frontend]",
|
|
24
|
+
"test": "Home Health Full Lifecycle complete home health workflow: create case, manage visits, verify and reject occurrences, close case",
|
|
25
|
+
"file": "playwright/e2e/homeHealth/fullLifecycle.spec.ts:1170",
|
|
26
|
+
"framework": "playwright",
|
|
27
|
+
"isNewFlaky": false,
|
|
28
|
+
"failures": [
|
|
29
|
+
{
|
|
30
|
+
"error": "TimeoutError: locator.click: Timeout 5000ms exceeded.\nCall log:\n - waiting for getByRole('dialog').filter({ hasText: 'Are you sure you want to close this case?' }).getByRole('button', { name: 'Close', exact: true })\n - locator canonical to <button tabindex=\"0\" type=\"button\" class=\"MuiButtonBase-root MuiButton-root MuiButton-contained MuiButton-containedPrimary MuiButton-sizeMedium MuiButton-containedSizeMedium MuiButton-fullWidth MuiButton-root MuiButton-contained MuiButton-containedPrimary MuiButton-sizeMedium MuiButton-containedSizeMedium MuiButton-fullWidth css-6qhbw3\">…</button>\n - attempting click action\n - waiting for element to be visible, enabled and stable\n - element is not stable\n - retrying click action\n - waiting for element to be visible, enabled and stable\n - element was detached from the DOM, retrying\n",
|
|
31
|
+
"stack": "TimeoutError: locator.click: Timeout 5000ms exceeded.\nCall log:\n - waiting for getByRole('dialog').filter({ hasText: 'Are you sure you want to close this case?' }).getByRole('button', { name: 'Close', exact: true })\n - locator canonical to <button tabindex=\"0\" type=\"button\" class=\"MuiButtonBase-root MuiButton-root MuiButton-contained MuiButton-containedPrimary MuiButton-sizeMedium MuiButton-containedSizeMedium MuiButton-fullWidth MuiButton-root MuiButton-contained MuiButton-containedPrimary MuiButton-sizeMedium MuiButton-containedSizeMedium MuiButton-fullWidth css-6qhbw3\">…</button>\n - attempting click action\n - waiting for element to be visible, enabled and stable\n - element is not stable\n - retrying click action\n - waiting for element to be visible, enabled and stable\n - element was detached from the DOM, retrying\n\n at submitCloseCase (/opt/actions-runner/_work/[admin frontend]/[admin frontend]/playwright/e2e/homeHealth/fullLifecycle.spec.ts:792:17)\n at /opt/actions-runner/_work/[admin frontend]/[admin frontend]/playwright/e2e/homeHealth/fullLifecycle.spec.ts:1782:9\n at /opt/actions-runner/_work/[admin frontend]/[admin frontend]/playwright/e2e/homeHealth/fullLifecycle.spec.ts:1774:7\n at WorkerMain._runTest (/opt/actions-runner/_work/[admin frontend]/[admin frontend]/node_modules/dd-trace/packages/datadog-instrumentations/src/playwright.js:1692:5)",
|
|
32
|
+
"branch": "main",
|
|
33
|
+
"pipeline": "[external evidence reference]",
|
|
34
|
+
"commit": "ae7ad5ee34fd9d833c47c68aec34f8d3e4c03745",
|
|
35
|
+
"durationMs": 56753,
|
|
36
|
+
"shard": "2/4",
|
|
37
|
+
"timestamp": "2026-07-06T17:16:19Z"
|
|
38
|
+
}
|
|
39
|
+
]
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Plan Output
|
|
44
|
+
|
|
45
|
+
**Test ID:** `[bf2e9756e2c0]`
|
|
46
|
+
|
|
47
|
+
**Confidence:** 4/5. The failure artifact directly shows the close dialog button was visible/enabled, the click timed out because the element became unstable/detached, and no close-case PATCH was emitted. The exact reason the dialog disappeared is inferred from UI/test timing, so this is not 5/5.
|
|
48
|
+
|
|
49
|
+
**Failure surface:** User action no-op / test harness. The app reached the confirmation dialog, but the destructive close-case request never started.
|
|
50
|
+
|
|
51
|
+
**Current main status:** The failing code path still exists on current main/worktree in `playwright/e2e/homeHealth/fullLifecycle.spec.ts`: `submitCloseCase` waits for `PATCH /cases/{caseId}` and clicks the `Close` button in a single `Promise.all` at lines 784-792. No open change with label `flaky-test-fix` matched this file. Recent commit `28bdf114626` / [ticket redacted] fixed a different close-case flake where the PATCH succeeded and the helper retried a one-shot mutation; this new failure happens before the PATCH starts.
|
|
52
|
+
|
|
53
|
+
**Symptom:** In Step j, `submitCloseCase` times out on `closeButton.click({ timeout: ATTEMPT_TIMEOUT_MS })`. Playwright reports the button canonical, then was unstable and detached. The paired `waitForHomeHealthResponse` also times out because no matching `PATCH /[home-health service]/api/v1/*/cases/{caseId}` occurs.
|
|
54
|
+
|
|
55
|
+
**Root cause:** `submitCloseCase` treats one transient close-dialog/button remount as terminal. The close dialog is mounted under `CaseActionsMenu` / `CaseClosureDialog`; the failed run shows it can disappear or remount during the click window before the close PATCH starts. The helper lacks the request-observed guard used elsewhere in this spec for visit verification actions, so a pre-request click detach fails the test instead of safely reopening the dialog and trying again.
|
|
56
|
+
|
|
57
|
+
**Evidence:**
|
|
58
|
+
|
|
59
|
+
- LLM report summary: 52 tests total, 49 passed, 1 flaky, 2 skipped. This test failed first attempt and passed retry.
|
|
60
|
+
- Failed timeline around Step j: `Case Actions` clicked at ~49071ms, `Close Case` clicked at ~49113ms, dialog text visible at ~49374ms, `Close` button visible/enabled at ~49391-49394ms, then both `waitForResponse` and `Click ... Close` start at ~49398ms and time out after 5000ms.
|
|
61
|
+
- Failed network activity after the close click contains Datadog/Braze and unrelated `/api/extra-worked-time-requests` and `/api/user/get` requests, but no `PATCH /[home-health service]/api/v1/.../cases/{caseId}`.
|
|
62
|
+
- Failure screenshot shows the dialog is gone, the case is still visible under Active Cases, and the case has not moved to ended Cases.
|
|
63
|
+
- Passed retry follows the same Step j path and completes: click Case Actions, click Close Case, see close dialog, click Close, settle Active Cases, then verify the case under ended Cases.
|
|
64
|
+
- Product code path: `src/appV2/ExperimentalHomeHealth/Cases/CaseDashboard/CaseClosureDialog.tsx` only calls `updateCase` from the `Close` button handler, then closes the modal after success; `useUpdateCase` invalidates open/ended case queries on success.
|
|
65
|
+
|
|
66
|
+
**Proposed fix:** Test harness only, in `playwright/e2e/homeHealth/fullLifecycle.spec.ts`.
|
|
67
|
+
|
|
68
|
+
1. Refactor `submitCloseCase` to mirror the existing request-observed pattern used by `clickVisitOccurrenceActionButtonUntilPatchObserved`.
|
|
69
|
+
2. Start a close-case response result promise with `waitForHomeHealthResponseResult({ action: "close case", isMatchingRequest: (request) => isCaseUpdateRequest(request, caseId), timeout: ACTION_TIMEOUT_MS })` before retrying pre-request UI work.
|
|
70
|
+
3. Add a helper such as `clickCloseCaseButtonUntilPatchObserved({ page, closureDialog, caseId })` that:
|
|
71
|
+
- creates `page.waitForRequest((request) => isCaseUpdateRequest(request, caseId), { timeout: ATTEMPT_TIMEOUT_MS }).then(() => true, () => false)`;
|
|
72
|
+
- locates the Close button fresh from the current dialog;
|
|
73
|
+
- asserts visible/enabled and clicks;
|
|
74
|
+
- if the click throws but the PATCH was observed, returns success;
|
|
75
|
+
- if no PATCH was observed, throws a retryable pre-request error.
|
|
76
|
+
4. Wrap only the pre-mutation open/fill/click path in `expect(...).toPass({ intervals: [500, 1_000, 2_000], timeout: ACTION_TIMEOUT_MS })` so retries are allowed before a close PATCH starts, but the mutation itself is still executed once.
|
|
77
|
+
5. After the helper observes the PATCH, await the response result with `getSuccessfulHomeHealthResponse`, assert `data.attributes.status === CaseStatus.[attempt reference redacted]`, settle the dashboard, and assert the active case card disappears.
|
|
78
|
+
6. Add close-case diagnostics on final failure, similar to `attachCancelVisitDialogOpenDiagnostics`: visible dialog texts, close button count/visible/enabled, case card text, current URL, whether the close PATCH was observed, and a screenshot attachment if useful.
|
|
79
|
+
7. Do not use `force: true`, fixed sleeps, or a longer click timeout as the fix.
|
|
80
|
+
|
|
81
|
+
**Observability to reach 5/5:** Add the close-case test diagnostics above. They would confirm whether the dialog ended from an `onClose`, remounted with a new button, or disappeared because the case card subtree remounted. No backend telemetry is required for this occurrence because the expected backend request never started.
|
|
82
|
+
|
|
83
|
+
**Sibling candidates:** The exact `Promise.all([waitForHomeHealthResponse, closeButton.click])` anti-pattern is localized to close case. Review nearby destructive dialog submits in the same file while implementing: cancel visit confirmations and remove booked worker use a request promise plus direct click; they may not need changes, but should be checked against the same request-observed guard criterion.
|
|
84
|
+
|
|
85
|
+
**Validation plan:**
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
npx oxfmt --check playwright/e2e/homeHealth/fullLifecycle.spec.ts
|
|
89
|
+
npx oxlint playwright/e2e/homeHealth/fullLifecycle.spec.ts
|
|
90
|
+
npm run lint:fast
|
|
91
|
+
npm run typecheck
|
|
92
|
+
npm run playwright:run -- playwright/e2e/homeHealth/fullLifecycle.spec.ts --grep "complete home health workflow"
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
If local Playwright setup requires deployed-env credentials, record the setup blocker and run the smallest available lint/typecheck verification locally.
|
|
96
|
+
|
|
97
|
+
**Open questions:** None for implementation. The fix should not require product-code changes unless new diagnostics show real user-visible close-dialog dismissal without a request.
|
|
98
|
+
|
|
99
|
+
**Residual risk:** The full lifecycle spec has several independently flaky surfaces. This plan only addresses the close-case confirm-button detach before the PATCH starts; later ended-tab verification or unrelated home-health API/setup flakes can still fail separately.
|
package/skills/flaky-critic/references/backtests/2026-07-16-b8-prior-attempts/inputs/case-09.md
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# Historical plan snapshot
|
|
2
|
+
|
|
3
|
+
## Groundcrew
|
|
4
|
+
|
|
5
|
+
Repository: [mobile frontend]
|
|
6
|
+
GitHub repo: [mobile frontend]
|
|
7
|
+
Implementation workflow: use the `cb-work` skill or, if unavailable, the `core:go`/`go` skill.
|
|
8
|
+
|
|
9
|
+
## Task
|
|
10
|
+
|
|
11
|
+
Stabilize the MPR V2 Playwright flow in `playwright/e2e/shift/timekeeping.spec.ts` by making `selectMinuteThatRequiresClockInApproval` avoid low-minute loop-boundary clicks that can settle the wheel into a same-hour future time.
|
|
12
|
+
|
|
13
|
+
Suggested smallest fix: update `getTargetMinuteForClockInApproval` so it avoids both `00` and the `01 -> 00` path. For this flow, a slightly later minute is still earlier than the actual worker clock-in because the shift is already in progress; it only needs to dirty the picker and trigger the approval step. A conservative helper shape is:
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
function getTargetMinuteForClockInApproval(selectedMinute: number): number {
|
|
17
|
+
if (selectedMinute <= 1) {
|
|
18
|
+
return selectedMinute + 1;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return selectedMinute - 1;
|
|
22
|
+
}
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Consider using a slightly wider low-minute guard, for example `selectedMinute <= 5`, if local trace review shows the smooth scroll can settle across several low-minute values. Keep the change test-harness-only unless the implementation investigation proves a real product bug in `WheelTimePicker` click/scroll-end behavior.
|
|
26
|
+
|
|
27
|
+
## Acceptance Criteria
|
|
28
|
+
|
|
29
|
+
- [ ] The MPR V2 E2E helper no longer clicks `0 minutes` when the selected minute is `1`.
|
|
30
|
+
- [ ] The helper still reaches the approval-step UI by waiting for the earlier-clock-in approval copy and enabled `Next` button.
|
|
31
|
+
- [ ] The change body includes this implementation ticket ID.
|
|
32
|
+
- [ ] Targeted formatting/linting and the smallest practical Playwright verification are run or the Playwright environment blocker is documented.
|
|
33
|
+
|
|
34
|
+
## Flake Details
|
|
35
|
+
|
|
36
|
+
```json
|
|
37
|
+
{
|
|
38
|
+
"repo": "[mobile frontend]",
|
|
39
|
+
"test": "Missed punch request should complete MPR V2 flow: already started working, edit clock-in, and submit timesheet",
|
|
40
|
+
"file": "playwright/e2e/shift/timekeeping.spec.ts:920",
|
|
41
|
+
"framework": "playwright",
|
|
42
|
+
"isNewFlaky": false,
|
|
43
|
+
"failures": [
|
|
44
|
+
{
|
|
45
|
+
"error": "Error: Clock-in approval state not reached after clicking 55 minutes; selected minute: 55; Next enabled: false; approval copy: <not visible>\n\nCall Log:\n- Timeout 30000ms exceeded while waiting on the predicate",
|
|
46
|
+
"stack": "Error: Clock-in approval state not reached after clicking 55 minutes; selected minute: 55; Next enabled: false; approval copy: <not visible>\n\nCall Log:\n- Timeout 30000ms exceeded while waiting on the predicate\n at selectMinuteThatRequiresClockInApproval (/home/runner/work/[mobile frontend]/[mobile frontend]/playwright/e2e/shift/timekeeping.spec.ts:147:6)\n at /home/runner/work/[mobile frontend]/[mobile frontend]/playwright/e2e/shift/timekeeping.spec.ts:975:11\n at WorkerMain._runTest (/home/runner/work/[mobile frontend]/[mobile frontend]/node_modules/dd-trace/packages/datadog-instrumentations/src/playwright.js:1692:5)",
|
|
47
|
+
"branch": "gh-readonly-queue/main/change-[reference redacted]-139c9148f92f65dc0d8f2a8f642c56fea71e4e95",
|
|
48
|
+
"pipeline": "[external evidence reference]",
|
|
49
|
+
"commit": "eece17af4aa80924757ee2444f013dadb956d75e",
|
|
50
|
+
"durationMs": [attempt reference redacted],
|
|
51
|
+
"shard": "3/4",
|
|
52
|
+
"timestamp": "2026-06-25T14:06:34Z"
|
|
53
|
+
}
|
|
54
|
+
]
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Plan Output
|
|
59
|
+
|
|
60
|
+
**Test ID:** `a51c4867d1e5326a80d8-240a586ace394c9bb6fb`
|
|
61
|
+
|
|
62
|
+
**Confidence:** 4/5. The LLM report, trace steps, and screenshot directly show the failed UI state. One link is inferred: the report does not expose the wheel column `scrollTop` or scroll-end events, so the exact mechanism that moves from `0` to high-50s minutes is inferred from the step sequence and component behavior.
|
|
63
|
+
|
|
64
|
+
**Failure surface:** User action no-op / test harness. The click actions completed, but the expected approval-state transition did not remain reachable. No relevant backend request was emitted during the failed picker-selection loop.
|
|
65
|
+
|
|
66
|
+
**Current main status:** Still applicable on current `origin/main`/branch head `e12d296a7e8`. No open GitHub change labeled `flaky-test-fix` was found. Recent main commits `893373a2abb` and `ba607976ecd` stabilized this same MPR picker area but do not cover the `selectedMinute === 1 -> click 0` low-minute boundary seen here.
|
|
67
|
+
|
|
68
|
+
**Symptom:** `selectMinuteThatRequiresClockInApproval` timed out at `playwright/e2e/shift/timekeeping.spec.ts:147`. The final diagnostic was: `Clock-in approval state not reached after clicking 55 minutes; selected minute: 55; Next enabled: false; approval copy: <not visible>`.
|
|
69
|
+
|
|
70
|
+
**Root Cause:** The test helper derives each retry target from the currently selected minute and usually subtracts one. When the selected minute is `1`, it clicks `0 minutes`. In this live E2E flow the looped `WheelTimePicker` uses smooth scrolling and scroll-end recentering; after the low-minute boundary click, subsequent retries observed/clicked high minute values (`57`, `56`, `55`, `54`). Those same-hour high-minute selections were in the future relative to browser time, so `useClockInTimeValidation` showed the future-time error, hid the approval copy, and left the footer as disabled `Save` instead of enabled `Next`.
|
|
71
|
+
|
|
72
|
+
**Evidence:**
|
|
73
|
+
|
|
74
|
+
- LLM report summary for run [reference redacted]`: 45 total, 44 passed, 1 flaky; this test failed on attempt 1 and passed on attempt 2.
|
|
75
|
+
- Failed attempt timeline reached `Adjust clock in` at offset `68591ms`, then the helper clicked minute options `0`, `57`, `56`, `55`, and `54` before timing out.
|
|
76
|
+
- Passing retry reached `Adjust clock in` at offset `28654ms`, clicked `2 minutes`, saw the approval copy, found `Next` enabled, and completed the full flow.
|
|
77
|
+
- Failure screenshot shows the adjustment sheet with error copy `This time (7:54 AM) is in the future. Please end your shift before requesting shift payment.`, selected `54` minutes, and a disabled `Save` button.
|
|
78
|
+
- The product validation path in `validateClockInTimestamp` marks selected times after `startOfMinute(new Date())` as `IN_FUTURE`; `TimekeepingAdjustmentBottomSheet` only labels the footer `Next` when `requiresApproval` is stable.
|
|
79
|
+
- Network summary had retained-request caps (`instancesDroppedByGroupCap: 29`, `instancesEvictedAfterAdmission: 14`), but no failed backend request explains the picker transition. The only retained 4xx was an unrelated `worker-payouts/last` 404.
|
|
80
|
+
|
|
81
|
+
**Proposed Fix:** Test harness only, in `playwright/e2e/shift/timekeeping.spec.ts`.
|
|
82
|
+
|
|
83
|
+
Update the minute target helper to avoid low-minute loop-boundary targets. At minimum, handle `selectedMinute <= 1` by clicking a later safe minute, not `0`. This keeps the selected adjusted time earlier than the actual worker clock-in in this scenario while avoiding the looped wheel boundary that can settle into future high-minute values.
|
|
84
|
+
|
|
85
|
+
Optionally improve diagnostics in `getMinuteSelectionDiagnostics` to include the visible footer button text, visible intent/error copy, selected hour/minute/meridiem labels, and browser `new Date().toISOString()` so the next failure is self-contained.
|
|
86
|
+
|
|
87
|
+
**Observability to Reach 5/5:**
|
|
88
|
+
|
|
89
|
+
- Frontend/test reporter: include selected hour/minute/meridiem, all visible intent/error banner text, visible footer button names, and browser current time in the helper failure message.
|
|
90
|
+
- If the low-minute fix does not settle the flake, add temporary Playwright trace diagnostics for the minutes listbox `scrollTop` and selected option before/after each click to prove whether `WheelColumn` scroll-end recentering is overriding `onSelect`.
|
|
91
|
+
- Backend telemetry is not required for this failure unless a future occurrence emits `validate_timekeeping_action` during the failed transition.
|
|
92
|
+
|
|
93
|
+
**Sibling Candidates:**
|
|
94
|
+
|
|
95
|
+
- Primary: `playwright/e2e/shift/timekeeping.spec.ts` helper `getTargetMinuteForClockInApproval` / `selectMinuteThatRequiresClockInApproval`.
|
|
96
|
+
- Review but do not preemptively patch: `src/appV2/redesign/components/WheelTimePicker/WheelColumn.tsx`, because a real product click/scroll bug would need separate proof.
|
|
97
|
+
|
|
98
|
+
**Validation Plan:**
|
|
99
|
+
|
|
100
|
+
- `npx oxfmt --check playwright/e2e/shift/timekeeping.spec.ts`
|
|
101
|
+
- `npm run lint -- playwright/e2e/shift/timekeeping.spec.ts`
|
|
102
|
+
- If the local Playwright environment is available: `npx playwright test --config ./playwright.config.ts --project "Mobile Chrome" playwright/e2e/shift/timekeeping.spec.ts --grep "already started working"`
|
|
103
|
+
- If Playwright setup is missing, run/document `npm run playwright:setup` and the blocker, then rely on CI for the live E2E run.
|
|
104
|
+
|
|
105
|
+
**Open Questions:** None blocking. The implementation can proceed with a test-harness-only change.
|
|
106
|
+
|
|
107
|
+
**Residual Risk:** This flow still depends on live E2E services and real wall-clock time. If the wheel component itself can override clicked selections after smooth scroll in normal user interaction, the test-harness fix will reduce flakes but not address that broader product behavior.
|
package/skills/flaky-critic/references/backtests/2026-07-16-b8-prior-attempts/inputs/case-10.md
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# Historical plan snapshot
|
|
2
|
+
|
|
3
|
+
## Groundcrew
|
|
4
|
+
|
|
5
|
+
Repository: [admin frontend]
|
|
6
|
+
Implementation workflow: implement this ticket using the `cb-work` skill if available. If `cb-work` is unavailable, use the `core:go`/`go` skill. Follow this repo's AGENTS.md implementation workflow and run the documented verification.
|
|
7
|
+
|
|
8
|
+
In the change body, include this implementation ticket ID and investigation ticket `[ticket redacted]`.
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Task
|
|
15
|
+
|
|
16
|
+
Stabilize the shared Playwright E2E Cognito user provisioning path so freshly created facility/workplace/HCP users are not used for Cognito Admin API mutations before they exist in the staging Cognito user pool `us-west-2_HV1ibP3I6`.
|
|
17
|
+
|
|
18
|
+
Do not create per-test fixes. Diagnose and fix the shared setup path used by these fingerprints.
|
|
19
|
+
|
|
20
|
+
## Required Fix Shape
|
|
21
|
+
|
|
22
|
+
Implement one shared Cognito readiness/de-stressing mechanism instead of increasing per-test retries.
|
|
23
|
+
|
|
24
|
+
Required readiness signal:
|
|
25
|
+
|
|
26
|
+
- After [backend service]/test-helper user creation returns successfully, wait for `AdminGetUser` to succeed for the exact synthetic E2E user in pool `us-west-2_HV1ibP3I6` before calling `AdminSetUserPasswordCommand` or `AdminUpdateUserAttributesCommand`.
|
|
27
|
+
- For worker/HCP setup, also verify the returned Cognito user has enough expected identity attributes to safely apply the requested user-type attribute update. If the backend creates the user under a normalized username instead of raw email, resolve that username once and use it consistently for all later Cognito Admin calls.
|
|
28
|
+
- Treat `UserNotFoundException` as readiness-not-yet-met. Do not call password or attribute mutations until readiness is confirmed.
|
|
29
|
+
|
|
30
|
+
Required retry bound and behavior:
|
|
31
|
+
|
|
32
|
+
- Use a bounded wait that is long enough for staging Cognito propagation, with capped backoff and jitter. The existing 5 attempts spaced 2s apart is the observed insufficient bound; replace it with an explicit total timeout such as 60-90s unless investigation shows a better staging-specific bound.
|
|
33
|
+
- Retries must be idempotent. Re-running setup should not create duplicate users, repeatedly reset passwords for the same readiness miss, or fan out multiple identical Cognito Admin calls for one synthetic user.
|
|
34
|
+
- When many users are created in one setup path, limit or serialize Cognito Admin readiness/mutation calls enough to avoid adding burst pressure to Cognito/[backend service]. Prefer a small shared queue or existing repo helper over a new dependency.
|
|
35
|
+
|
|
36
|
+
Required exhaustion metadata:
|
|
37
|
+
|
|
38
|
+
- On timeout, fail with a single enriched error that includes pool ID, synthetic email or canonical username, setup helper path, requested mutation type (`password` or `userType`), total elapsed time, attempt count, last AWS exception name/code/status/request ID if available, last successful readiness state, GitHub run/job identifiers if available from env, and the originating test file/worker where practical.
|
|
39
|
+
- Keep real-user PHI out of logs. The failing users here are synthetic Playwright users, but helper logging should still avoid leaking unrelated user data.
|
|
40
|
+
|
|
41
|
+
## Observability to Reach 5/5 Confidence
|
|
42
|
+
|
|
43
|
+
Current confidence is 4/5 that this is one shared setup/backend-provisioning failure mode because direct staging [backend service]/Cognito telemetry was unavailable during investigation. The implementation should close that gap before the ticket is considered fully canonical.
|
|
44
|
+
|
|
45
|
+
Collect or add enough observability to prove which path is true:
|
|
46
|
+
|
|
47
|
+
- [backend service]/test-helper creates/imports the Cognito user successfully, but Cognito propagation is eventually consistent and the frontend harness must wait for `AdminGetUser` readiness.
|
|
48
|
+
- [backend service]/test-helper returns success before it has deterministically created/imported the Cognito user, so the true fix belongs in [backend service] or its test-helper contract.
|
|
49
|
+
- Cognito/backend throttling or burst pressure is delaying creation/readiness, so the harness must reduce concurrent Admin calls and expose enough timing data to verify the reduction.
|
|
50
|
+
|
|
51
|
+
Concrete signals to capture in Datadog, CI logs, or targeted helper instrumentation:
|
|
52
|
+
|
|
53
|
+
- Timestamp of [backend service]/test-helper user-create response for the synthetic email.
|
|
54
|
+
- Timestamp and outcome of each readiness probe, including `AdminGetUser` success or `UserNotFoundException`.
|
|
55
|
+
- Timestamp and outcome of the subsequent `AdminSetUserPasswordCommand` / `AdminUpdateUserAttributesCommand`.
|
|
56
|
+
- Total elapsed time from backend user-create success to Cognito readiness, grouped by helper path and user type.
|
|
57
|
+
- Any Cognito throttling, AWS SDK status, or [backend service] error/trace ID tied to the synthetic user creation.
|
|
58
|
+
|
|
59
|
+
Do not close this as 5/5 confidence from local green tests alone. Either attach the staging telemetry/CI evidence in the change or document why the fix had to move to [backend service]/auth infrastructure and link the follow-up implementation.
|
|
60
|
+
|
|
61
|
+
## Storm Details
|
|
62
|
+
|
|
63
|
+
Shared error signature:
|
|
64
|
+
|
|
65
|
+
```text
|
|
66
|
+
Error: Cognito user '[EMAIL]' does not exist in pool 'us-west-2_HV1ibP3I6' after 5 attempts. Ensure the user is provisioned in Cognito before running E2E tests.
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Tests bundled: 6
|
|
70
|
+
Repos affected: 1
|
|
71
|
+
CI runs affected: 2
|
|
72
|
+
First failure: 2026-07-06T11:38:20Z
|
|
73
|
+
Last failure: 2026-07-06T11:43:46Z
|
|
74
|
+
|
|
75
|
+
- `9166129be528` — `playwright/e2e/myAccount.spec.ts:88`
|
|
76
|
+
- `26803343548f` — `playwright/e2e/auth.spec.ts:103`
|
|
77
|
+
- `43dfbdb912d9` — `playwright/e2e/placements/acceptApplication.spec.ts:144`
|
|
78
|
+
- `9bbc4081a989` — `playwright/e2e/facilityOnboarding.spec.ts:32`
|
|
79
|
+
- `63172183d01a` — `playwright/e2e/homeHealth/fullLifecycle.spec.ts:876`
|
|
80
|
+
- `6b98dfce6bf1` — `playwright/e2e/auth.spec.ts:182`
|
|
81
|
+
|
|
82
|
+
Runs:
|
|
83
|
+
|
|
84
|
+
- [[external evidence reference]]([external evidence reference])
|
|
85
|
+
- [[external evidence reference]]([external evidence reference])
|
|
86
|
+
|
|
87
|
+
## Investigation Findings
|
|
88
|
+
|
|
89
|
+
Failure surface: test setup/auth/data, before browser user-flow assertions.
|
|
90
|
+
|
|
91
|
+
Shared dependency: staging [backend service]/test-helper user creation plus AWS Cognito user pool `us-west-2_HV1ibP3I6`. CI config sets `E2E_ENVIRONMENT=staging` and `E2E_SERVICE_NAME=[backend service]`.
|
|
92
|
+
|
|
93
|
+
Shared helper path:
|
|
94
|
+
|
|
95
|
+
- `playwright/helpers/cognitoPassword.ts` calls `AdminSetUserPasswordCommand` for freshly created facility users and throws after five `UserNotFoundException` retries spaced 2s apart.
|
|
96
|
+
- `playwright/helpers/cognitoUserTypes.ts` has the sibling pattern for `AdminUpdateUserAttributesCommand` used by worker/HCP setup.
|
|
97
|
+
- Failing tests reach these through shared helpers such as `createFacilityUserWithRetry`, `createLtcFacilityWithUser`, `createHomeHealthcareWorkplaceWithUser`, `createHcfWithAssignedShiftWithRetry`, and `loginWithCognitoPassword`.
|
|
98
|
+
|
|
99
|
+
Representative CI evidence:
|
|
100
|
+
|
|
101
|
+
- Run [reference redacted]`, job `e2e-playwright-1`: `Created facility user ... email: playwright-gtygfpwvlhf@playwright-hcf.com`at`2026-07-06T11:43:07Z`, followed immediately by `Cognito user ... not found (attempt 1/5)`through attempt 4, then the test fails from`playwright/helpers/cognitoPassword.ts:65`.
|
|
102
|
+
- Run [reference redacted]`, job `e2e-playwright-1`: same sequence for `playwright-fovjnxnxzsj@playwright-hcf.com`; the helper fails after five attempts from `playwright/helpers/cognitoPassword.ts:65`.
|
|
103
|
+
- The failures occurred on separate self-hosted runners in the `cbh` group (`m8a.4xlarge`, `us-west-2b`), not one stale workspace.
|
|
104
|
+
- Current `origin/main` still has the same relevant setup code; no open `flaky-test-fix` change was found for this exact signature/fingerprints.
|
|
105
|
+
|
|
106
|
+
Datadog/incident check:
|
|
107
|
+
|
|
108
|
+
- Local Datadog CLI credentials were unavailable (`dog` and `~/.dogrc` absent).
|
|
109
|
+
- [incident.io]([external evidence reference]) telemetry has no configured telemetry datasource, so direct Datadog logs/metrics/traces could not be queried from this session.
|
|
110
|
+
- [incident.io]([external evidence reference]) did not show Cognito/staging/user-create incidents in `2026-07-06T11:00:00Z` to `2026-07-06T12:00:00Z`.
|
|
111
|
+
- One unrelated incident existed in the window: `INC-423` Stripe Payment Issues for Workers.
|
|
112
|
+
- One Platform Datadog alert existed in the window: production HCF login high latency at `2026-07-06T11:05:36Z`; this does not directly explain staging Cognito user provisioning.
|
|
113
|
+
|
|
114
|
+
Current confidence: 4/5 that this is one shared setup/backend-provisioning failure mode, not six independent test flakes. Confidence is not 5/5 because direct Datadog traces/logs for staging [backend service]/Cognito provisioning were unavailable.
|
|
115
|
+
|
|
116
|
+
## Acceptance Criteria
|
|
117
|
+
|
|
118
|
+
- [ ] The shared setup path waits on or deterministically creates/validates Cognito users before `AdminSetUserPassword`/`AdminUpdateUserAttributes` are called.
|
|
119
|
+
- [ ] Readiness is based on a concrete `AdminGetUser` success signal, with a documented timeout/backoff bound and clear behavior for `UserNotFoundException`, throttling, and final timeout.
|
|
120
|
+
- [ ] Timeout failures include the exhaustion metadata listed above so future flakes can be debugged from CI logs without rerunning the investigation.
|
|
121
|
+
- [ ] Retries are idempotent and do not amplify Cognito/backend throttling.
|
|
122
|
+
- [ ] The implementation reduces call burstiness where the shared setup creates multiple users or applies multiple Cognito mutations in one flow.
|
|
123
|
+
- [ ] The fix applies to all contained fingerprints, not individual test assertions.
|
|
124
|
+
- [ ] If [backend service] or auth infrastructure is the true fix locus, document the frontend harness evidence and implement in the correct repo or add the needed observability before closing.
|
|
125
|
+
- [ ] Add or update focused tests for the shared helper behavior where practical.
|
|
126
|
+
- [ ] Run the documented relevant verification for the changed repo.
|
|
127
|
+
|
|
128
|
+
## Suggested Starting Points
|
|
129
|
+
|
|
130
|
+
- `playwright/helpers/cognitoPassword.ts`
|
|
131
|
+
- `playwright/helpers/cognitoUserTypes.ts`
|
|
132
|
+
- `playwright/api/user.ts`
|
|
133
|
+
- `playwright/api/facility.ts`
|
|
134
|
+
- `playwright/api/homeHealth.ts`
|
|
135
|
+
- `playwright/helpers/login.ts`
|
|
136
|
+
|
|
137
|
+
Also inspect backend/test-helper behavior for `/api/facilityUser`, `/api/user/create`, and any JIT Cognito import path that should make new users appear in `us-west-2_HV1ibP3I6`.
|
|
138
|
+
|
|
139
|
+
## Related
|
|
140
|
+
|
|
141
|
+
Investigation: `[ticket redacted]`
|
package/skills/flaky-critic/references/backtests/2026-07-16-b8-prior-attempts/inputs/case-11.md
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# Historical plan snapshot
|
|
2
|
+
|
|
3
|
+
## Groundcrew
|
|
4
|
+
|
|
5
|
+
Repository: `[admin frontend]`
|
|
6
|
+
Implementation workflow: use the `cb-work` skill or, if unavailable, the `core:go` skill.
|
|
7
|
+
|
|
8
|
+
Include this implementation ticket ID in the change body.
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Flake details
|
|
15
|
+
|
|
16
|
+
```json
|
|
17
|
+
{
|
|
18
|
+
"repo": "[admin frontend]",
|
|
19
|
+
"test": "Chat (redesign) — mobile chat from shift details on mobile renders as a stacked bottom sheet and can be ended",
|
|
20
|
+
"file": "playwright/e2e/chat.spec.ts:241",
|
|
21
|
+
"framework": "playwright",
|
|
22
|
+
"isNewFlaky": false,
|
|
23
|
+
"failures": [
|
|
24
|
+
{
|
|
25
|
+
"error": "Error: expect(page).toHaveURL(expected) failed\n\nExpected pattern: /chatWorkerId=/\nReceived string: \"[external evidence reference]"\nTimeout: 4000ms\n\nCall log:\n - Expect \"toHaveURL\" with timeout 4000ms\n 8 × unexpected value \"[external evidence reference]"\n\n\nCall Log:\n- Timeout 30000ms exceeded while waiting on the predicate",
|
|
26
|
+
"stack": "Error: expect(page).toHaveURL(expected) failed\n\nExpected pattern: /chatWorkerId=/\nReceived string: \"[external evidence reference]"\nTimeout: 4000ms\n\nCall log:\n - Expect \"toHaveURL\" with timeout 4000ms\n 8 × unexpected value \"[external evidence reference]"\n\n\nCall Log:\n- Timeout 30000ms exceeded while waiting on the predicate\n at clickUntilUrl (/opt/actions-runner/_work/[admin frontend]/[admin frontend]/playwright/e2e/chat.spec.ts:125:6)\n at /opt/actions-runner/_work/[admin frontend]/[admin frontend]/playwright/e2e/chat.spec.ts:264:13\n at WorkerMain._runTest (/opt/actions-runner/_work/[admin frontend]/[admin frontend]/node_modules/dd-trace/packages/datadog-instrumentations/src/playwright.js:1692:5)",
|
|
27
|
+
"branch": "main",
|
|
28
|
+
"pipeline": "[external evidence reference]",
|
|
29
|
+
"commit": "40f5b4ebe9cc9d01c4ef6129a67e238087690723",
|
|
30
|
+
"durationMs": 60384,
|
|
31
|
+
"shard": "4/4",
|
|
32
|
+
"timestamp": "2026-07-02T15:01:43Z"
|
|
33
|
+
}
|
|
34
|
+
]
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Plan output
|
|
39
|
+
|
|
40
|
+
**Test ID:** `03dd965d45c5`
|
|
41
|
+
|
|
42
|
+
**Confidence:** 4/5. The artifact directly proves chat opened while `chatWorkerId` was absent. The missing link is exact identification of the competing history writer because current reporter output does not log URL writes.
|
|
43
|
+
|
|
44
|
+
**Failure surface:** Product/client state drift. The click was not a no-op and the backend chat-channel request succeeded; the failure is the client URL state not reflecting the open chat panel.
|
|
45
|
+
|
|
46
|
+
**Current main status:** Current `origin/main` still has the failing code path. The failing commit `40f5b4e` already included prior test-only hardening from change [reference redacted] and change [reference redacted]. No later relevant changes touched `playwright/e2e/chat.spec.ts`, `useChatPanel`, or `useShiftDeepLinking`.
|
|
47
|
+
|
|
48
|
+
**Symptom:** The Playwright test clicked the mobile Shift Details `Chat` button, then `clickUntilUrl(... /chatWorkerId=/ ...)` timed out for 30s. The final URL remained `/schedule?date=2026-07-03&view=day&shiftId=6a467d5e35d466dbaffea56b`.
|
|
49
|
+
|
|
50
|
+
**Root cause:** The shift-details chat modal and the URL are two sources of truth. In this occurrence the chat modal state and worker info were set, but `chatWorkerId` was missing from the URL. The earlier retry helper correctly avoids re-clicking once chat is visibly open, so it cannot repair this state drift.
|
|
51
|
+
|
|
52
|
+
**Evidence:**
|
|
53
|
+
|
|
54
|
+
- LLM report for run [reference redacted]`: attempt 1 failed; attempt 2 passed.
|
|
55
|
+
- Failure timeline: at ~28.6s, `Click getByRole('button', { name: 'Chat', exact: true })` completed; at ~29.07s, two `POST [external evidence reference] calls returned `201`with request body`{"facilityId":"6a467d5ca3fe1f1fd5fb40e5","agentId":"6a467d5936acbdb4f58f3d02"}`.
|
|
56
|
+
- Screenshot/page snapshot at failure show `Close chat`, `Chat messages`, and the disabled `Chat message` textbox mounted in the stacked bottom sheet.
|
|
57
|
+
- The URL assertion still saw no `chatWorkerId` for the entire retry budget.
|
|
58
|
+
- change [reference redacted] originally included a guarded URL reconciliation effect in `useChatPanel`, then removed it before integration. Its own notes say to re-add it if this exact flake recurs.
|
|
59
|
+
|
|
60
|
+
**Proposed fix:** Product fix in `src/appV2/redesign/Chat/hooks/useChatPanel.ts` plus focused hook tests.
|
|
61
|
+
|
|
62
|
+
1. Reintroduce the guarded reconciliation from change [reference redacted]'s removed commits:
|
|
63
|
+
- import `useLocation` in `useChatPanel`;
|
|
64
|
+
- track `chatOpenedShiftId` in a ref;
|
|
65
|
+
- set that ref when chat opens from a click or deep link;
|
|
66
|
+
- clear it when chat closes or when shift-change cleanup runs;
|
|
67
|
+
- while chat is open and `chatWorkerInfo.workerId` exists, if `location.search` lacks the matching `chatWorkerId` and `chatOpenedShiftId.current === shiftId`, call `updateChatUrlParameter(chatWorkerInfo.workerId)`.
|
|
68
|
+
2. Keep the shift guard. Without it, a later shift change could resurrect `?shiftId=B&chatWorkerId=A`.
|
|
69
|
+
3. Add/restore `useChatPanel.test.tsx` coverage:
|
|
70
|
+
- restores `chatWorkerId` when another URL writer drops it while chat is open on the same shift;
|
|
71
|
+
- does not restore `chatWorkerId` after switching to another shift;
|
|
72
|
+
- preserves existing close/toggle/deep-link behavior.
|
|
73
|
+
4. Do not add more Playwright retries/timeouts for this symptom; the app state is already visibly open, so extra clicking would mask URL/state drift.
|
|
74
|
+
|
|
75
|
+
**Observability to reach 5/5:** Add temporary or permanent frontend debug telemetry for query-param modal URL writes in this area:
|
|
76
|
+
|
|
77
|
+
- In `useChatPanel.updateChatUrlParameter`, log old URL, new URL, workerId, shiftId, and reason (`open`, `close`, `repair`) in non-PII-safe structured form.
|
|
78
|
+
- In `useShiftDeepLinking.updateUrl` / `buildShiftDeepLinkUrl`, log old URL, new URL, shiftId/inviteId, and whether `chatWorkerId` was preserved or removed.
|
|
79
|
+
- Ideally emit these as Datadog RUM actions or console debug gated for E2E so the Playwright LLM report captures the writer sequence next time.
|
|
80
|
+
|
|
81
|
+
**Sibling candidates:** Query-param-driven drawer/sheet hooks that maintain separate React modal state and URL params: `useShiftDeepLinking`, `useChatPanel`, My Professionals profile/chat URL state, MonthlyView selected slot/chat URL state.
|
|
82
|
+
|
|
83
|
+
**Validation plan:**
|
|
84
|
+
|
|
85
|
+
- `npm run test:v2 -- src/appV2/redesign/Chat/hooks/useChatPanel.test.tsx src/appV2/redesign/DailyView/hooks/useShiftDeepLinking.test.tsx`
|
|
86
|
+
- `npm run lint:fast -- src/appV2/redesign/Chat/hooks/useChatPanel.ts src/appV2/redesign/Chat/hooks/useChatPanel.test.tsx`
|
|
87
|
+
- If a deployed environment is available, rerun `playwright/e2e/chat.spec.ts` for the mobile project against staging/development.
|
|
88
|
+
|
|
89
|
+
**Open questions:** None blocking. A larger URL-as-source-of-truth modal model would be cleaner, but the guarded reconciliation is the smallest fix supported by this artifact.
|
|
90
|
+
|
|
91
|
+
**Residual risk:** If a different writer repeatedly strips `chatWorkerId` every render, reconciliation could loop or hide a deeper ownership bug. The shift guard and tests reduce stale-worker risk, and URL-write telemetry would make any remaining loop diagnosable.
|
|
92
|
+
|
|
93
|
+
## Prior related context
|
|
94
|
+
|
|
95
|
+
- `[ticket redacted]`: prior investigation.
|
|
96
|
+
- `[ticket redacted]`: duplicate prior investigation.
|
|
97
|
+
- `[ticket redacted]`: prior implementation for the same family of mobile chat URL flakes.
|
|
98
|
+
- change [reference redacted]: test-only hardening available after removing the exact product-side reconciliation that this recurrence now supports.
|
package/skills/flaky-critic/references/backtests/2026-07-16-b8-prior-attempts/inputs/case-12.md
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# Historical plan snapshot
|
|
2
|
+
|
|
3
|
+
## Groundcrew
|
|
4
|
+
|
|
5
|
+
Repository: [mobile frontend]
|
|
6
|
+
Implementation workflow: use the `cb-work` skill when available. If that skill is unavailable, use the `core:go` skill.
|
|
7
|
+
|
|
8
|
+
## Task
|
|
9
|
+
|
|
10
|
+
Fix the flaky Playwright flow where the rate-negotiation `SlideToConfirmButton` sometimes does not invoke the proposal action, leaving the test on `/shift-negotiation/:shiftId` after the slide gesture instead of navigating back to `/shift/:shiftId`.
|
|
11
|
+
|
|
12
|
+
Include this implementation ticket ID in the change body.
|
|
13
|
+
|
|
14
|
+
## Flake Details
|
|
15
|
+
|
|
16
|
+
```json
|
|
17
|
+
{
|
|
18
|
+
"repo": "[mobile frontend]",
|
|
19
|
+
"test": "Rate Negotiations new UI should propose new rate for a shift and end negotiation",
|
|
20
|
+
"file": "playwright/e2e/rateNegotiations/rateNegotiationv2.spec.ts:369",
|
|
21
|
+
"framework": "playwright",
|
|
22
|
+
"isNewFlaky": false,
|
|
23
|
+
"failures": [
|
|
24
|
+
{
|
|
25
|
+
"error": "Error: expect(page).toHaveURL(expected) failed\n\nExpected: \"[external evidence reference]"\nReceived: \"[external evidence reference]"\nTimeout: 30000ms",
|
|
26
|
+
"stack": "rateNegotiationv2.spec.ts:466",
|
|
27
|
+
"branch": "main",
|
|
28
|
+
"pipeline": "[external evidence reference]",
|
|
29
|
+
"commit": "7638c4bd74e598414254053d8c97e0611dbad943",
|
|
30
|
+
"durationMs": 52870,
|
|
31
|
+
"shard": "2/4",
|
|
32
|
+
"timestamp": "2026-07-06T16:26:13Z"
|
|
33
|
+
}
|
|
34
|
+
]
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Plan Output
|
|
39
|
+
|
|
40
|
+
Confidence: 4/5. The failure artifact directly shows the slide CTA still open after the gesture, and the component code has a concrete stale-state completion check. Confidence is not 5/5 because the LLM report hit network retention caps, so absence of a retained `POST /negotiation` is strong but not absolute proof that no mutation request was emitted.
|
|
41
|
+
|
|
42
|
+
Failure surface: User action no-op, with product component behavior as the likely root and test harness diagnostics as a secondary improvement.
|
|
43
|
+
|
|
44
|
+
Current main status: The affected code path still exists on current `origin/main`/HEAD `a58a6893d9c025196f1b10bff49b548f2cd03910`. No open change with label `flaky-test-fix` matched this test or file. Commit `77129b26883` landed after the failing commit and only adds `workerAuthToken` to shift-offer setup; it does not address the slide/no-op path.
|
|
45
|
+
|
|
46
|
+
Symptom: In failed attempt 0, the test executes `slideToConfirmButton(page, "Slide to propose $33.00/hr")`, then `expect(page).toHaveURL(shiftDetailsPath)` times out at `playwright/e2e/rateNegotiations/rateNegotiationv2.spec.ts:467`. The actual URL stays `/home-v2/shift-discovery/list/shift-negotiation/6a4bd731b22f99dbbc009a7d`.
|
|
47
|
+
|
|
48
|
+
Root cause: `SlideToConfirmButton` decides whether the slide completed in `handlePointerUp` using React state `offsetX`. During a fast drag/release, especially under CI load, the last `pointermove` can call `setOffsetX(...)` but `pointerup` can still observe the previous render's `offsetX` value. That makes the component reset to 0 and skip `onConfirm()`, even though the pointer moved far enough. The Playwright helper triggers this edge by moving and releasing quickly after the rate-negotiation footer migration to `SlideToConfirmButton` in commit `7638c4bd74e`.
|
|
49
|
+
|
|
50
|
+
Evidence:
|
|
51
|
+
|
|
52
|
+
- LLM report `/tmp/playwright-llm-report-28806486162/llm-report.json` has one flaky test in the shard: 15 passed, this test passed only on retry.
|
|
53
|
+
- Failed timeline: `Bounding box getByText('Slide to propose $33.00/hr').locator('../..')` at 20536ms, `Mouse move` at 20541ms, `Mouse down` at 20545ms, `Mouse move` at 20562ms, `Mouse up` at 21272ms, then `Expect "toHaveURL"` fails at 21275ms.
|
|
54
|
+
- Failure screenshot shows the `Shift Rate Negotiation` bottom sheet still open with `Slide to propose $33.00/hr`; it is not in loading/success state and has not navigated away.
|
|
55
|
+
- Retained negotiation network entries around the slide are reads only: `GET /api/negotiation/shifts/:shiftId?offerId=...` at 19826ms and 20878ms. There is no retained `POST /negotiation` proposal write near the slide. The report did hit network caps (`instancesDroppedByGroupCap: 17`, `instancesEvictedAfterAdmission: 10`), so this supports but does not solely prove the no-op.
|
|
56
|
+
- `src/appV2/redesign/system/ui-components/components/SlideToConfirmButton/index.tsx` lines 177-209 update `offsetX` in `handlePointerMove` and read `offsetX` in `handlePointerUp` to decide `offsetX / currentMax >= 0.8`.
|
|
57
|
+
- `playwright/utils/button.ts` lines 43-59 uses a generic fast mouse drag for every `SlideToConfirmButton`; `playwright/e2e/rateNegotiations/rateNegotiationv2.spec.ts` uses it at lines 464 and 634. Timekeeping E2Es also use the same helper.
|
|
58
|
+
- There is no dedicated `SlideToConfirmButton` component test file covering fast drag/release behavior.
|
|
59
|
+
|
|
60
|
+
Proposed fix:
|
|
61
|
+
|
|
62
|
+
1. In `src/appV2/redesign/system/ui-components/components/SlideToConfirmButton/index.tsx`, stop using render-state `offsetX` as the source of truth inside `handlePointerUp`. Compute the release offset from the current `PointerEvent` (`event.clientX - dragStateRef.current.startX`) and/or keep the latest clamped offset in a ref that is updated synchronously in `handlePointerMove`. Use that computed/ref value for the threshold check, then update state for rendering.
|
|
63
|
+
2. Keep the reset/complete state transitions the same: partial drags reset to 0; completed drags set to max, mark complete, and call `onConfirm()` exactly once.
|
|
64
|
+
3. Add focused appV2 component coverage for `SlideToConfirmButton`: a fast drag that crosses the threshold and releases immediately calls `onConfirm`, a partial drag does not, and disabled/loading states still do not call `onConfirm`. Prefer user-facing queries where possible; if the current component lacks accessible semantics, keep the test scoped to the rendered CTA text and pointer events.
|
|
65
|
+
4. Improve E2E diagnostics around the proposal action in `playwright/e2e/rateNegotiations/rateNegotiationv2.spec.ts`: after sliding, wait for the deterministic proposal mutation or a post-success route/UI signal so a future no-op fails at the missing `POST /negotiation`/confirm signal instead of a 30s URL timeout. Avoid arbitrary sleeps or blind retries.
|
|
66
|
+
|
|
67
|
+
Observability to reach 5/5:
|
|
68
|
+
|
|
69
|
+
- Add deterministic Playwright evidence around the slide action: wait for the `POST /negotiation` request/response after the proposal slide and include its absence in the failure path.
|
|
70
|
+
- If touching the component, consider adding temporary debug output gated by the existing E2E/debug localStorage pattern or test-only attachments for slide metrics (`startX`, release delta, max offset, threshold result) if the component remains hard to diagnose in traces.
|
|
71
|
+
- No backend telemetry is required for this plan unless the deterministic wait proves the mutation is emitted and failing server-side.
|
|
72
|
+
|
|
73
|
+
Sibling candidates:
|
|
74
|
+
|
|
75
|
+
- `playwright/e2e/rateNegotiations/rateNegotiationv2.spec.ts:634` uses the same helper in the counter-proposal path.
|
|
76
|
+
- `playwright/e2e/shift/timekeeping.spec.ts` uses `slideToConfirmButton` for clock-out flows at lines 663, 755, 858, and 1010.
|
|
77
|
+
- All product uses of shared `SlideToConfirmButton` inherit the stale pointer-state behavior, including shift cancel, timekeeping, booking confirmation, Clipboard Score, and rate negotiation.
|
|
78
|
+
|
|
79
|
+
Validation plan:
|
|
80
|
+
|
|
81
|
+
- `npm run test:v2 src/appV2/redesign/system/ui-components/components/SlideToConfirmButton/SlideToConfirmButton.test.tsx`
|
|
82
|
+
- `npm run test:v2 src/appV2/Negotiations/RateNegotiationBottomSheet.test.tsx`
|
|
83
|
+
- With a valid `playwright.env`, run `npx playwright test playwright/e2e/rateNegotiations/rateNegotiationv2.spec.ts --project "Mobile Chrome" --config ./playwright.config.ts`
|
|
84
|
+
- Run the repo's standard verification command if required by the final diff scope.
|
|
85
|
+
|
|
86
|
+
Open questions: None blocking. The highest-confidence local fix is in the shared slide component; the E2E change should improve diagnostics, not mask the product behavior.
|
|
87
|
+
|
|
88
|
+
Residual risk: If fixing the slide component reveals a real backend/post-success navigation issue after `POST /negotiation`, the deterministic E2E wait should expose that as a different failure surface with a request/response artifact.
|
|
89
|
+
|
|
90
|
+
## Acceptance Criteria
|
|
91
|
+
|
|
92
|
+
- [ ] Fast slide/release over the completion threshold reliably calls `onConfirm` in `SlideToConfirmButton`.
|
|
93
|
+
- [ ] Partial/disabled/loading slide cases remain unchanged.
|
|
94
|
+
- [ ] The rate-negotiation proposal E2E waits on a deterministic proposal or post-success signal instead of relying only on a later URL timeout.
|
|
95
|
+
- [ ] Validation commands above pass or any environment-only blocker is documented in the change.
|
|
96
|
+
|
|
97
|
+
## Related
|
|
98
|
+
|
|
99
|
+
Investigation ticket: `[ticket redacted]`
|
package/skills/flaky-critic/references/backtests/2026-07-16-b8-prior-attempts/inputs/case-13.md
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Historical plan snapshot
|
|
2
|
+
|
|
3
|
+
## Flaky Test Report
|
|
4
|
+
|
|
5
|
+
The following E2E test in `[admin frontend]` is among the **top 10 flakiest tests** (last 30 days) on the [Datadog Flaky Tests Management]([external evidence reference]) dashboard. Owned by **Synapse**.
|
|
6
|
+
|
|
7
|
+
### Affected Tests
|
|
8
|
+
|
|
9
|
+
| \# | Test | Failures (30d) | File | Repo |
|
|
10
|
+
| --- | ---------------------------------------------------------------------------------------------------------------- | -------------- | ---------------------------------- | ------------------------------------------------- |
|
|
11
|
+
| 1 | `Daily View — Admin User should navigate to daily view, display shifts, interact with filters and shift details` | 6 | `playwright/e2e/dailyView.spec.ts` | [[admin frontend]]([external evidence reference]) |
|
|
12
|
+
|
|
13
|
+
### Datadog Links
|
|
14
|
+
|
|
15
|
+
- [Flaky Tests Dashboard]([external evidence reference])
|
|
16
|
+
|
|
17
|
+
### Context
|
|
18
|
+
|
|
19
|
+
This test exercises the Daily View page for an Admin User — navigating to it, verifying shifts are displayed, and interacting with filters and shift details. Previous investigations ([ticket redacted], [ticket redacted]) canonical earlier occurrences, but the test continues to flake.
|
|
20
|
+
|
|
21
|
+
### Recommended Next Steps
|
|
22
|
+
|
|
23
|
+
1. Check Datadog CI test traces for the specific failure error messages
|
|
24
|
+
2. Compare with previous fix in [ticket redacted] to see if the same root cause has regressed
|
|
25
|
+
3. Investigate filter interaction timing or data loading race conditions
|