test(desktop): enforce entry runtime boundary#408
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
✅ Files skipped from review due to trivial changes (1)
📝 WalkthroughWalkthroughAdds ChangesDesktop boundary checks and phase tracking
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@app/desktop/src/__e2e__/desktop-data-boundary.spec.ts`:
- Around line 51-58: The boundary check in the desktop E2E spec is using a fixed
1s timeout, which can be too short to cover the next health poll. Update the
wait in desktop-data-boundary.spec around the runtime backends assertion to use
the full HEALTH_POLL_MS delay before checking backendRequests.requests, so the
no-runtime-backend assertion and assertE2EDataModeScenario run after the
expected poll window.
In `@app/desktop/src/hooks/useHealth.ts`:
- Around line 25-37: The `useHealth` poll callback only guards updates with
`mountedRef` and `enabledRef`, so an older `fetchHealth()` response can still
overwrite newer state after polling is toggled off and back on. In `useHealth`,
add a poll-generation or request token inside `poll` before awaiting
`fetchHealth()`, then re-check that token before every `setHealth`, `setOnline`,
and `setLastError` update so only the latest session can commit state.
In `@docs/roadmap.md`:
- Line 3: The roadmap’s last-updated metadata is future-dated and needs to be
corrected. Update the “最后更新” value in the roadmap metadata to the actual edit
date, keeping the change limited to the existing last-updated entry so the
document remains accurate.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 5da5b8db-a4fd-4624-9892-98da2dcb01f6
📒 Files selected for processing (6)
app/desktop/package.jsonapp/desktop/src/__e2e__/chat-flow-ui.spec.tsapp/desktop/src/__e2e__/desktop-data-boundary.spec.tsapp/desktop/src/__tests__/useHealth.test.tsapp/desktop/src/hooks/useHealth.tsdocs/roadmap.md
| await page.waitForTimeout(1_000); | ||
|
|
||
| const runtimeBackends = backendRequests.requests.filter((request) => | ||
| request.phase === 'workbench-runtime' && | ||
| isBackendBoundary(classifyE2ERequest(request.url, DESKTOP_DEMO_BOUNDARY_SCENARIO)) | ||
| ); | ||
| expect(runtimeBackends, formatRequests(runtimeBackends)).toEqual([]); | ||
| assertE2EDataModeScenario(DESKTOP_DEMO_BOUNDARY_SCENARIO, backendRequests.requests); |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
USE_HEALTH_FILE="$(fd 'useHealth.ts' app/desktop/src | head -n1)"
USE_HEALTH_TEST_FILE="$(fd 'useHealth.test.ts' app/desktop/src | head -n1)"
echo "useHealth file: ${USE_HEALTH_FILE}"
ast-grep outline "${USE_HEALTH_FILE}" --view expanded
rg -n -C3 'setInterval|setTimeout|poll|interval|health' "${USE_HEALTH_FILE}"
if [[ -n "${USE_HEALTH_TEST_FILE}" ]]; then
echo
echo "useHealth test file: ${USE_HEALTH_TEST_FILE}"
rg -n -C3 'advanceTimersByTime|runOnlyPendingTimers|poll|interval|health' "${USE_HEALTH_TEST_FILE}"
fiRepository: TokenDanceLab/AgentHub
Length of output: 6318
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "useHealth.ts"
cat -n app/desktop/src/hooks/useHealth.ts | sed -n '1,220p'
echo
echo "desktop-data-boundary.spec.ts"
cat -n app/desktop/src/__e2e__/desktop-data-boundary.spec.ts | sed -n '1,220p'
echo
echo "Search HEALTH_POLL_MS"
rg -n 'HEALTH_POLL_MS|useHealth\(' app/desktop/srcRepository: TokenDanceLab/AgentHub
Length of output: 11683
Wait a full HEALTH_POLL_MS before asserting no runtime backend requests. The current 1s sleep can miss a later /v1/health poll and let a boundary regression slip through. app/desktop/src/__e2e__/desktop-data-boundary.spec.ts:51-58
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@app/desktop/src/__e2e__/desktop-data-boundary.spec.ts` around lines 51 - 58,
The boundary check in the desktop E2E spec is using a fixed 1s timeout, which
can be too short to cover the next health poll. Update the wait in
desktop-data-boundary.spec around the runtime backends assertion to use the full
HEALTH_POLL_MS delay before checking backendRequests.requests, so the
no-runtime-backend assertion and assertE2EDataModeScenario run after the
expected poll window.
| const enabledRef = useRef(enabled); | ||
| enabledRef.current = enabled; | ||
|
|
||
| const poll = useCallback(async () => { | ||
| if (!enabled) return; | ||
| try { | ||
| const h = await fetchHealth(); | ||
| if (!mountedRef.current) return; | ||
| if (!mountedRef.current || !enabledRef.current) return; | ||
| setHealth(h); | ||
| setOnline(true); | ||
| setLastError(null); | ||
| } catch (error) { | ||
| if (!mountedRef.current) return; | ||
| if (!mountedRef.current || !enabledRef.current) return; |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Guard stale responses by poll generation, not only enabled.
If polling is disabled and then re-enabled before an earlier fetchHealth() resolves, that older response will still pass the current mountedRef.current && enabledRef.current check and overwrite the new session’s state. Capture a request/session token before await fetchHealth() and compare it again before each state update.
Possible fix
const mountedRef = useRef(true);
const enabledRef = useRef(enabled);
+ const pollEpochRef = useRef(0);
enabledRef.current = enabled;
const poll = useCallback(async () => {
if (!enabled) return;
+ const pollEpoch = pollEpochRef.current;
try {
const h = await fetchHealth();
- if (!mountedRef.current || !enabledRef.current) return;
+ if (!mountedRef.current || !enabledRef.current || pollEpoch !== pollEpochRef.current) return;
setHealth(h);
setOnline(true);
setLastError(null);
} catch (error) {
- if (!mountedRef.current || !enabledRef.current) return;
+ if (!mountedRef.current || !enabledRef.current || pollEpoch !== pollEpochRef.current) return;
setOnline(false);
setHealth(null);
setLastError(error instanceof Error ? error.message : 'Local Edge health check failed');
}
}, [enabled]);
useEffect(() => {
mountedRef.current = true;
enabledRef.current = enabled;
+ pollEpochRef.current += 1;
if (!enabled) {
setOnline(false);
setHealth(null);
setLastError(null);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const enabledRef = useRef(enabled); | |
| enabledRef.current = enabled; | |
| const poll = useCallback(async () => { | |
| if (!enabled) return; | |
| try { | |
| const h = await fetchHealth(); | |
| if (!mountedRef.current) return; | |
| if (!mountedRef.current || !enabledRef.current) return; | |
| setHealth(h); | |
| setOnline(true); | |
| setLastError(null); | |
| } catch (error) { | |
| if (!mountedRef.current) return; | |
| if (!mountedRef.current || !enabledRef.current) return; | |
| const mountedRef = useRef(true); | |
| const enabledRef = useRef(enabled); | |
| const pollEpochRef = useRef(0); | |
| enabledRef.current = enabled; | |
| const poll = useCallback(async () => { | |
| if (!enabled) return; | |
| const pollEpoch = pollEpochRef.current; | |
| try { | |
| const h = await fetchHealth(); | |
| if (!mountedRef.current || !enabledRef.current || pollEpoch !== pollEpochRef.current) return; | |
| setHealth(h); | |
| setOnline(true); | |
| setLastError(null); | |
| } catch (error) { | |
| if (!mountedRef.current || !enabledRef.current || pollEpoch !== pollEpochRef.current) return; | |
| setOnline(false); | |
| setHealth(null); | |
| setLastError(error instanceof Error ? error.message : 'Local Edge health check failed'); | |
| } | |
| }, [enabled]); | |
| useEffect(() => { | |
| mountedRef.current = true; | |
| enabledRef.current = enabled; | |
| pollEpochRef.current += 1; |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@app/desktop/src/hooks/useHealth.ts` around lines 25 - 37, The `useHealth`
poll callback only guards updates with `mountedRef` and `enabledRef`, so an
older `fetchHealth()` response can still overwrite newer state after polling is
toggled off and back on. In `useHealth`, add a poll-generation or request token
inside `poll` before awaiting `fetchHealth()`, then re-check that token before
every `setHealth`, `setOnline`, and `setLastError` update so only the latest
session can commit state.
| # AgentHub Roadmap | ||
|
|
||
| 最后更新:2026-06-28 | ||
| 最后更新:2026-06-29 |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Fix the last-updated date.
2026-06-29 is future-dated here, which makes the roadmap metadata inaccurate. Please set it to the actual edit date.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/roadmap.md` at line 3, The roadmap’s last-updated metadata is
future-dated and needs to be corrected. Update the “最后更新” value in the roadmap
metadata to the actual edit date, keeping the change limited to the existing
last-updated entry so the document remains accurate.
Summary
useHealthso in-flight entry health responses do not update state after polling is disabledCloses #387
Verification
corepack.cmd pnpm --dir app/desktop exec vitest run src/__tests__/useHealth.test.tscorepack.cmd pnpm --dir app/desktop test:e2e:data-boundarycorepack.cmd pnpm --dir app/desktop test:e2e:chat-flowcorepack.cmd pnpm --dir app/desktop typecheckcorepack.cmd pnpm --dir app/desktop buildpwsh ./scripts/verify/verify-doc-ssot.ps1pwsh ./scripts/verify/verify-project-skills.ps1pwsh ./scripts/verify/verify-real-e2e-contract.ps1git diff --checkEvidence boundary: Desktop Vite Playwright + fixture/unit + build.
real_tested=false; no packaged Desktop, sidecar, installer/signing, real login, real CLI/model/API, or production path tested.Summary by CodeRabbit
New Features
Tests
useHealthtest covering behavior after disabling polling.Bug Fixes
Documentation