diff --git a/docs/ui-cleanup/README.md b/docs/ui-cleanup/README.md new file mode 100644 index 0000000..f665bdd --- /dev/null +++ b/docs/ui-cleanup/README.md @@ -0,0 +1,53 @@ +# UI cleanup browser evidence + +The screenshots compare frozen baseline `b826f88` (served from `/tmp/foreman-ui-cleanup-baseline-b826f88`) with the final UI at `1655af6`. Each phase uses the same deterministic Atlas API fixture, viewport height (1050 px), opened usage dock, task data, run events, quota readings, and GitHub status. Screenshots use JPEG quality 80 with animation and transitions disabled. The app is served through Vite only; Playwright intercepts every `/api/**` request, including the event stream. No backend or live Planner, Worker, Reviewer, or provider is started. + +The matrix covers four states (idle project, active validation, failed API contract validation, and awaiting human approval), three widths (1024, 1440, 1920), and dark/light themes. See [`checks.json`](./checks.json) for all 48 deduplicated page and scroll-container measurements, actual theme assertions, page errors, writes, focused keyboard probe results, and Open PR interaction checks. Intended center-panel vertical scrolling is allowed; the page and tested horizontal scroll containers have no horizontal overflow. + +## 1440 px comparison + +| State | Theme | Before | After | +|---|---|---|---| +| Idle project | Dark | [viewport](./before/idle-dark-1440-viewport.jpeg) | [viewport](./after/idle-dark-1440-viewport.jpeg) | +| Idle project | Light | [viewport](./before/idle-light-1440-viewport.jpeg) | [viewport](./after/idle-light-1440-viewport.jpeg) | +| Active run | Dark | [viewport](./before/active-dark-1440-viewport.jpeg) | [viewport](./after/active-dark-1440-viewport.jpeg) | +| Active run | Light | [viewport](./before/active-light-1440-viewport.jpeg) | [viewport](./after/active-light-1440-viewport.jpeg) | +| Failed validation | Dark | [failed check and output](./before/failed-dark-1440-center.jpeg) | [failed check and output](./after/failed-dark-1440-center.jpeg) | +| Failed validation | Light | [scrolled viewport](./before/failed-light-1440-viewport.jpeg) | [scrolled viewport](./after/failed-light-1440-viewport.jpeg) | +| Awaiting approval | Dark | [review controls](./before/approval-dark-1440-review.jpeg) | [review controls](./after/approval-dark-1440-review.jpeg) | +| Awaiting approval | Light | [review controls](./before/approval-light-1440-review.jpeg) | [review controls](./after/approval-light-1440-review.jpeg) | + +The active fixture has one passed, one running, and one queued validation check plus Worker/Orchestrator progress events, so the Live Response activity and running phase are populated. The usage dock is open in each screenshot. The approval review images show the ready decision controls. Open PR is disabled in the default fixture, with a reason explaining that the result must first be promoted. + +The complete 1024 and 1920 screenshot matrix is retained locally at `/tmp/foreman-ui-cleanup-width-matrix/{before,after}` for review; it is intentionally not part of the committed evidence to keep the docs compact. The linked 1440 viewport images show the same capture framing; the failed state also has a dedicated center-panel capture, and approval has dedicated center and GitHub panel captures. + +## Interaction and accessibility checks + +The browser interaction check exercises four promotion states. A matching but unpromoted task result is disabled; a promoted result with a missing remote branch is disabled; a different remote SHA is disabled; and a matching promoted remote branch enables Open PR and opens the existing confirmation dialog. The dialog was not submitted. All four checks recorded zero writes, and each matrix page independently recorded zero writes. The focus probe used Tab to focus the theme toggle in both themes and verified a visible solid 2 px `:focus-visible` outline. This is a targeted focus check, not a full keyboard traversal or accessibility audit. + +Static token-pair contrast calculations supplied for the final stylesheet: + +| Pair | Dark | Light | +|---|---:|---:| +| Text / surface | 14.87:1 | 12.63:1 | +| Dim / surface | 9.44:1 | 7.00:1 | +| Muted / surface | 6.33:1 | 4.76:1 | +| Semantic badge foreground / background (minimum) | 7.65:1 | 5.85:1 | +| Quota fill / rail | 6.33:1 | 4.76:1 | +| Focus ring / surface | 16.16:1 | 4.15:1 | + +These are static token-pair calculations. They do not assess every rendered state, text size, overlay, or interaction and should not be read as a comprehensive WCAG audit. + +## Reproduce + +The harness is [`capture.mjs`](./capture.mjs), with fixture responses defined inline. It requires an external Playwright install and Chrome/Chromium; no project dependency or package file is changed. Set `PLAYWRIGHT_MODULE` to the external Playwright `index.mjs` path if it is not installed in this repository, and optionally set `CHROME_PATH` to a Chrome/Chromium executable. The harness uses `/usr/bin/google-chrome` when present, otherwise Playwright's installed browser. + +Serve Vite from the baseline tree and working tree on separate ports, without starting the backend. Then capture either phase by setting `BASE_URL`, `SCREEN_DIR`, and `METRICS_PATH`; `THEMES`, `WIDTHS`, and `STATES` can filter the matrix. Set `RUN_INTERACTION_CHECKS=1` to additionally run the Open PR gate and focus probes. All API requests are stubbed by the harness. Example for the working tree: + +```sh +PLAYWRIGHT_MODULE=/path/to/node_modules/playwright/index.mjs \ +BASE_URL=http://127.0.0.1:5174/ \ +SCREEN_DIR="$PWD/docs/ui-cleanup/after" \ +METRICS_PATH=/tmp/foreman-ui-cleanup/after.jsonl \ +RUN_INTERACTION_CHECKS=1 node docs/ui-cleanup/capture.mjs +``` diff --git a/docs/ui-cleanup/after/active-dark-1440-viewport.jpeg b/docs/ui-cleanup/after/active-dark-1440-viewport.jpeg new file mode 100644 index 0000000..57db97f Binary files /dev/null and b/docs/ui-cleanup/after/active-dark-1440-viewport.jpeg differ diff --git a/docs/ui-cleanup/after/active-light-1440-viewport.jpeg b/docs/ui-cleanup/after/active-light-1440-viewport.jpeg new file mode 100644 index 0000000..9c7b777 Binary files /dev/null and b/docs/ui-cleanup/after/active-light-1440-viewport.jpeg differ diff --git a/docs/ui-cleanup/after/approval-dark-1440-center.jpeg b/docs/ui-cleanup/after/approval-dark-1440-center.jpeg new file mode 100644 index 0000000..d3321e8 Binary files /dev/null and b/docs/ui-cleanup/after/approval-dark-1440-center.jpeg differ diff --git a/docs/ui-cleanup/after/approval-dark-1440-github.jpeg b/docs/ui-cleanup/after/approval-dark-1440-github.jpeg new file mode 100644 index 0000000..8ae0086 Binary files /dev/null and b/docs/ui-cleanup/after/approval-dark-1440-github.jpeg differ diff --git a/docs/ui-cleanup/after/approval-dark-1440-review.jpeg b/docs/ui-cleanup/after/approval-dark-1440-review.jpeg new file mode 100644 index 0000000..c246055 Binary files /dev/null and b/docs/ui-cleanup/after/approval-dark-1440-review.jpeg differ diff --git a/docs/ui-cleanup/after/approval-dark-1440-viewport.jpeg b/docs/ui-cleanup/after/approval-dark-1440-viewport.jpeg new file mode 100644 index 0000000..bfc8b23 Binary files /dev/null and b/docs/ui-cleanup/after/approval-dark-1440-viewport.jpeg differ diff --git a/docs/ui-cleanup/after/approval-light-1440-review.jpeg b/docs/ui-cleanup/after/approval-light-1440-review.jpeg new file mode 100644 index 0000000..5f18bc0 Binary files /dev/null and b/docs/ui-cleanup/after/approval-light-1440-review.jpeg differ diff --git a/docs/ui-cleanup/after/approval-light-1440-viewport.jpeg b/docs/ui-cleanup/after/approval-light-1440-viewport.jpeg new file mode 100644 index 0000000..50ab80b Binary files /dev/null and b/docs/ui-cleanup/after/approval-light-1440-viewport.jpeg differ diff --git a/docs/ui-cleanup/after/failed-dark-1440-center.jpeg b/docs/ui-cleanup/after/failed-dark-1440-center.jpeg new file mode 100644 index 0000000..4982e80 Binary files /dev/null and b/docs/ui-cleanup/after/failed-dark-1440-center.jpeg differ diff --git a/docs/ui-cleanup/after/failed-dark-1440-viewport.jpeg b/docs/ui-cleanup/after/failed-dark-1440-viewport.jpeg new file mode 100644 index 0000000..9277ed4 Binary files /dev/null and b/docs/ui-cleanup/after/failed-dark-1440-viewport.jpeg differ diff --git a/docs/ui-cleanup/after/failed-light-1440-viewport.jpeg b/docs/ui-cleanup/after/failed-light-1440-viewport.jpeg new file mode 100644 index 0000000..374f589 Binary files /dev/null and b/docs/ui-cleanup/after/failed-light-1440-viewport.jpeg differ diff --git a/docs/ui-cleanup/after/idle-dark-1440-viewport.jpeg b/docs/ui-cleanup/after/idle-dark-1440-viewport.jpeg new file mode 100644 index 0000000..1bd6396 Binary files /dev/null and b/docs/ui-cleanup/after/idle-dark-1440-viewport.jpeg differ diff --git a/docs/ui-cleanup/after/idle-light-1440-viewport.jpeg b/docs/ui-cleanup/after/idle-light-1440-viewport.jpeg new file mode 100644 index 0000000..52811ac Binary files /dev/null and b/docs/ui-cleanup/after/idle-light-1440-viewport.jpeg differ diff --git a/docs/ui-cleanup/before/active-dark-1440-viewport.jpeg b/docs/ui-cleanup/before/active-dark-1440-viewport.jpeg new file mode 100644 index 0000000..7dd11fc Binary files /dev/null and b/docs/ui-cleanup/before/active-dark-1440-viewport.jpeg differ diff --git a/docs/ui-cleanup/before/active-light-1440-viewport.jpeg b/docs/ui-cleanup/before/active-light-1440-viewport.jpeg new file mode 100644 index 0000000..0eb4834 Binary files /dev/null and b/docs/ui-cleanup/before/active-light-1440-viewport.jpeg differ diff --git a/docs/ui-cleanup/before/approval-dark-1440-center.jpeg b/docs/ui-cleanup/before/approval-dark-1440-center.jpeg new file mode 100644 index 0000000..e808f8d Binary files /dev/null and b/docs/ui-cleanup/before/approval-dark-1440-center.jpeg differ diff --git a/docs/ui-cleanup/before/approval-dark-1440-github.jpeg b/docs/ui-cleanup/before/approval-dark-1440-github.jpeg new file mode 100644 index 0000000..378d847 Binary files /dev/null and b/docs/ui-cleanup/before/approval-dark-1440-github.jpeg differ diff --git a/docs/ui-cleanup/before/approval-dark-1440-review.jpeg b/docs/ui-cleanup/before/approval-dark-1440-review.jpeg new file mode 100644 index 0000000..c57d223 Binary files /dev/null and b/docs/ui-cleanup/before/approval-dark-1440-review.jpeg differ diff --git a/docs/ui-cleanup/before/approval-dark-1440-viewport.jpeg b/docs/ui-cleanup/before/approval-dark-1440-viewport.jpeg new file mode 100644 index 0000000..b63d659 Binary files /dev/null and b/docs/ui-cleanup/before/approval-dark-1440-viewport.jpeg differ diff --git a/docs/ui-cleanup/before/approval-light-1440-review.jpeg b/docs/ui-cleanup/before/approval-light-1440-review.jpeg new file mode 100644 index 0000000..33c7b84 Binary files /dev/null and b/docs/ui-cleanup/before/approval-light-1440-review.jpeg differ diff --git a/docs/ui-cleanup/before/approval-light-1440-viewport.jpeg b/docs/ui-cleanup/before/approval-light-1440-viewport.jpeg new file mode 100644 index 0000000..c6cb05f Binary files /dev/null and b/docs/ui-cleanup/before/approval-light-1440-viewport.jpeg differ diff --git a/docs/ui-cleanup/before/failed-dark-1440-center.jpeg b/docs/ui-cleanup/before/failed-dark-1440-center.jpeg new file mode 100644 index 0000000..fbbee89 Binary files /dev/null and b/docs/ui-cleanup/before/failed-dark-1440-center.jpeg differ diff --git a/docs/ui-cleanup/before/failed-dark-1440-viewport.jpeg b/docs/ui-cleanup/before/failed-dark-1440-viewport.jpeg new file mode 100644 index 0000000..3c53f59 Binary files /dev/null and b/docs/ui-cleanup/before/failed-dark-1440-viewport.jpeg differ diff --git a/docs/ui-cleanup/before/failed-light-1440-viewport.jpeg b/docs/ui-cleanup/before/failed-light-1440-viewport.jpeg new file mode 100644 index 0000000..f4d8be5 Binary files /dev/null and b/docs/ui-cleanup/before/failed-light-1440-viewport.jpeg differ diff --git a/docs/ui-cleanup/before/idle-dark-1440-viewport.jpeg b/docs/ui-cleanup/before/idle-dark-1440-viewport.jpeg new file mode 100644 index 0000000..1fcaabb Binary files /dev/null and b/docs/ui-cleanup/before/idle-dark-1440-viewport.jpeg differ diff --git a/docs/ui-cleanup/before/idle-light-1440-viewport.jpeg b/docs/ui-cleanup/before/idle-light-1440-viewport.jpeg new file mode 100644 index 0000000..24f1212 Binary files /dev/null and b/docs/ui-cleanup/before/idle-light-1440-viewport.jpeg differ diff --git a/docs/ui-cleanup/capture.mjs b/docs/ui-cleanup/capture.mjs new file mode 100644 index 0000000..ce8bb62 --- /dev/null +++ b/docs/ui-cleanup/capture.mjs @@ -0,0 +1,148 @@ +import fs from 'node:fs/promises'; +import path from 'node:path'; +import { fileURLToPath, pathToFileURL } from 'node:url'; +const docsDir = path.dirname(fileURLToPath(import.meta.url)); +const repoDir = path.resolve(docsDir, '../..'); +const playwrightModule = process.env.PLAYWRIGHT_MODULE ?? path.join(repoDir, 'node_modules/playwright/index.mjs'); +const { chromium } = await import(pathToFileURL(playwrightModule).href); + +const now = '2026-09-29T14:00:00.000Z'; +const events = [ + ['e1','project.planner_message_added','project','proj-atlas',{activity:{summary:'Planner outlined a safe approach for the API retry flow.'}}], + ['e2','run.created','run','run-active',{activity:{summary:'Started Worker implementation for bounded retries.'}}], + ['e3','controller.started','run','run-active',{activity:{summary:'Orchestrator is coordinating validation and review.'}}], + ['e4','worker.completed','run','run-active',{activity:{summary:'Worker updated retry handling and added coverage.'}}], + ['e5','run.validation_failed','run','run-failed',{activity:{summary:'Typecheck passed; API contract check failed on a missing timeout guard.'}}], + ['e6','run.awaiting_approval','run','run-approval',{activity:{summary:'Reviewer recommends the verified result. Human approval is required.'}}], +].map(([id,type,entityType,entityId,extra],i)=>({id,type,entityType,entityId,at:`2026-09-29T13:${String(54+i).padStart(2,'0')}:00.000Z`,...extra})); +const baseRun = (id,status,phase)=>({id,status,createdAt:now,updatedAt:now,pinnedBaseCommit:'3b8f4c210a7751519cb06413aa4a5190bc4c4f2e',workspaceId:`workspace-${id}`,controller:{startedAt:now,phase,active:phase!=='stopped'&&phase!=='awaiting_approval',budgets:{roleTurns:{planner:3,orchestrator:3,worker:2,reviewer:2},workerAttempts:2}},assignments:[{id:id==='run-active'?'orchestrator-active':`orchestrator-${id}`,roleId:'orchestrator',status:'succeeded',createdAt:now,requestedConfig:{harnessId:'codex-cli',model:'gpt-5'},result:'Plan is ready; run focused typecheck and retry contract checks.'},{id:id==='run-active'?'worker-active':`worker-${id}`,roleId:'worker',status:'succeeded',createdAt:now,requestedConfig:{harnessId:'claude-code',model:'claude-sonnet-4'}}],guidance:[{id:`guidance-${id}`,text:'Keep retries bounded and preserve the original error context.',status:'applied',createdAt:now}],usage:{inputTokens:18240,outputTokens:2710,thinkingTokens:5200,cachedInputTokens:8064,runtimeMs:98400,requestCount:7,measured:true}}); +const evidence=(id)=>({provenance:'recorded_replay',workerAssignmentId:`worker-${id}`,workspaceId:`workspace-${id}`,responseId:`response-${id}`,requestedModel:'claude-sonnet-4',actualModel:'claude-sonnet-4',actualModelStatus:'observed',pinnedBaseCommit:'3b8f4c210a7751519cb06413aa4a5190bc4c4f2e',completeSnapshot:{reportedComplete:true,reportedErrors:0,entryCount:38},scopeVerified:true,allowedScope:['src/retry.ts','tests/retry.test.ts'],changes:[{path:'src/retry.ts',kind:'modified',summary:'Bound retry attempts and keep the upstream error for diagnostics.'},{path:'tests/retry.test.ts',kind:'added',summary:'Cover backoff, timeout, and exhausted retries.'}],reviewDiff:'diff --git a/src/retry.ts b/src/retry.ts\n+const maxAttempts = Math.min(config.maxAttempts, 4);\n+if (signal.aborted) throw signal.reason;'}); +const validation=(passed)=>({id:passed?'validation-ok':'validation-failed',status:passed?'passed':'failed',passed,checks:[{name:'TypeScript',passed:true,details:'No type errors.'},{name:'API contract',passed,details:passed?'Retry budget and timeout behavior match the contract.':'Expected timeout guard when the request is aborted.'},{name:'Unit tests',passed,details:passed?'42 tests passed.':'41 passed, 1 failed.'}],observations:[{name:'TypeScript',command:'pnpm',args:['typecheck'],exitCode:0,timedOut:false,output:'Typecheck completed with no errors.',passed:true},{name:'API contract',command:'pnpm',args:['test','--','retry'],exitCode:passed?0:1,timedOut:false,output:passed?'42 tests passed.':'Expected request abort to stop retry scheduling.\n\n1 test failed; 41 passed.',passed}],resultGate:{passed,reason:passed?'All configured checks passed.':'API contract check failed.'},policy:{requireAllChecksPass:true,configuredCheckCount:3},createdAt:now}); +const tasks=[ +{id:'task-idle',title:'Document retry behavior',goal:'Clarify retries, timeout handling, and operational limits.',suggestedAllowedPaths:['docs/api/retries.md'],validationCriteria:['Document the maximum attempt count','Explain timeout and cancellation behavior'],status:'ready',runs:[]}, +{id:'task-active',title:'Bound API retries safely',goal:'Limit retries and preserve request cancellation behavior.',suggestedAllowedPaths:['src/retry.ts','tests/retry.test.ts'],validationCriteria:['Retry count is bounded','Abort signals stop retries','Existing error context is retained'],status:'in progress',runs:[{...baseRun('run-active','in_progress','validating'),validationProgress:{attemptId:'validation-active',startedAt:'2026-09-29T13:58:00.000Z',checks:[{name:'TypeScript',command:'pnpm',args:['typecheck'],status:'passed',output:'Typecheck completed with no errors.',outputTruncated:false,startedAt:'2026-09-29T13:58:00.000Z',finishedAt:'2026-09-29T13:58:49.000Z',elapsedMs:49000,exitCode:0},{name:'API contract',command:'pnpm',args:['test','--','retry'],status:'running',output:'Running focused timeout and cancellation cases…',outputTruncated:false,startedAt:'2026-09-29T13:58:00.000Z',elapsedMs:51000},{name:'Unit tests',command:'pnpm',args:['test'],status:'queued',output:'',outputTruncated:false}]},workerProposal:{id:'proposal-active',status:'dispatched',text:'Add a bounded retry policy with abort-aware backoff and focused tests.',orchestratorAssignmentId:'orchestrator-active',workerAssignmentId:'worker-active',createdAt:now},workerEvidence:evidence('active') }]}, +{id:'task-failed',title:'Add request timeout guard',goal:'Stop retry scheduling when a request times out or is cancelled.',suggestedAllowedPaths:['src/retry.ts','tests/retry.test.ts'],validationCriteria:['Timeout cancels pending retries','Failure is reported clearly'],status:'failed',runs:[{...baseRun('run-failed','failed','stopped'),workerEvidence:evidence('failed'),validation:validation(false)}]}, +{id:'task-approval',title:'Preserve upstream error details',goal:'Keep useful upstream diagnostics through retry exhaustion.',suggestedAllowedPaths:['src/retry.ts','tests/retry.test.ts'],validationCriteria:['Error metadata survives retries','Successful response behavior is unchanged'],status:'awaiting approval',runs:[{...baseRun('run-approval','awaiting_approval','awaiting_approval'),workerEvidence:evidence('approval'),validation:validation(true),reviewerRecommendation:{id:'recommendation-approval',provenance:'simulated_fixture',verdict:'recommend',rationale:'The retry bound, cancellation handling, and error context are correct and the configured checks passed.',createdAt:now}}]}, +]; +const streamEvents=[{id:'e7',type:'assignment.progress',entityType:'assignment',entityId:'worker-active',at:'2026-09-29T13:58:10.000Z',data:{assignmentId:'worker-active',roleId:'worker',model:'claude-sonnet-4',activity:{summary:'Added an abort-aware retry limit; preserving the existing error context.'}}},{id:'e8',type:'response.activity',entityType:'assignment',entityId:'worker-active',at:'2026-09-29T13:58:42.000Z',data:{assignmentId:'worker-active',roleId:'worker',model:'claude-sonnet-4',response:{activity:{summary:'Checking cancellation behavior and the focused retry tests.'}}}},{id:'e9',type:'assignment.progress',entityType:'assignment',entityId:'orchestrator-active',at:'2026-09-29T13:57:10.000Z',data:{assignmentId:'orchestrator-active',roleId:'orchestrator',model:'gpt-5',activity:{summary:'Coordinating the bounded retry implementation and its checks.'}}}]; +const state={projects:[{id:'proj-atlas',name:'Atlas API',repoPath:'/workspace/atlas-api',status:'ready',plannerTurnCount:4,plannerMessages:[{id:'pm1',role:'user',text:'Improve retry reliability while preserving request cancellation.',createdAt:'2026-09-29T13:50:00Z'},{id:'pm2',role:'planner',text:'I split the work into retry limits, timeout handling, and user-facing diagnostics.',createdAt:'2026-09-29T13:51:00Z'}],plannerAssignments:[{id:'planner-assignment',roleId:'planner',status:'succeeded',createdAt:'2026-09-29T13:50:00Z',requestedConfig:{harnessId:'claude-code',model:'claude-sonnet-4'},result:'Split the retry reliability work into bounded attempts, timeout handling, and diagnostics.'}],usage:{inputTokens:32400,outputTokens:6100,totalTokens:38500,thinkingTokens:9200,cachedInputTokens:12000,runtimeMs:184000,requestCount:15,measured:true},tasks}],roles:[{id:'planner',name:'Planner',enabled:true},{id:'orchestrator',name:'Orchestrator',enabled:true},{id:'worker',name:'Worker',enabled:true},{id:'reviewer',name:'Reviewer',enabled:true}],events:[...events,...streamEvents]}; +const github={available:true,remoteUrl:'https://github.com/acme/atlas-api',repository:'acme/atlas-api',account:'alex-dev',message:'No pull request is linked to this result branch.',taskBranch:undefined,taskCommit:undefined,remoteBranchSha:null,remoteBranchStatus:'missing'}; +const systemChrome=process.env.CHROME_PATH??(await fs.access('/usr/bin/google-chrome').then(()=>'/usr/bin/google-chrome').catch(()=>undefined)); +const browser=await chromium.launch({headless:true, ...(systemChrome?{executablePath:systemChrome}:{}), args:['--no-sandbox']}); +const baseUrl=process.env.BASE_URL??'http://127.0.0.1:5173/'; +const out=process.env.SCREEN_DIR??path.join(docsDir,'before'); +const metricsPath=process.env.METRICS_PATH??'/tmp/foreman-ui-cleanup/metrics.jsonl'; +await fs.mkdir(out,{recursive:true});await fs.mkdir(path.dirname(metricsPath),{recursive:true}); +const captureScreenshots=process.env.CAPTURE_SCREENSHOTS!=='0'; +const widths=(process.env.WIDTHS??'1024,1440,1920').split(',').map(Number); +const themes=(process.env.THEMES??'dark,light').split(','); +const scenarios=[['idle','Document retry behavior'],['active','Bound API retries safely'],['failed','Add request timeout guard'],['approval','Preserve upstream error details']]; +const selectedScenarios=process.env.STATES?scenarios.filter(([key])=>process.env.STATES.split(',').includes(key)):scenarios; +for(const width of widths){ + for(const theme of themes){ + for(const [key,title] of selectedScenarios){ + const context=await browser.newContext({viewport:{width,height:1050},deviceScaleFactor:1}); + const page=await context.newPage(); const apiCalls=[]; + const pageErrors=[];page.on('pageerror',error=>pageErrors.push(error.message)); + let githubMode='base'; + const resultCommit='c7a30d4f33b2e89b66dc0284f1aee75fc12a8b55'; + const fixtureGithub=()=>{ + const result={...github}; + if(githubMode==='base') return result; + result.taskBranch='foreman/task-preserve-upstream-error-details'; result.taskCommit=resultCommit; + if(githubMode==='unpromoted-matching'){result.remoteBranchStatus='matching';result.remoteBranchSha=resultCommit;return result;} + if(githubMode==='promoted-missing'){result.remoteBranchStatus='missing';result.remoteBranchSha=null;return result;} + if(githubMode==='promoted-different'){result.remoteBranchStatus='different';result.remoteBranchSha='d34db33fd34db33fd34db33fd34db33fd34db33f';return result;} + result.remoteBranchStatus='matching';result.remoteBranchSha=resultCommit;return result; + }; + await page.addInitScript((theme)=>{localStorage.setItem('foreman-theme',theme);},theme); + await page.route('**/api/**',async route=>{ + const req=route.request(), url=new URL(req.url()), method=req.method(), path=url.pathname; apiCalls.push(`${method} ${path}`); + if(path==='/api/events') return route.fulfill({status:200,headers:{'content-type':'text/event-stream','cache-control':'no-cache'},body:'data: {"type":"fixture.ready"}\n\n'}); + if(path==='/api/state') { + const snapshot=structuredClone(state); + if(githubMode.startsWith('promoted-')){ + const run=snapshot.projects[0].tasks.find(task=>task.id==='task-approval').runs[0]; + run.status='completed'; + run.approval={id:'approval-approval',approved:true,decision:'approved',evidenceCommit:run.pinnedBaseCommit,evidenceDigest:'0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef',rationale:'Approved deterministic browser fixture.',createdAt:now}; + run.promotion={status:'applied',resultCommit:resultCommit,destinationBranch:'foreman/task-preserve-upstream-error-details',evidenceDigest:'0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef',updatedAt:now}; + } + return route.fulfill({status:200,contentType:'application/json',body:JSON.stringify(snapshot)}); + } + if(path==='/api/status') return route.fulfill({status:200,contentType:'application/json',body:JSON.stringify({uhp:{status:'ready',configured:true},memory:{status:'ready',configured:true}})}); + if(path==='/api/runs/run-approval/decision') return route.fulfill({status:200,contentType:'application/json',body:JSON.stringify({runId:'run-approval',evidenceDigest:'0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef',pinnedBaseCommit:'3b8f4c210a7751519cb06413aa4a5190bc4c4f2e',workerResponseId:'response-approval',validationId:'validation-ok',recommendationId:'recommendation-approval'})}); + if(path==='/api/projects/proj-atlas/usage') return route.fulfill({status:200,contentType:'application/json',body:JSON.stringify({harnesses:[{harnessId:'claude-code',status:'ready',windows:{fiveHour:{status:'available',usedPercent:35,remainingPercent:65,resetAt:'2026-09-29T17:00:00.000Z',observedAt:now},weekly:{status:'available',usedPercent:42,remainingPercent:58,resetAt:'2026-10-05T00:00:00.000Z',observedAt:now}}},{harnessId:'codex-cli',status:'ready',windows:{fiveHour:{status:'available',usedPercent:58,remainingPercent:42,resetAt:'2026-09-29T17:30:00.000Z'},weekly:{status:'available',usedPercent:27,remainingPercent:73,resetAt:'2026-10-05T00:00:00.000Z'}}}]})}); + if(path==='/api/tasks/task-idle/start-preview') return route.fulfill({status:200,contentType:'application/json',body:JSON.stringify({taskId:'task-idle',requiresExplicitBase:false,canStart:true,scope:['docs/api/retries.md'],validationCriteria:['Document the maximum attempt count','Explain timeout and cancellation behavior'],validationCommands:[{name:'Docs lint',command:'pnpm',args:['docs:check']}],budgets:{roleTurns:{planner:3,orchestrator:3,worker:2,reviewer:2},workerAttempts:2},currentHead:'3b8f4c210a7751519cb06413aa4a5190bc4c4f2e'})}); + const m=path.match(/^\/api\/runs\/([^/]+)\/github$/); + if(m) return route.fulfill({status:200,contentType:'application/json',body:JSON.stringify(fixtureGithub())}); + if(method!=='GET'&&method!=='HEAD') {apiCalls.push(`WRITE ${method} ${path}`);return route.fulfill({status:200,contentType:'application/json',body:'{}'});} + return route.fulfill({status:404,contentType:'application/json',body:JSON.stringify({error:`Unstubbed fixture endpoint ${path}`})}); + }); + await page.goto(baseUrl); + const initialTheme=await page.evaluate(()=>document.documentElement.dataset.theme); + const expectedThemeToggle=theme==='light'?'Switch to dark theme':'Switch to light theme'; + const actualThemeToggle=await page.getByRole('button',{name:/Switch to (dark|light) theme/}).getAttribute('aria-label'); + if(initialTheme!==theme||actualThemeToggle!==expectedThemeToggle)throw new Error(`Theme initialization failed: wanted ${theme}/${expectedThemeToggle}, got ${initialTheme}/${actualThemeToggle}`); + await page.addStyleTag({content:'*,*::before,*::after{animation:none!important;transition:none!important;scroll-behavior:auto!important;caret-color:transparent!important}'}); + await page.locator('.usage-dock-more').evaluate(el=>{el.open=true}); + await page.getByRole('button',{name:title, exact:false}).first().click(); + await page.waitForTimeout(350); + if(key!=='idle') await page.getByRole('button',{name:/Run Awaiting Approval|Run In Progress|Run Failed|Run/}).first().click().catch(()=>{}); + await page.waitForTimeout(250); + if(key==='failed') {const summary=page.locator('.validation-progress');if(await summary.count())await summary.scrollIntoViewIfNeeded();const failure=page.locator('.validation-progress details').filter({hasText:'API contract'}).first();if(await failure.count()&&!await failure.evaluate(el=>el.open))await failure.locator('summary').click();} + if(key==='approval') {const panel=page.locator('.decision-panel').first();if(await panel.count())await panel.scrollIntoViewIfNeeded();if(captureScreenshots&&width===1440&&await panel.count())await page.screenshot({path:`${out}/approval-${theme}-${width}-review.jpeg`,type:'jpeg',quality:80,fullPage:false});const human=page.locator('.evidence-block').filter({has:page.locator('summary b', {hasText:'Human decision'})}).first();if(await human.count()){await human.locator('summary').click();const decision=human.locator('.decision-actions').first();if(await decision.count())await decision.scrollIntoViewIfNeeded();}} + // Confirm fixture is stable and capture the complete app plus dedicated scroll panels. + const filename=`${key}-${theme}-${width}.jpeg`; + if(captureScreenshots)await page.screenshot({path:`${out}/${filename}`,type:'jpeg',quality:80,fullPage:true}); + const overflow=await page.evaluate(()=>{const names=['.layout','.tree-content','.center','.inspector-scroll','.github-scroll','.usage-dock'];return {doc:document.documentElement.scrollWidth>document.documentElement.clientWidth,body:document.body.scrollWidth>document.body.clientWidth,scrollWidth:document.documentElement.scrollWidth,clientWidth:document.documentElement.clientWidth,containers:Object.fromEntries(names.map(name=>{const el=document.querySelector(name);if(!el)return[name,null];const box=el.getBoundingClientRect();return[name,{clientWidth:el.clientWidth,scrollWidth:el.scrollWidth,clientHeight:el.clientHeight,scrollHeight:el.scrollHeight,horizontalOverflow:el.scrollWidth>el.clientWidth,verticalOverflow:el.scrollHeight>el.clientHeight,visible:box.width>0&&box.height>0}]}))}}); + if(width===1440){ + if(captureScreenshots)await page.screenshot({path:`${out}/${key}-${theme}-${width}-viewport.jpeg`,type:'jpeg',quality:80,fullPage:false}); + if(captureScreenshots&&theme==='dark'&&key==='failed') {const el=page.locator('.center').first();if(await el.count())await el.screenshot({path:`${out}/failed-dark-${width}-center.jpeg`,type:'jpeg',quality:80});} + if(captureScreenshots&&theme==='dark'&&key==='approval') {const el=page.locator('.center').first();if(await el.count())await el.screenshot({path:`${out}/approval-dark-${width}-center.jpeg`,type:'jpeg',quality:80});const aside=page.locator('.github-card').first();if(await aside.count())await aside.screenshot({path:`${out}/approval-dark-${width}-github.jpeg`,type:'jpeg',quality:80});} + } + if(pageErrors.length)throw new Error(`Page errors in ${key}/${theme}/${width}: ${pageErrors.join(' | ')}`); + const unexpectedWrites=apiCalls.filter(call=>call.startsWith('WRITE')); + if(unexpectedWrites.length)throw new Error(`Unexpected fixture write during ${key}/${theme}/${width}: ${unexpectedWrites.join(', ')}`); + await fs.appendFile(metricsPath,JSON.stringify({key,theme,width,overflow,calls:apiCalls,pageErrors,initialTheme,themeToggle:actualThemeToggle})+'\n'); + if(process.env.RUN_INTERACTION_CHECKS==='1'&&width===1440&&theme==='dark'&&key==='approval'){ + const gateResults=[]; + const clickOpenPr=async(mode,expectedDisabled,reasonFragment)=>{ + githubMode=mode;await page.goto(baseUrl);await page.addStyleTag({content:'*,*::before,*::after{animation:none!important;transition:none!important;scroll-behavior:auto!important}'}); + await page.getByRole('button',{name:'Preserve upstream error details',exact:false}).first().click();await page.waitForTimeout(150); + await page.getByRole('button',{name:/Run Awaiting Approval|Run Completed|Run/}).first().click().catch(()=>{}); + await page.waitForFunction(()=>document.querySelector('.github-scroll')?.innerText.includes('Open PR')); + const button=page.getByRole('button',{name:'Open PR',exact:true});await button.waitFor({state:'visible'}); + const disabled=await button.isDisabled(); + const reason=await page.locator('#github-open-pr-reason').textContent().catch(()=>null); + let clickOutcome=''; + if(expectedDisabled){try{await button.click({timeout:500});clickOutcome='click unexpectedly succeeded';}catch{clickOutcome='browser refused disabled click';}} + else {await button.click();await page.getByRole('dialog').waitFor({state:'visible'});clickOutcome='confirmation dialog opened';} + const dialog=await page.getByRole('dialog').count()>0; + if(disabled!==expectedDisabled)throw new Error(`${mode}: expected disabled=${expectedDisabled}, received ${disabled}`); + if(reasonFragment&&!(reason??'').includes(reasonFragment))throw new Error(`${mode}: expected reason containing ${reasonFragment}; received ${reason}`); + if(expectedDisabled&&dialog)throw new Error(`${mode}: disabled Open PR opened a confirmation dialog`); + const writes=apiCalls.filter(call=>call.startsWith('WRITE')); + if(writes.length)throw new Error(`${mode}: unexpected fixture write ${writes.join(', ')}`); + gateResults.push({scenario:mode,disabled,reason,clickOutcome,dialog,writes}); + }; + await clickOpenPr('unpromoted-matching',true,'Promote the approved result'); + await clickOpenPr('promoted-missing',true,'Push the promoted result branch'); + await clickOpenPr('promoted-different',true,'remote branch differs'); + await clickOpenPr('promoted-matching',false,undefined); + const gatePath=process.env.GATE_RESULTS_PATH??'/tmp/foreman-ui-cleanup/pr-gate-results.json';await fs.mkdir(path.dirname(gatePath),{recursive:true});await fs.writeFile(gatePath,JSON.stringify(gateResults,null,2)+'\n'); + githubMode='base';await page.goto(baseUrl);await page.addStyleTag({content:'*,*::before,*::after{animation:none!important;transition:none!important;scroll-behavior:auto!important}'});await page.keyboard.press('Tab'); + const focusProbe=await page.evaluate(()=>{const el=document.activeElement;if(!el)return null;const style=getComputedStyle(el);return {tag:el.tagName,ariaLabel:el.getAttribute('aria-label'),text:el.textContent?.trim().slice(0,80),outlineStyle:style.outlineStyle,outlineWidth:style.outlineWidth,outlineColor:style.outlineColor,focusVisible:el.matches(':focus-visible')}}); + const focusPath=process.env.FOCUS_RESULTS_PATH?.replace(/\.json$/,`-${theme}.json`)??`/tmp/foreman-ui-cleanup/focus-${theme}.json`;await fs.mkdir(path.dirname(focusPath),{recursive:true}); + await fs.writeFile(focusPath,JSON.stringify({theme,width,focusProbe},null,2)+'\n'); + } + if(width===1440&&theme==='light'&&key==='approval'){ + await page.goto(baseUrl);await page.keyboard.press('Tab'); + const focusProbe=await page.evaluate(()=>{const el=document.activeElement;if(!el)return null;const style=getComputedStyle(el);return {tag:el.tagName,ariaLabel:el.getAttribute('aria-label'),text:el.textContent?.trim().slice(0,80),outlineStyle:style.outlineStyle,outlineWidth:style.outlineWidth,outlineColor:style.outlineColor,focusVisible:el.matches(':focus-visible')}}); + const focusPath=process.env.FOCUS_RESULTS_PATH?.replace(/\.json$/,`-${theme}.json`)??`/tmp/foreman-ui-cleanup/focus-${theme}.json`;await fs.mkdir(path.dirname(focusPath),{recursive:true}); + await fs.writeFile(focusPath,JSON.stringify({theme,width,focusProbe},null,2)+'\n'); + } + await context.close(); + } + } +} +await browser.close(); diff --git a/docs/ui-cleanup/checks.json b/docs/ui-cleanup/checks.json new file mode 100644 index 0000000..334869b --- /dev/null +++ b/docs/ui-cleanup/checks.json @@ -0,0 +1,3329 @@ +{ + "baselineCommit": "b826f88", + "afterCommit": "1655af6", + "matrixSummary": { + "cases": 48, + "perPhase": 24, + "states": [ + "idle", + "active", + "failed", + "approval" + ], + "themes": [ + "dark", + "light" + ], + "widths": [ + 1024, + 1440, + 1920 + ], + "allMatchRequestedTheme": true, + "pageErrors": 0, + "apiWrites": 0, + "pageHorizontalOverflowCases": 0, + "containerHorizontalOverflowCases": 0 + }, + "cases": [ + { + "phase": "before", + "state": "active", + "theme": "dark", + "width": 1024, + "actualTheme": "dark", + "themeToggle": "Switch to light theme", + "pageErrors": [], + "apiWrites": [], + "pageHorizontalOverflow": false, + "containers": { + ".layout": { + "clientWidth": 992, + "scrollWidth": 992, + "clientHeight": 954, + "scrollHeight": 954, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".tree-content": { + "clientWidth": 188, + "scrollWidth": 188, + "clientHeight": 561, + "scrollHeight": 561, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".center": { + "clientWidth": 520, + "scrollWidth": 520, + "clientHeight": 954, + "scrollHeight": 2182, + "horizontalOverflow": false, + "verticalOverflow": true, + "visible": true + }, + ".inspector-scroll": { + "clientWidth": 250, + "scrollWidth": 250, + "clientHeight": 278, + "scrollHeight": 304, + "horizontalOverflow": false, + "verticalOverflow": true, + "visible": true + }, + ".github-scroll": { + "clientWidth": 250, + "scrollWidth": 250, + "clientHeight": 544, + "scrollHeight": 544, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".usage-dock": { + "clientWidth": 188, + "scrollWidth": 188, + "clientHeight": 335, + "scrollHeight": 335, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + } + } + }, + { + "phase": "before", + "state": "active", + "theme": "dark", + "width": 1440, + "actualTheme": "dark", + "themeToggle": "Switch to light theme", + "pageErrors": [], + "apiWrites": [], + "pageHorizontalOverflow": false, + "containers": { + ".layout": { + "clientWidth": 1408, + "scrollWidth": 1408, + "clientHeight": 954, + "scrollHeight": 954, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".tree-content": { + "clientWidth": 246, + "scrollWidth": 246, + "clientHeight": 591, + "scrollHeight": 591, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".center": { + "clientWidth": 832, + "scrollWidth": 832, + "clientHeight": 954, + "scrollHeight": 1861, + "horizontalOverflow": false, + "verticalOverflow": true, + "visible": true + }, + ".inspector-scroll": { + "clientWidth": 296, + "scrollWidth": 296, + "clientHeight": 225, + "scrollHeight": 225, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".github-scroll": { + "clientWidth": 296, + "scrollWidth": 296, + "clientHeight": 598, + "scrollHeight": 598, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".usage-dock": { + "clientWidth": 246, + "scrollWidth": 246, + "clientHeight": 305, + "scrollHeight": 305, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + } + } + }, + { + "phase": "before", + "state": "active", + "theme": "dark", + "width": 1920, + "actualTheme": "dark", + "themeToggle": "Switch to light theme", + "pageErrors": [], + "apiWrites": [], + "pageHorizontalOverflow": false, + "containers": { + ".layout": { + "clientWidth": 1888, + "scrollWidth": 1888, + "clientHeight": 954, + "scrollHeight": 954, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".tree-content": { + "clientWidth": 246, + "scrollWidth": 246, + "clientHeight": 591, + "scrollHeight": 591, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".center": { + "clientWidth": 1214, + "scrollWidth": 1214, + "clientHeight": 954, + "scrollHeight": 1849, + "horizontalOverflow": false, + "verticalOverflow": true, + "visible": true + }, + ".inspector-scroll": { + "clientWidth": 394, + "scrollWidth": 394, + "clientHeight": 210, + "scrollHeight": 210, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".github-scroll": { + "clientWidth": 394, + "scrollWidth": 394, + "clientHeight": 613, + "scrollHeight": 613, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".usage-dock": { + "clientWidth": 246, + "scrollWidth": 246, + "clientHeight": 305, + "scrollHeight": 305, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + } + } + }, + { + "phase": "before", + "state": "active", + "theme": "light", + "width": 1024, + "actualTheme": "light", + "themeToggle": "Switch to dark theme", + "pageErrors": [], + "apiWrites": [], + "pageHorizontalOverflow": false, + "containers": { + ".layout": { + "clientWidth": 992, + "scrollWidth": 992, + "clientHeight": 954, + "scrollHeight": 954, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".tree-content": { + "clientWidth": 188, + "scrollWidth": 188, + "clientHeight": 561, + "scrollHeight": 561, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".center": { + "clientWidth": 520, + "scrollWidth": 520, + "clientHeight": 954, + "scrollHeight": 2182, + "horizontalOverflow": false, + "verticalOverflow": true, + "visible": true + }, + ".inspector-scroll": { + "clientWidth": 250, + "scrollWidth": 250, + "clientHeight": 278, + "scrollHeight": 304, + "horizontalOverflow": false, + "verticalOverflow": true, + "visible": true + }, + ".github-scroll": { + "clientWidth": 250, + "scrollWidth": 250, + "clientHeight": 544, + "scrollHeight": 544, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".usage-dock": { + "clientWidth": 188, + "scrollWidth": 188, + "clientHeight": 335, + "scrollHeight": 335, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + } + } + }, + { + "phase": "before", + "state": "active", + "theme": "light", + "width": 1440, + "actualTheme": "light", + "themeToggle": "Switch to dark theme", + "pageErrors": [], + "apiWrites": [], + "pageHorizontalOverflow": false, + "containers": { + ".layout": { + "clientWidth": 1408, + "scrollWidth": 1408, + "clientHeight": 954, + "scrollHeight": 954, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".tree-content": { + "clientWidth": 246, + "scrollWidth": 246, + "clientHeight": 591, + "scrollHeight": 591, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".center": { + "clientWidth": 832, + "scrollWidth": 832, + "clientHeight": 954, + "scrollHeight": 1861, + "horizontalOverflow": false, + "verticalOverflow": true, + "visible": true + }, + ".inspector-scroll": { + "clientWidth": 296, + "scrollWidth": 296, + "clientHeight": 225, + "scrollHeight": 225, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".github-scroll": { + "clientWidth": 296, + "scrollWidth": 296, + "clientHeight": 598, + "scrollHeight": 598, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".usage-dock": { + "clientWidth": 246, + "scrollWidth": 246, + "clientHeight": 305, + "scrollHeight": 305, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + } + } + }, + { + "phase": "before", + "state": "active", + "theme": "light", + "width": 1920, + "actualTheme": "light", + "themeToggle": "Switch to dark theme", + "pageErrors": [], + "apiWrites": [], + "pageHorizontalOverflow": false, + "containers": { + ".layout": { + "clientWidth": 1888, + "scrollWidth": 1888, + "clientHeight": 954, + "scrollHeight": 954, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".tree-content": { + "clientWidth": 246, + "scrollWidth": 246, + "clientHeight": 591, + "scrollHeight": 591, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".center": { + "clientWidth": 1214, + "scrollWidth": 1214, + "clientHeight": 954, + "scrollHeight": 1849, + "horizontalOverflow": false, + "verticalOverflow": true, + "visible": true + }, + ".inspector-scroll": { + "clientWidth": 394, + "scrollWidth": 394, + "clientHeight": 210, + "scrollHeight": 210, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".github-scroll": { + "clientWidth": 394, + "scrollWidth": 394, + "clientHeight": 613, + "scrollHeight": 613, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".usage-dock": { + "clientWidth": 246, + "scrollWidth": 246, + "clientHeight": 305, + "scrollHeight": 305, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + } + } + }, + { + "phase": "before", + "state": "approval", + "theme": "dark", + "width": 1024, + "actualTheme": "dark", + "themeToggle": "Switch to light theme", + "pageErrors": [], + "apiWrites": [], + "pageHorizontalOverflow": false, + "containers": { + ".layout": { + "clientWidth": 992, + "scrollWidth": 992, + "clientHeight": 954, + "scrollHeight": 954, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".tree-content": { + "clientWidth": 188, + "scrollWidth": 188, + "clientHeight": 561, + "scrollHeight": 561, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".center": { + "clientWidth": 520, + "scrollWidth": 520, + "clientHeight": 954, + "scrollHeight": 2275, + "horizontalOverflow": false, + "verticalOverflow": true, + "visible": true + }, + ".inspector-scroll": { + "clientWidth": 250, + "scrollWidth": 250, + "clientHeight": 64, + "scrollHeight": 64, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".github-scroll": { + "clientWidth": 250, + "scrollWidth": 250, + "clientHeight": 759, + "scrollHeight": 759, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".usage-dock": { + "clientWidth": 188, + "scrollWidth": 188, + "clientHeight": 335, + "scrollHeight": 335, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + } + } + }, + { + "phase": "before", + "state": "approval", + "theme": "dark", + "width": 1440, + "actualTheme": "dark", + "themeToggle": "Switch to light theme", + "pageErrors": [], + "apiWrites": [], + "pageHorizontalOverflow": false, + "containers": { + ".layout": { + "clientWidth": 1408, + "scrollWidth": 1408, + "clientHeight": 954, + "scrollHeight": 954, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".tree-content": { + "clientWidth": 246, + "scrollWidth": 246, + "clientHeight": 591, + "scrollHeight": 591, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".center": { + "clientWidth": 832, + "scrollWidth": 832, + "clientHeight": 954, + "scrollHeight": 1915, + "horizontalOverflow": false, + "verticalOverflow": true, + "visible": true + }, + ".inspector-scroll": { + "clientWidth": 296, + "scrollWidth": 296, + "clientHeight": 64, + "scrollHeight": 64, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".github-scroll": { + "clientWidth": 296, + "scrollWidth": 296, + "clientHeight": 759, + "scrollHeight": 759, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".usage-dock": { + "clientWidth": 246, + "scrollWidth": 246, + "clientHeight": 305, + "scrollHeight": 305, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + } + } + }, + { + "phase": "before", + "state": "approval", + "theme": "dark", + "width": 1920, + "actualTheme": "dark", + "themeToggle": "Switch to light theme", + "pageErrors": [], + "apiWrites": [], + "pageHorizontalOverflow": false, + "containers": { + ".layout": { + "clientWidth": 1888, + "scrollWidth": 1888, + "clientHeight": 954, + "scrollHeight": 954, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".tree-content": { + "clientWidth": 246, + "scrollWidth": 246, + "clientHeight": 591, + "scrollHeight": 591, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".center": { + "clientWidth": 1214, + "scrollWidth": 1214, + "clientHeight": 954, + "scrollHeight": 1865, + "horizontalOverflow": false, + "verticalOverflow": true, + "visible": true + }, + ".inspector-scroll": { + "clientWidth": 394, + "scrollWidth": 394, + "clientHeight": 46, + "scrollHeight": 46, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".github-scroll": { + "clientWidth": 394, + "scrollWidth": 394, + "clientHeight": 777, + "scrollHeight": 777, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".usage-dock": { + "clientWidth": 246, + "scrollWidth": 246, + "clientHeight": 305, + "scrollHeight": 305, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + } + } + }, + { + "phase": "before", + "state": "approval", + "theme": "light", + "width": 1024, + "actualTheme": "light", + "themeToggle": "Switch to dark theme", + "pageErrors": [], + "apiWrites": [], + "pageHorizontalOverflow": false, + "containers": { + ".layout": { + "clientWidth": 992, + "scrollWidth": 992, + "clientHeight": 954, + "scrollHeight": 954, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".tree-content": { + "clientWidth": 188, + "scrollWidth": 188, + "clientHeight": 561, + "scrollHeight": 561, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".center": { + "clientWidth": 520, + "scrollWidth": 520, + "clientHeight": 954, + "scrollHeight": 2275, + "horizontalOverflow": false, + "verticalOverflow": true, + "visible": true + }, + ".inspector-scroll": { + "clientWidth": 250, + "scrollWidth": 250, + "clientHeight": 64, + "scrollHeight": 64, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".github-scroll": { + "clientWidth": 250, + "scrollWidth": 250, + "clientHeight": 759, + "scrollHeight": 759, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".usage-dock": { + "clientWidth": 188, + "scrollWidth": 188, + "clientHeight": 335, + "scrollHeight": 335, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + } + } + }, + { + "phase": "before", + "state": "approval", + "theme": "light", + "width": 1440, + "actualTheme": "light", + "themeToggle": "Switch to dark theme", + "pageErrors": [], + "apiWrites": [], + "pageHorizontalOverflow": false, + "containers": { + ".layout": { + "clientWidth": 1408, + "scrollWidth": 1408, + "clientHeight": 954, + "scrollHeight": 954, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".tree-content": { + "clientWidth": 246, + "scrollWidth": 246, + "clientHeight": 591, + "scrollHeight": 591, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".center": { + "clientWidth": 832, + "scrollWidth": 832, + "clientHeight": 954, + "scrollHeight": 1915, + "horizontalOverflow": false, + "verticalOverflow": true, + "visible": true + }, + ".inspector-scroll": { + "clientWidth": 296, + "scrollWidth": 296, + "clientHeight": 64, + "scrollHeight": 64, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".github-scroll": { + "clientWidth": 296, + "scrollWidth": 296, + "clientHeight": 759, + "scrollHeight": 759, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".usage-dock": { + "clientWidth": 246, + "scrollWidth": 246, + "clientHeight": 305, + "scrollHeight": 305, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + } + } + }, + { + "phase": "before", + "state": "approval", + "theme": "light", + "width": 1920, + "actualTheme": "light", + "themeToggle": "Switch to dark theme", + "pageErrors": [], + "apiWrites": [], + "pageHorizontalOverflow": false, + "containers": { + ".layout": { + "clientWidth": 1888, + "scrollWidth": 1888, + "clientHeight": 954, + "scrollHeight": 954, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".tree-content": { + "clientWidth": 246, + "scrollWidth": 246, + "clientHeight": 591, + "scrollHeight": 591, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".center": { + "clientWidth": 1214, + "scrollWidth": 1214, + "clientHeight": 954, + "scrollHeight": 1865, + "horizontalOverflow": false, + "verticalOverflow": true, + "visible": true + }, + ".inspector-scroll": { + "clientWidth": 394, + "scrollWidth": 394, + "clientHeight": 46, + "scrollHeight": 46, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".github-scroll": { + "clientWidth": 394, + "scrollWidth": 394, + "clientHeight": 777, + "scrollHeight": 777, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".usage-dock": { + "clientWidth": 246, + "scrollWidth": 246, + "clientHeight": 305, + "scrollHeight": 305, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + } + } + }, + { + "phase": "before", + "state": "failed", + "theme": "dark", + "width": 1024, + "actualTheme": "dark", + "themeToggle": "Switch to light theme", + "pageErrors": [], + "apiWrites": [], + "pageHorizontalOverflow": false, + "containers": { + ".layout": { + "clientWidth": 992, + "scrollWidth": 992, + "clientHeight": 954, + "scrollHeight": 954, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".tree-content": { + "clientWidth": 188, + "scrollWidth": 188, + "clientHeight": 561, + "scrollHeight": 561, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".center": { + "clientWidth": 520, + "scrollWidth": 520, + "clientHeight": 954, + "scrollHeight": 2545, + "horizontalOverflow": false, + "verticalOverflow": true, + "visible": true + }, + ".inspector-scroll": { + "clientWidth": 250, + "scrollWidth": 250, + "clientHeight": 64, + "scrollHeight": 64, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".github-scroll": { + "clientWidth": 250, + "scrollWidth": 250, + "clientHeight": 759, + "scrollHeight": 759, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".usage-dock": { + "clientWidth": 188, + "scrollWidth": 188, + "clientHeight": 335, + "scrollHeight": 335, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + } + } + }, + { + "phase": "before", + "state": "failed", + "theme": "dark", + "width": 1440, + "actualTheme": "dark", + "themeToggle": "Switch to light theme", + "pageErrors": [], + "apiWrites": [], + "pageHorizontalOverflow": false, + "containers": { + ".layout": { + "clientWidth": 1408, + "scrollWidth": 1408, + "clientHeight": 954, + "scrollHeight": 954, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".tree-content": { + "clientWidth": 246, + "scrollWidth": 246, + "clientHeight": 591, + "scrollHeight": 591, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".center": { + "clientWidth": 832, + "scrollWidth": 832, + "clientHeight": 954, + "scrollHeight": 2145, + "horizontalOverflow": false, + "verticalOverflow": true, + "visible": true + }, + ".inspector-scroll": { + "clientWidth": 296, + "scrollWidth": 296, + "clientHeight": 64, + "scrollHeight": 64, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".github-scroll": { + "clientWidth": 296, + "scrollWidth": 296, + "clientHeight": 759, + "scrollHeight": 759, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".usage-dock": { + "clientWidth": 246, + "scrollWidth": 246, + "clientHeight": 305, + "scrollHeight": 305, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + } + } + }, + { + "phase": "before", + "state": "failed", + "theme": "dark", + "width": 1920, + "actualTheme": "dark", + "themeToggle": "Switch to light theme", + "pageErrors": [], + "apiWrites": [], + "pageHorizontalOverflow": false, + "containers": { + ".layout": { + "clientWidth": 1888, + "scrollWidth": 1888, + "clientHeight": 954, + "scrollHeight": 954, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".tree-content": { + "clientWidth": 246, + "scrollWidth": 246, + "clientHeight": 591, + "scrollHeight": 591, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".center": { + "clientWidth": 1214, + "scrollWidth": 1214, + "clientHeight": 954, + "scrollHeight": 2074, + "horizontalOverflow": false, + "verticalOverflow": true, + "visible": true + }, + ".inspector-scroll": { + "clientWidth": 394, + "scrollWidth": 394, + "clientHeight": 46, + "scrollHeight": 46, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".github-scroll": { + "clientWidth": 394, + "scrollWidth": 394, + "clientHeight": 777, + "scrollHeight": 777, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".usage-dock": { + "clientWidth": 246, + "scrollWidth": 246, + "clientHeight": 305, + "scrollHeight": 305, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + } + } + }, + { + "phase": "before", + "state": "failed", + "theme": "light", + "width": 1024, + "actualTheme": "light", + "themeToggle": "Switch to dark theme", + "pageErrors": [], + "apiWrites": [], + "pageHorizontalOverflow": false, + "containers": { + ".layout": { + "clientWidth": 992, + "scrollWidth": 992, + "clientHeight": 954, + "scrollHeight": 954, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".tree-content": { + "clientWidth": 188, + "scrollWidth": 188, + "clientHeight": 561, + "scrollHeight": 561, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".center": { + "clientWidth": 520, + "scrollWidth": 520, + "clientHeight": 954, + "scrollHeight": 2545, + "horizontalOverflow": false, + "verticalOverflow": true, + "visible": true + }, + ".inspector-scroll": { + "clientWidth": 250, + "scrollWidth": 250, + "clientHeight": 64, + "scrollHeight": 64, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".github-scroll": { + "clientWidth": 250, + "scrollWidth": 250, + "clientHeight": 759, + "scrollHeight": 759, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".usage-dock": { + "clientWidth": 188, + "scrollWidth": 188, + "clientHeight": 335, + "scrollHeight": 335, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + } + } + }, + { + "phase": "before", + "state": "failed", + "theme": "light", + "width": 1440, + "actualTheme": "light", + "themeToggle": "Switch to dark theme", + "pageErrors": [], + "apiWrites": [], + "pageHorizontalOverflow": false, + "containers": { + ".layout": { + "clientWidth": 1408, + "scrollWidth": 1408, + "clientHeight": 954, + "scrollHeight": 954, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".tree-content": { + "clientWidth": 246, + "scrollWidth": 246, + "clientHeight": 591, + "scrollHeight": 591, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".center": { + "clientWidth": 832, + "scrollWidth": 832, + "clientHeight": 954, + "scrollHeight": 2145, + "horizontalOverflow": false, + "verticalOverflow": true, + "visible": true + }, + ".inspector-scroll": { + "clientWidth": 296, + "scrollWidth": 296, + "clientHeight": 64, + "scrollHeight": 64, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".github-scroll": { + "clientWidth": 296, + "scrollWidth": 296, + "clientHeight": 759, + "scrollHeight": 759, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".usage-dock": { + "clientWidth": 246, + "scrollWidth": 246, + "clientHeight": 305, + "scrollHeight": 305, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + } + } + }, + { + "phase": "before", + "state": "failed", + "theme": "light", + "width": 1920, + "actualTheme": "light", + "themeToggle": "Switch to dark theme", + "pageErrors": [], + "apiWrites": [], + "pageHorizontalOverflow": false, + "containers": { + ".layout": { + "clientWidth": 1888, + "scrollWidth": 1888, + "clientHeight": 954, + "scrollHeight": 954, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".tree-content": { + "clientWidth": 246, + "scrollWidth": 246, + "clientHeight": 591, + "scrollHeight": 591, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".center": { + "clientWidth": 1214, + "scrollWidth": 1214, + "clientHeight": 954, + "scrollHeight": 2074, + "horizontalOverflow": false, + "verticalOverflow": true, + "visible": true + }, + ".inspector-scroll": { + "clientWidth": 394, + "scrollWidth": 394, + "clientHeight": 46, + "scrollHeight": 46, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".github-scroll": { + "clientWidth": 394, + "scrollWidth": 394, + "clientHeight": 777, + "scrollHeight": 777, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".usage-dock": { + "clientWidth": 246, + "scrollWidth": 246, + "clientHeight": 305, + "scrollHeight": 305, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + } + } + }, + { + "phase": "before", + "state": "idle", + "theme": "dark", + "width": 1024, + "actualTheme": "dark", + "themeToggle": "Switch to light theme", + "pageErrors": [], + "apiWrites": [], + "pageHorizontalOverflow": false, + "containers": { + ".layout": { + "clientWidth": 992, + "scrollWidth": 992, + "clientHeight": 954, + "scrollHeight": 954, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".tree-content": { + "clientWidth": 188, + "scrollWidth": 188, + "clientHeight": 591, + "scrollHeight": 591, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".center": { + "clientWidth": 520, + "scrollWidth": 520, + "clientHeight": 954, + "scrollHeight": 1120, + "horizontalOverflow": false, + "verticalOverflow": true, + "visible": true + }, + ".inspector-scroll": { + "clientWidth": 250, + "scrollWidth": 250, + "clientHeight": 64, + "scrollHeight": 64, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".github-scroll": { + "clientWidth": 250, + "scrollWidth": 250, + "clientHeight": 759, + "scrollHeight": 759, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".usage-dock": { + "clientWidth": 188, + "scrollWidth": 188, + "clientHeight": 305, + "scrollHeight": 305, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + } + } + }, + { + "phase": "before", + "state": "idle", + "theme": "dark", + "width": 1440, + "actualTheme": "dark", + "themeToggle": "Switch to light theme", + "pageErrors": [], + "apiWrites": [], + "pageHorizontalOverflow": false, + "containers": { + ".layout": { + "clientWidth": 1408, + "scrollWidth": 1408, + "clientHeight": 954, + "scrollHeight": 954, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".tree-content": { + "clientWidth": 246, + "scrollWidth": 246, + "clientHeight": 606, + "scrollHeight": 606, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".center": { + "clientWidth": 832, + "scrollWidth": 832, + "clientHeight": 954, + "scrollHeight": 1016, + "horizontalOverflow": false, + "verticalOverflow": true, + "visible": true + }, + ".inspector-scroll": { + "clientWidth": 296, + "scrollWidth": 296, + "clientHeight": 64, + "scrollHeight": 64, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".github-scroll": { + "clientWidth": 296, + "scrollWidth": 296, + "clientHeight": 759, + "scrollHeight": 759, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".usage-dock": { + "clientWidth": 246, + "scrollWidth": 246, + "clientHeight": 290, + "scrollHeight": 290, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + } + } + }, + { + "phase": "before", + "state": "idle", + "theme": "dark", + "width": 1920, + "actualTheme": "dark", + "themeToggle": "Switch to light theme", + "pageErrors": [], + "apiWrites": [], + "pageHorizontalOverflow": false, + "containers": { + ".layout": { + "clientWidth": 1888, + "scrollWidth": 1888, + "clientHeight": 954, + "scrollHeight": 954, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".tree-content": { + "clientWidth": 246, + "scrollWidth": 246, + "clientHeight": 606, + "scrollHeight": 606, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".center": { + "clientWidth": 1214, + "scrollWidth": 1214, + "clientHeight": 954, + "scrollHeight": 1016, + "horizontalOverflow": false, + "verticalOverflow": true, + "visible": true + }, + ".inspector-scroll": { + "clientWidth": 394, + "scrollWidth": 394, + "clientHeight": 46, + "scrollHeight": 46, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".github-scroll": { + "clientWidth": 394, + "scrollWidth": 394, + "clientHeight": 777, + "scrollHeight": 777, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".usage-dock": { + "clientWidth": 246, + "scrollWidth": 246, + "clientHeight": 290, + "scrollHeight": 290, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + } + } + }, + { + "phase": "before", + "state": "idle", + "theme": "light", + "width": 1024, + "actualTheme": "light", + "themeToggle": "Switch to dark theme", + "pageErrors": [], + "apiWrites": [], + "pageHorizontalOverflow": false, + "containers": { + ".layout": { + "clientWidth": 992, + "scrollWidth": 992, + "clientHeight": 954, + "scrollHeight": 954, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".tree-content": { + "clientWidth": 188, + "scrollWidth": 188, + "clientHeight": 591, + "scrollHeight": 591, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".center": { + "clientWidth": 520, + "scrollWidth": 520, + "clientHeight": 954, + "scrollHeight": 1120, + "horizontalOverflow": false, + "verticalOverflow": true, + "visible": true + }, + ".inspector-scroll": { + "clientWidth": 250, + "scrollWidth": 250, + "clientHeight": 64, + "scrollHeight": 64, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".github-scroll": { + "clientWidth": 250, + "scrollWidth": 250, + "clientHeight": 759, + "scrollHeight": 759, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".usage-dock": { + "clientWidth": 188, + "scrollWidth": 188, + "clientHeight": 305, + "scrollHeight": 305, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + } + } + }, + { + "phase": "before", + "state": "idle", + "theme": "light", + "width": 1440, + "actualTheme": "light", + "themeToggle": "Switch to dark theme", + "pageErrors": [], + "apiWrites": [], + "pageHorizontalOverflow": false, + "containers": { + ".layout": { + "clientWidth": 1408, + "scrollWidth": 1408, + "clientHeight": 954, + "scrollHeight": 954, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".tree-content": { + "clientWidth": 246, + "scrollWidth": 246, + "clientHeight": 606, + "scrollHeight": 606, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".center": { + "clientWidth": 832, + "scrollWidth": 832, + "clientHeight": 954, + "scrollHeight": 1016, + "horizontalOverflow": false, + "verticalOverflow": true, + "visible": true + }, + ".inspector-scroll": { + "clientWidth": 296, + "scrollWidth": 296, + "clientHeight": 64, + "scrollHeight": 64, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".github-scroll": { + "clientWidth": 296, + "scrollWidth": 296, + "clientHeight": 759, + "scrollHeight": 759, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".usage-dock": { + "clientWidth": 246, + "scrollWidth": 246, + "clientHeight": 290, + "scrollHeight": 290, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + } + } + }, + { + "phase": "before", + "state": "idle", + "theme": "light", + "width": 1920, + "actualTheme": "light", + "themeToggle": "Switch to dark theme", + "pageErrors": [], + "apiWrites": [], + "pageHorizontalOverflow": false, + "containers": { + ".layout": { + "clientWidth": 1888, + "scrollWidth": 1888, + "clientHeight": 954, + "scrollHeight": 954, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".tree-content": { + "clientWidth": 246, + "scrollWidth": 246, + "clientHeight": 606, + "scrollHeight": 606, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".center": { + "clientWidth": 1214, + "scrollWidth": 1214, + "clientHeight": 954, + "scrollHeight": 1016, + "horizontalOverflow": false, + "verticalOverflow": true, + "visible": true + }, + ".inspector-scroll": { + "clientWidth": 394, + "scrollWidth": 394, + "clientHeight": 46, + "scrollHeight": 46, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".github-scroll": { + "clientWidth": 394, + "scrollWidth": 394, + "clientHeight": 777, + "scrollHeight": 777, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".usage-dock": { + "clientWidth": 246, + "scrollWidth": 246, + "clientHeight": 290, + "scrollHeight": 290, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + } + } + }, + { + "phase": "after", + "state": "active", + "theme": "dark", + "width": 1024, + "actualTheme": "dark", + "themeToggle": "Switch to light theme", + "pageErrors": [], + "apiWrites": [], + "pageHorizontalOverflow": false, + "containers": { + ".layout": { + "clientWidth": 992, + "scrollWidth": 992, + "clientHeight": 954, + "scrollHeight": 954, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".tree-content": { + "clientWidth": 188, + "scrollWidth": 188, + "clientHeight": 561, + "scrollHeight": 561, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".center": { + "clientWidth": 520, + "scrollWidth": 520, + "clientHeight": 954, + "scrollHeight": 2175, + "horizontalOverflow": false, + "verticalOverflow": true, + "visible": true + }, + ".inspector-scroll": { + "clientWidth": 250, + "scrollWidth": 250, + "clientHeight": 278, + "scrollHeight": 304, + "horizontalOverflow": false, + "verticalOverflow": true, + "visible": true + }, + ".github-scroll": { + "clientWidth": 250, + "scrollWidth": 250, + "clientHeight": 544, + "scrollHeight": 544, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".usage-dock": { + "clientWidth": 188, + "scrollWidth": 188, + "clientHeight": 335, + "scrollHeight": 335, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + } + } + }, + { + "phase": "after", + "state": "active", + "theme": "dark", + "width": 1440, + "actualTheme": "dark", + "themeToggle": "Switch to light theme", + "pageErrors": [], + "apiWrites": [], + "pageHorizontalOverflow": false, + "containers": { + ".layout": { + "clientWidth": 1408, + "scrollWidth": 1408, + "clientHeight": 954, + "scrollHeight": 954, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".tree-content": { + "clientWidth": 246, + "scrollWidth": 246, + "clientHeight": 591, + "scrollHeight": 591, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".center": { + "clientWidth": 832, + "scrollWidth": 832, + "clientHeight": 954, + "scrollHeight": 1854, + "horizontalOverflow": false, + "verticalOverflow": true, + "visible": true + }, + ".inspector-scroll": { + "clientWidth": 296, + "scrollWidth": 296, + "clientHeight": 225, + "scrollHeight": 225, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".github-scroll": { + "clientWidth": 296, + "scrollWidth": 296, + "clientHeight": 598, + "scrollHeight": 598, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".usage-dock": { + "clientWidth": 246, + "scrollWidth": 246, + "clientHeight": 305, + "scrollHeight": 305, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + } + } + }, + { + "phase": "after", + "state": "active", + "theme": "dark", + "width": 1920, + "actualTheme": "dark", + "themeToggle": "Switch to light theme", + "pageErrors": [], + "apiWrites": [], + "pageHorizontalOverflow": false, + "containers": { + ".layout": { + "clientWidth": 1888, + "scrollWidth": 1888, + "clientHeight": 954, + "scrollHeight": 954, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".tree-content": { + "clientWidth": 246, + "scrollWidth": 246, + "clientHeight": 591, + "scrollHeight": 591, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".center": { + "clientWidth": 1214, + "scrollWidth": 1214, + "clientHeight": 954, + "scrollHeight": 1842, + "horizontalOverflow": false, + "verticalOverflow": true, + "visible": true + }, + ".inspector-scroll": { + "clientWidth": 394, + "scrollWidth": 394, + "clientHeight": 210, + "scrollHeight": 210, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".github-scroll": { + "clientWidth": 394, + "scrollWidth": 394, + "clientHeight": 613, + "scrollHeight": 613, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".usage-dock": { + "clientWidth": 246, + "scrollWidth": 246, + "clientHeight": 305, + "scrollHeight": 305, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + } + } + }, + { + "phase": "after", + "state": "active", + "theme": "light", + "width": 1024, + "actualTheme": "light", + "themeToggle": "Switch to dark theme", + "pageErrors": [], + "apiWrites": [], + "pageHorizontalOverflow": false, + "containers": { + ".layout": { + "clientWidth": 992, + "scrollWidth": 992, + "clientHeight": 954, + "scrollHeight": 954, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".tree-content": { + "clientWidth": 188, + "scrollWidth": 188, + "clientHeight": 561, + "scrollHeight": 561, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".center": { + "clientWidth": 520, + "scrollWidth": 520, + "clientHeight": 954, + "scrollHeight": 2175, + "horizontalOverflow": false, + "verticalOverflow": true, + "visible": true + }, + ".inspector-scroll": { + "clientWidth": 250, + "scrollWidth": 250, + "clientHeight": 278, + "scrollHeight": 304, + "horizontalOverflow": false, + "verticalOverflow": true, + "visible": true + }, + ".github-scroll": { + "clientWidth": 250, + "scrollWidth": 250, + "clientHeight": 544, + "scrollHeight": 544, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".usage-dock": { + "clientWidth": 188, + "scrollWidth": 188, + "clientHeight": 335, + "scrollHeight": 335, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + } + } + }, + { + "phase": "after", + "state": "active", + "theme": "light", + "width": 1440, + "actualTheme": "light", + "themeToggle": "Switch to dark theme", + "pageErrors": [], + "apiWrites": [], + "pageHorizontalOverflow": false, + "containers": { + ".layout": { + "clientWidth": 1408, + "scrollWidth": 1408, + "clientHeight": 954, + "scrollHeight": 954, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".tree-content": { + "clientWidth": 246, + "scrollWidth": 246, + "clientHeight": 591, + "scrollHeight": 591, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".center": { + "clientWidth": 832, + "scrollWidth": 832, + "clientHeight": 954, + "scrollHeight": 1854, + "horizontalOverflow": false, + "verticalOverflow": true, + "visible": true + }, + ".inspector-scroll": { + "clientWidth": 296, + "scrollWidth": 296, + "clientHeight": 225, + "scrollHeight": 225, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".github-scroll": { + "clientWidth": 296, + "scrollWidth": 296, + "clientHeight": 598, + "scrollHeight": 598, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".usage-dock": { + "clientWidth": 246, + "scrollWidth": 246, + "clientHeight": 305, + "scrollHeight": 305, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + } + } + }, + { + "phase": "after", + "state": "active", + "theme": "light", + "width": 1920, + "actualTheme": "light", + "themeToggle": "Switch to dark theme", + "pageErrors": [], + "apiWrites": [], + "pageHorizontalOverflow": false, + "containers": { + ".layout": { + "clientWidth": 1888, + "scrollWidth": 1888, + "clientHeight": 954, + "scrollHeight": 954, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".tree-content": { + "clientWidth": 246, + "scrollWidth": 246, + "clientHeight": 591, + "scrollHeight": 591, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".center": { + "clientWidth": 1214, + "scrollWidth": 1214, + "clientHeight": 954, + "scrollHeight": 1842, + "horizontalOverflow": false, + "verticalOverflow": true, + "visible": true + }, + ".inspector-scroll": { + "clientWidth": 394, + "scrollWidth": 394, + "clientHeight": 210, + "scrollHeight": 210, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".github-scroll": { + "clientWidth": 394, + "scrollWidth": 394, + "clientHeight": 613, + "scrollHeight": 613, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".usage-dock": { + "clientWidth": 246, + "scrollWidth": 246, + "clientHeight": 305, + "scrollHeight": 305, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + } + } + }, + { + "phase": "after", + "state": "approval", + "theme": "dark", + "width": 1024, + "actualTheme": "dark", + "themeToggle": "Switch to light theme", + "pageErrors": [], + "apiWrites": [], + "pageHorizontalOverflow": false, + "containers": { + ".layout": { + "clientWidth": 992, + "scrollWidth": 992, + "clientHeight": 954, + "scrollHeight": 954, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".tree-content": { + "clientWidth": 188, + "scrollWidth": 188, + "clientHeight": 561, + "scrollHeight": 561, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".center": { + "clientWidth": 520, + "scrollWidth": 520, + "clientHeight": 954, + "scrollHeight": 2269, + "horizontalOverflow": false, + "verticalOverflow": true, + "visible": true + }, + ".inspector-scroll": { + "clientWidth": 250, + "scrollWidth": 250, + "clientHeight": 64, + "scrollHeight": 64, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".github-scroll": { + "clientWidth": 250, + "scrollWidth": 250, + "clientHeight": 759, + "scrollHeight": 759, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".usage-dock": { + "clientWidth": 188, + "scrollWidth": 188, + "clientHeight": 335, + "scrollHeight": 335, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + } + } + }, + { + "phase": "after", + "state": "approval", + "theme": "dark", + "width": 1440, + "actualTheme": "dark", + "themeToggle": "Switch to light theme", + "pageErrors": [], + "apiWrites": [], + "pageHorizontalOverflow": false, + "containers": { + ".layout": { + "clientWidth": 1408, + "scrollWidth": 1408, + "clientHeight": 954, + "scrollHeight": 954, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".tree-content": { + "clientWidth": 246, + "scrollWidth": 246, + "clientHeight": 591, + "scrollHeight": 591, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".center": { + "clientWidth": 832, + "scrollWidth": 832, + "clientHeight": 954, + "scrollHeight": 1909, + "horizontalOverflow": false, + "verticalOverflow": true, + "visible": true + }, + ".inspector-scroll": { + "clientWidth": 296, + "scrollWidth": 296, + "clientHeight": 64, + "scrollHeight": 64, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".github-scroll": { + "clientWidth": 296, + "scrollWidth": 296, + "clientHeight": 759, + "scrollHeight": 759, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".usage-dock": { + "clientWidth": 246, + "scrollWidth": 246, + "clientHeight": 305, + "scrollHeight": 305, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + } + } + }, + { + "phase": "after", + "state": "approval", + "theme": "dark", + "width": 1920, + "actualTheme": "dark", + "themeToggle": "Switch to light theme", + "pageErrors": [], + "apiWrites": [], + "pageHorizontalOverflow": false, + "containers": { + ".layout": { + "clientWidth": 1888, + "scrollWidth": 1888, + "clientHeight": 954, + "scrollHeight": 954, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".tree-content": { + "clientWidth": 246, + "scrollWidth": 246, + "clientHeight": 591, + "scrollHeight": 591, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".center": { + "clientWidth": 1214, + "scrollWidth": 1214, + "clientHeight": 954, + "scrollHeight": 1859, + "horizontalOverflow": false, + "verticalOverflow": true, + "visible": true + }, + ".inspector-scroll": { + "clientWidth": 394, + "scrollWidth": 394, + "clientHeight": 46, + "scrollHeight": 46, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".github-scroll": { + "clientWidth": 394, + "scrollWidth": 394, + "clientHeight": 777, + "scrollHeight": 777, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".usage-dock": { + "clientWidth": 246, + "scrollWidth": 246, + "clientHeight": 305, + "scrollHeight": 305, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + } + } + }, + { + "phase": "after", + "state": "approval", + "theme": "light", + "width": 1024, + "actualTheme": "light", + "themeToggle": "Switch to dark theme", + "pageErrors": [], + "apiWrites": [], + "pageHorizontalOverflow": false, + "containers": { + ".layout": { + "clientWidth": 992, + "scrollWidth": 992, + "clientHeight": 954, + "scrollHeight": 954, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".tree-content": { + "clientWidth": 188, + "scrollWidth": 188, + "clientHeight": 561, + "scrollHeight": 561, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".center": { + "clientWidth": 520, + "scrollWidth": 520, + "clientHeight": 954, + "scrollHeight": 2269, + "horizontalOverflow": false, + "verticalOverflow": true, + "visible": true + }, + ".inspector-scroll": { + "clientWidth": 250, + "scrollWidth": 250, + "clientHeight": 64, + "scrollHeight": 64, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".github-scroll": { + "clientWidth": 250, + "scrollWidth": 250, + "clientHeight": 759, + "scrollHeight": 759, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".usage-dock": { + "clientWidth": 188, + "scrollWidth": 188, + "clientHeight": 335, + "scrollHeight": 335, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + } + } + }, + { + "phase": "after", + "state": "approval", + "theme": "light", + "width": 1440, + "actualTheme": "light", + "themeToggle": "Switch to dark theme", + "pageErrors": [], + "apiWrites": [], + "pageHorizontalOverflow": false, + "containers": { + ".layout": { + "clientWidth": 1408, + "scrollWidth": 1408, + "clientHeight": 954, + "scrollHeight": 954, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".tree-content": { + "clientWidth": 246, + "scrollWidth": 246, + "clientHeight": 591, + "scrollHeight": 591, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".center": { + "clientWidth": 832, + "scrollWidth": 832, + "clientHeight": 954, + "scrollHeight": 1909, + "horizontalOverflow": false, + "verticalOverflow": true, + "visible": true + }, + ".inspector-scroll": { + "clientWidth": 296, + "scrollWidth": 296, + "clientHeight": 64, + "scrollHeight": 64, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".github-scroll": { + "clientWidth": 296, + "scrollWidth": 296, + "clientHeight": 759, + "scrollHeight": 759, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".usage-dock": { + "clientWidth": 246, + "scrollWidth": 246, + "clientHeight": 305, + "scrollHeight": 305, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + } + } + }, + { + "phase": "after", + "state": "approval", + "theme": "light", + "width": 1920, + "actualTheme": "light", + "themeToggle": "Switch to dark theme", + "pageErrors": [], + "apiWrites": [], + "pageHorizontalOverflow": false, + "containers": { + ".layout": { + "clientWidth": 1888, + "scrollWidth": 1888, + "clientHeight": 954, + "scrollHeight": 954, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".tree-content": { + "clientWidth": 246, + "scrollWidth": 246, + "clientHeight": 591, + "scrollHeight": 591, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".center": { + "clientWidth": 1214, + "scrollWidth": 1214, + "clientHeight": 954, + "scrollHeight": 1859, + "horizontalOverflow": false, + "verticalOverflow": true, + "visible": true + }, + ".inspector-scroll": { + "clientWidth": 394, + "scrollWidth": 394, + "clientHeight": 46, + "scrollHeight": 46, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".github-scroll": { + "clientWidth": 394, + "scrollWidth": 394, + "clientHeight": 777, + "scrollHeight": 777, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".usage-dock": { + "clientWidth": 246, + "scrollWidth": 246, + "clientHeight": 305, + "scrollHeight": 305, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + } + } + }, + { + "phase": "after", + "state": "failed", + "theme": "dark", + "width": 1024, + "actualTheme": "dark", + "themeToggle": "Switch to light theme", + "pageErrors": [], + "apiWrites": [], + "pageHorizontalOverflow": false, + "containers": { + ".layout": { + "clientWidth": 992, + "scrollWidth": 992, + "clientHeight": 954, + "scrollHeight": 954, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".tree-content": { + "clientWidth": 188, + "scrollWidth": 188, + "clientHeight": 561, + "scrollHeight": 561, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".center": { + "clientWidth": 520, + "scrollWidth": 520, + "clientHeight": 954, + "scrollHeight": 2537, + "horizontalOverflow": false, + "verticalOverflow": true, + "visible": true + }, + ".inspector-scroll": { + "clientWidth": 250, + "scrollWidth": 250, + "clientHeight": 64, + "scrollHeight": 64, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".github-scroll": { + "clientWidth": 250, + "scrollWidth": 250, + "clientHeight": 759, + "scrollHeight": 759, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".usage-dock": { + "clientWidth": 188, + "scrollWidth": 188, + "clientHeight": 335, + "scrollHeight": 335, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + } + } + }, + { + "phase": "after", + "state": "failed", + "theme": "dark", + "width": 1440, + "actualTheme": "dark", + "themeToggle": "Switch to light theme", + "pageErrors": [], + "apiWrites": [], + "pageHorizontalOverflow": false, + "containers": { + ".layout": { + "clientWidth": 1408, + "scrollWidth": 1408, + "clientHeight": 954, + "scrollHeight": 954, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".tree-content": { + "clientWidth": 246, + "scrollWidth": 246, + "clientHeight": 591, + "scrollHeight": 591, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".center": { + "clientWidth": 832, + "scrollWidth": 832, + "clientHeight": 954, + "scrollHeight": 2137, + "horizontalOverflow": false, + "verticalOverflow": true, + "visible": true + }, + ".inspector-scroll": { + "clientWidth": 296, + "scrollWidth": 296, + "clientHeight": 64, + "scrollHeight": 64, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".github-scroll": { + "clientWidth": 296, + "scrollWidth": 296, + "clientHeight": 759, + "scrollHeight": 759, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".usage-dock": { + "clientWidth": 246, + "scrollWidth": 246, + "clientHeight": 305, + "scrollHeight": 305, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + } + } + }, + { + "phase": "after", + "state": "failed", + "theme": "dark", + "width": 1920, + "actualTheme": "dark", + "themeToggle": "Switch to light theme", + "pageErrors": [], + "apiWrites": [], + "pageHorizontalOverflow": false, + "containers": { + ".layout": { + "clientWidth": 1888, + "scrollWidth": 1888, + "clientHeight": 954, + "scrollHeight": 954, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".tree-content": { + "clientWidth": 246, + "scrollWidth": 246, + "clientHeight": 591, + "scrollHeight": 591, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".center": { + "clientWidth": 1214, + "scrollWidth": 1214, + "clientHeight": 954, + "scrollHeight": 2066, + "horizontalOverflow": false, + "verticalOverflow": true, + "visible": true + }, + ".inspector-scroll": { + "clientWidth": 394, + "scrollWidth": 394, + "clientHeight": 46, + "scrollHeight": 46, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".github-scroll": { + "clientWidth": 394, + "scrollWidth": 394, + "clientHeight": 777, + "scrollHeight": 777, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".usage-dock": { + "clientWidth": 246, + "scrollWidth": 246, + "clientHeight": 305, + "scrollHeight": 305, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + } + } + }, + { + "phase": "after", + "state": "failed", + "theme": "light", + "width": 1024, + "actualTheme": "light", + "themeToggle": "Switch to dark theme", + "pageErrors": [], + "apiWrites": [], + "pageHorizontalOverflow": false, + "containers": { + ".layout": { + "clientWidth": 992, + "scrollWidth": 992, + "clientHeight": 954, + "scrollHeight": 954, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".tree-content": { + "clientWidth": 188, + "scrollWidth": 188, + "clientHeight": 561, + "scrollHeight": 561, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".center": { + "clientWidth": 520, + "scrollWidth": 520, + "clientHeight": 954, + "scrollHeight": 2537, + "horizontalOverflow": false, + "verticalOverflow": true, + "visible": true + }, + ".inspector-scroll": { + "clientWidth": 250, + "scrollWidth": 250, + "clientHeight": 64, + "scrollHeight": 64, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".github-scroll": { + "clientWidth": 250, + "scrollWidth": 250, + "clientHeight": 759, + "scrollHeight": 759, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".usage-dock": { + "clientWidth": 188, + "scrollWidth": 188, + "clientHeight": 335, + "scrollHeight": 335, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + } + } + }, + { + "phase": "after", + "state": "failed", + "theme": "light", + "width": 1440, + "actualTheme": "light", + "themeToggle": "Switch to dark theme", + "pageErrors": [], + "apiWrites": [], + "pageHorizontalOverflow": false, + "containers": { + ".layout": { + "clientWidth": 1408, + "scrollWidth": 1408, + "clientHeight": 954, + "scrollHeight": 954, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".tree-content": { + "clientWidth": 246, + "scrollWidth": 246, + "clientHeight": 591, + "scrollHeight": 591, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".center": { + "clientWidth": 832, + "scrollWidth": 832, + "clientHeight": 954, + "scrollHeight": 2137, + "horizontalOverflow": false, + "verticalOverflow": true, + "visible": true + }, + ".inspector-scroll": { + "clientWidth": 296, + "scrollWidth": 296, + "clientHeight": 64, + "scrollHeight": 64, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".github-scroll": { + "clientWidth": 296, + "scrollWidth": 296, + "clientHeight": 759, + "scrollHeight": 759, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".usage-dock": { + "clientWidth": 246, + "scrollWidth": 246, + "clientHeight": 305, + "scrollHeight": 305, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + } + } + }, + { + "phase": "after", + "state": "failed", + "theme": "light", + "width": 1920, + "actualTheme": "light", + "themeToggle": "Switch to dark theme", + "pageErrors": [], + "apiWrites": [], + "pageHorizontalOverflow": false, + "containers": { + ".layout": { + "clientWidth": 1888, + "scrollWidth": 1888, + "clientHeight": 954, + "scrollHeight": 954, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".tree-content": { + "clientWidth": 246, + "scrollWidth": 246, + "clientHeight": 591, + "scrollHeight": 591, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".center": { + "clientWidth": 1214, + "scrollWidth": 1214, + "clientHeight": 954, + "scrollHeight": 2066, + "horizontalOverflow": false, + "verticalOverflow": true, + "visible": true + }, + ".inspector-scroll": { + "clientWidth": 394, + "scrollWidth": 394, + "clientHeight": 46, + "scrollHeight": 46, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".github-scroll": { + "clientWidth": 394, + "scrollWidth": 394, + "clientHeight": 777, + "scrollHeight": 777, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".usage-dock": { + "clientWidth": 246, + "scrollWidth": 246, + "clientHeight": 305, + "scrollHeight": 305, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + } + } + }, + { + "phase": "after", + "state": "idle", + "theme": "dark", + "width": 1024, + "actualTheme": "dark", + "themeToggle": "Switch to light theme", + "pageErrors": [], + "apiWrites": [], + "pageHorizontalOverflow": false, + "containers": { + ".layout": { + "clientWidth": 992, + "scrollWidth": 992, + "clientHeight": 954, + "scrollHeight": 954, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".tree-content": { + "clientWidth": 188, + "scrollWidth": 188, + "clientHeight": 591, + "scrollHeight": 591, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".center": { + "clientWidth": 520, + "scrollWidth": 520, + "clientHeight": 954, + "scrollHeight": 1120, + "horizontalOverflow": false, + "verticalOverflow": true, + "visible": true + }, + ".inspector-scroll": { + "clientWidth": 250, + "scrollWidth": 250, + "clientHeight": 64, + "scrollHeight": 64, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".github-scroll": { + "clientWidth": 250, + "scrollWidth": 250, + "clientHeight": 759, + "scrollHeight": 759, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".usage-dock": { + "clientWidth": 188, + "scrollWidth": 188, + "clientHeight": 305, + "scrollHeight": 305, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + } + } + }, + { + "phase": "after", + "state": "idle", + "theme": "dark", + "width": 1440, + "actualTheme": "dark", + "themeToggle": "Switch to light theme", + "pageErrors": [], + "apiWrites": [], + "pageHorizontalOverflow": false, + "containers": { + ".layout": { + "clientWidth": 1408, + "scrollWidth": 1408, + "clientHeight": 954, + "scrollHeight": 954, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".tree-content": { + "clientWidth": 246, + "scrollWidth": 246, + "clientHeight": 606, + "scrollHeight": 606, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".center": { + "clientWidth": 832, + "scrollWidth": 832, + "clientHeight": 954, + "scrollHeight": 1014, + "horizontalOverflow": false, + "verticalOverflow": true, + "visible": true + }, + ".inspector-scroll": { + "clientWidth": 296, + "scrollWidth": 296, + "clientHeight": 64, + "scrollHeight": 64, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".github-scroll": { + "clientWidth": 296, + "scrollWidth": 296, + "clientHeight": 759, + "scrollHeight": 759, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".usage-dock": { + "clientWidth": 246, + "scrollWidth": 246, + "clientHeight": 290, + "scrollHeight": 290, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + } + } + }, + { + "phase": "after", + "state": "idle", + "theme": "dark", + "width": 1920, + "actualTheme": "dark", + "themeToggle": "Switch to light theme", + "pageErrors": [], + "apiWrites": [], + "pageHorizontalOverflow": false, + "containers": { + ".layout": { + "clientWidth": 1888, + "scrollWidth": 1888, + "clientHeight": 954, + "scrollHeight": 954, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".tree-content": { + "clientWidth": 246, + "scrollWidth": 246, + "clientHeight": 606, + "scrollHeight": 606, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".center": { + "clientWidth": 1214, + "scrollWidth": 1214, + "clientHeight": 954, + "scrollHeight": 1014, + "horizontalOverflow": false, + "verticalOverflow": true, + "visible": true + }, + ".inspector-scroll": { + "clientWidth": 394, + "scrollWidth": 394, + "clientHeight": 46, + "scrollHeight": 46, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".github-scroll": { + "clientWidth": 394, + "scrollWidth": 394, + "clientHeight": 777, + "scrollHeight": 777, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".usage-dock": { + "clientWidth": 246, + "scrollWidth": 246, + "clientHeight": 290, + "scrollHeight": 290, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + } + } + }, + { + "phase": "after", + "state": "idle", + "theme": "light", + "width": 1024, + "actualTheme": "light", + "themeToggle": "Switch to dark theme", + "pageErrors": [], + "apiWrites": [], + "pageHorizontalOverflow": false, + "containers": { + ".layout": { + "clientWidth": 992, + "scrollWidth": 992, + "clientHeight": 954, + "scrollHeight": 954, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".tree-content": { + "clientWidth": 188, + "scrollWidth": 188, + "clientHeight": 591, + "scrollHeight": 591, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".center": { + "clientWidth": 520, + "scrollWidth": 520, + "clientHeight": 954, + "scrollHeight": 1120, + "horizontalOverflow": false, + "verticalOverflow": true, + "visible": true + }, + ".inspector-scroll": { + "clientWidth": 250, + "scrollWidth": 250, + "clientHeight": 64, + "scrollHeight": 64, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".github-scroll": { + "clientWidth": 250, + "scrollWidth": 250, + "clientHeight": 759, + "scrollHeight": 759, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".usage-dock": { + "clientWidth": 188, + "scrollWidth": 188, + "clientHeight": 305, + "scrollHeight": 305, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + } + } + }, + { + "phase": "after", + "state": "idle", + "theme": "light", + "width": 1440, + "actualTheme": "light", + "themeToggle": "Switch to dark theme", + "pageErrors": [], + "apiWrites": [], + "pageHorizontalOverflow": false, + "containers": { + ".layout": { + "clientWidth": 1408, + "scrollWidth": 1408, + "clientHeight": 954, + "scrollHeight": 954, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".tree-content": { + "clientWidth": 246, + "scrollWidth": 246, + "clientHeight": 606, + "scrollHeight": 606, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".center": { + "clientWidth": 832, + "scrollWidth": 832, + "clientHeight": 954, + "scrollHeight": 1014, + "horizontalOverflow": false, + "verticalOverflow": true, + "visible": true + }, + ".inspector-scroll": { + "clientWidth": 296, + "scrollWidth": 296, + "clientHeight": 64, + "scrollHeight": 64, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".github-scroll": { + "clientWidth": 296, + "scrollWidth": 296, + "clientHeight": 759, + "scrollHeight": 759, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".usage-dock": { + "clientWidth": 246, + "scrollWidth": 246, + "clientHeight": 290, + "scrollHeight": 290, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + } + } + }, + { + "phase": "after", + "state": "idle", + "theme": "light", + "width": 1920, + "actualTheme": "light", + "themeToggle": "Switch to dark theme", + "pageErrors": [], + "apiWrites": [], + "pageHorizontalOverflow": false, + "containers": { + ".layout": { + "clientWidth": 1888, + "scrollWidth": 1888, + "clientHeight": 954, + "scrollHeight": 954, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".tree-content": { + "clientWidth": 246, + "scrollWidth": 246, + "clientHeight": 606, + "scrollHeight": 606, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".center": { + "clientWidth": 1214, + "scrollWidth": 1214, + "clientHeight": 954, + "scrollHeight": 1014, + "horizontalOverflow": false, + "verticalOverflow": true, + "visible": true + }, + ".inspector-scroll": { + "clientWidth": 394, + "scrollWidth": 394, + "clientHeight": 46, + "scrollHeight": 46, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".github-scroll": { + "clientWidth": 394, + "scrollWidth": 394, + "clientHeight": 777, + "scrollHeight": 777, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + }, + ".usage-dock": { + "clientWidth": 246, + "scrollWidth": 246, + "clientHeight": 290, + "scrollHeight": 290, + "horizontalOverflow": false, + "verticalOverflow": false, + "visible": true + } + } + } + ], + "openPrGateInteractions": [ + { + "scenario": "unpromoted-matching", + "disabled": true, + "reason": "Promote the approved result before opening a pull request.", + "clickOutcome": "browser refused disabled click", + "dialog": false, + "writes": [] + }, + { + "scenario": "promoted-missing", + "disabled": true, + "reason": "Push the promoted result branch and refresh status before opening a pull request.", + "clickOutcome": "browser refused disabled click", + "dialog": false, + "writes": [] + }, + { + "scenario": "promoted-different", + "disabled": true, + "reason": "The remote branch differs from the promoted result. Push the result branch and refresh status.", + "clickOutcome": "browser refused disabled click", + "dialog": false, + "writes": [] + }, + { + "scenario": "promoted-matching", + "disabled": false, + "reason": null, + "clickOutcome": "confirmation dialog opened", + "dialog": true, + "writes": [] + } + ], + "keyboardFocusProbe": { + "dark": { + "tag": "BUTTON", + "ariaLabel": "Switch to light theme", + "text": "Light", + "outlineStyle": "solid", + "outlineWidth": "2px", + "outlineColor": "rgb(255, 241, 122)", + "focusVisible": true + }, + "light": { + "tag": "BUTTON", + "ariaLabel": "Switch to dark theme", + "text": "Dark", + "outlineStyle": "solid", + "outlineWidth": "2px", + "outlineColor": "rgb(105, 117, 0)", + "focusVisible": true + } + }, + "contrast": { + "basis": "Static CSS token-pair calculations; not a comprehensive WCAG or rendered-state audit.", + "ratios": { + "text/surface": { + "dark": 14.87, + "light": 12.63 + }, + "dim/surface": { + "dark": 9.44, + "light": 7.0 + }, + "muted/surface": { + "dark": 6.33, + "light": 4.76 + }, + "semantic badge foreground/background minimum": { + "dark": 7.65, + "light": 5.85 + }, + "quota fill/rail": { + "dark": 6.33, + "light": 4.76 + }, + "focus ring/surface": { + "dark": 16.16, + "light": 4.15 + } + } + } +} diff --git a/tests/ui.test.tsx b/tests/ui.test.tsx index 716638a..de2db69 100644 --- a/tests/ui.test.tsx +++ b/tests/ui.test.tsx @@ -1,7 +1,7 @@ import { createElement, type ReactElement, type ReactNode } from 'react'; import { renderToStaticMarkup } from 'react-dom/server'; import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; -import { App, debounce, type State, type TaskStartPreview } from '../ui/main.js'; +import { App, debounce, mergePrUnavailableReason, openPrUnavailableReason, pushResultUnavailableReason, type State, type TaskStartPreview } from '../ui/main.js'; import { DecisionPanel, DecisionDigestNotice, type DecisionPanelProps } from '../ui/decision-panel.js'; import type { DecisionDigestView } from '../ui/decision-digest.js'; import { ChecksPipeline, type StationObservation, type GithubCheckEntry } from '../ui/checks-pipeline.js'; @@ -49,6 +49,30 @@ describe('debounce helper',()=>{ }); }); +describe('GitHub action availability explanations',()=>{ + const openPrBase={promotionApplied:true,account:'reviewer',taskBranch:'foreman/task',taskCommit:'abc123',remoteBranchStatus:'matching' as const,busy:false}; + it('requires promotion even when stale GitHub branch and commit data match',()=>{ + expect(openPrUnavailableReason({...openPrBase,promotionApplied:false})).toMatch(/Promote the approved result/); + }); + it('explains remote mismatch, busy state, and success using the same availability decision',()=>{ + expect(openPrUnavailableReason({...openPrBase,remoteBranchStatus:'different'})).toMatch(/differs from the promoted result/); + expect(openPrUnavailableReason({...openPrBase,busy:true})).toMatch(/current GitHub action/); + expect(openPrUnavailableReason(openPrBase)).toBeUndefined(); + }); + it('blocks both push surfaces until promotion and allows a promoted mismatched branch to be pushed',()=>{ + expect(pushResultUnavailableReason({...openPrBase,promotionApplied:false})).toMatch(/Promote the approved result/); + expect(pushResultUnavailableReason({...openPrBase,remoteBranchStatus:'different'})).toBeUndefined(); + expect(pushResultUnavailableReason({...openPrBase,remoteBranchStatus:'matching'})).toMatch(/already matches/); + }); + it('explains disabled merge prerequisites and reports availability when all gates pass',()=>{ + const base={busy:false,diffAvailable:true,diffTruncated:false,state:'OPEN',queueRequired:false,mergeQueue:false,headMatchesResult:true}; + expect(mergePrUnavailableReason({...base,headMatchesResult:false})).toMatch(/head must match/); + expect(mergePrUnavailableReason({...base,queueRequired:null})).toMatch(/Refresh GitHub status/); + expect(mergePrUnavailableReason({...base,busy:true})).toMatch(/current GitHub action/); + expect(mergePrUnavailableReason(base)).toBeUndefined(); + }); +}); + describe('project Planner UI',()=>{ it('shows the continuing Planner, task tree, start controls, and named navigation with inline icons',()=>{ const state:State={projects:[{id:'prj_fixture',name:'Opened repository',plannerSession:{localId:'planner-session-fixture',roleId:'planner',generation:1,status:'active',config:{harnessId:'fixture',model:'simulated'},startedAt:'2026-01-01T00:00:00.000Z'},plannerMessages:[{id:'pmsg_user',role:'user',text:'Update the node README and add a REST endpoint.',createdAt:'2026-01-01T00:00:00.000Z'},{id:'pmsg_planner',role:'planner',text:'I split this into two tasks.',createdAt:'2026-01-01T00:01:00.000Z'}],tasks:[{id:'tsk_readme_fixture',title:'Update README',goal:'Document the node behavior.',suggestedAllowedPaths:['README.md'],validationCriteria:['README check passes'],status:'ready',runs:[]},{id:'tsk_endpoint_fixture',title:'Add REST endpoint',goal:'Implement the requested API endpoint.',suggestedAllowedPaths:['src/http/'],validationCriteria:['Endpoint tests pass'],status:'ready',runs:[]}]}],roles:[...['planner','orchestrator','worker','reviewer'].map(id=>({id,name:id,enabled:true,config:{harnessId:'fixture',model:'simulated'},availableConfigs:[{harnessId:'fixture',model:'simulated'}]}))]}; @@ -84,7 +108,7 @@ describe('project Planner UI',()=>{ const state:State={projects:[{id:'prj_blocked',name:'Blocked project',tasks:[{id:'tsk_blocked',title:'Update report',goal:'Update the report.',validationCriteria:['Report lint passes'],status:'ready'}]}],roles:[]}; const preview:TaskStartPreview={taskId:'tsk_blocked',scope:[],roleConfigs:{},validationCriteria:['Report lint passes'],validationCommands:[],requiresExplicitBase:true,reasons:['Choose at least one allowed path before starting this task','Dependency tsk_prior must be completed and promoted'],dependencyTaskIds:['tsk_prior'],canStart:false}; const html=renderToStaticMarkup(createElement(App,{initialState:state,initialTaskStartPreview:preview})); - expect(html).toContain('Resolve these blockers before starting');expect(html).toContain('Choose at least one allowed path before starting this task');expect(html).toContain('Dependency tsk_prior must be completed and promoted');expect(html).toContain('Related work must be integrated first');expect(html).toContain('pins the updated current HEAD automatically');expect(html).toContain('Approve task & start work');expect(html).toMatch(/