Skip to content

Fix Windows nightly test portability - #325

Merged
unbraind merged 3 commits into
mainfrom
fix/windows-nightly-test-portability
Jun 21, 2026
Merged

unbraind merged 3 commits into
mainfrom
fix/windows-nightly-test-portability

Conversation

@unbraind

@unbraind unbraind commented Jun 21, 2026 •

Copy link
Copy Markdown
Owner

Summary

  • Fix Windows nightly test failures from run 27898852339 by normalizing eval path assertions and making chmod-denial coverage POSIX-only.
  • Stabilize full coverage CI by retrying telemetry OTLP temp cleanup and extending the MCP dynamic package error-path spec timeout.
  • Track the work in pm-83rt with closed/released evidence and regenerate CHANGELOG.md via pm-changelog.

Verification

  • node scripts/run-tests.mjs test -- tests/unit/commands/eval-command.spec.ts tests/unit/extensions/extension-command.spec.ts tests/unit/core/search/search-cache.spec.ts tests/unit/core/telemetry/telemetry-runtime.spec.ts
  • node scripts/run-tests.mjs test -- tests/integration/mcp-dynamic-package-actions.spec.ts tests/integration/telemetry-otel-nonblocking.spec.ts tests/unit/commands/eval-command.spec.ts tests/unit/extensions/extension-command.spec.ts tests/unit/core/search/search-cache.spec.ts tests/unit/core/telemetry/telemetry-runtime.spec.ts
  • pm test pm-83rt --run --progress
  • pnpm changelog:pm:check
  • pnpm contracts:check
  • pnpm quality:static
  • pnpm build
  • pnpm quality:docs-links
  • node scripts/run-tests.mjs coverage: 241 files, 4796 tests, 100/100/100/100
  • Manual temp-dir smoke with isolated PM_GLOBAL_PATH: init/create/update/get passed
  • pm health --check-only --summary --json
  • pm validate --check-resolution --check-history-drift --json (pre-existing resolution warnings only; history drift ok)
  • node scripts/release/sentry-telemetry-gate.mjs --json
  • pm telemetry status --json

Review Agents

@codex review
/gemini review
@gemini-code-assist
@coderabbitai full review
@sourcery-ai review

Summary by Sourcery

Improve test suite portability and stability across platforms, particularly Windows, and document the fix in the changelog.

Bug Fixes:

  • Normalize eval command path assertions to be independent of OS path separators.
  • Restrict chmod-denial and POSIX-specific telemetry and search cache tests to non-Windows platforms to avoid Windows-only failures.
  • Increase timeout for MCP dynamic package error-path spec to reduce flakiness.
  • Make telemetry OTLP non-blocking integration cleanup more robust by retrying temporary directory removal.

Enhancements:

  • Add project management tracking artifacts for issue pm-83rt and regenerate the changelog entry describing the Windows test portability fix.

Tests:

  • Gate POSIX-only tests behind platform checks to keep full coverage meaningful on Windows while maintaining coverage on POSIX systems.

Stabilize the nightly and coverage test surfaces by normalizing eval path assertions, guarding chmod-based permission-denial coverage to POSIX, retrying telemetry OTLP temp cleanup while detached workers exit, and giving the MCP dynamic package error-path spec enough time under full coverage.

Track the remediation in pm-83rt with linked files, focused linked tests, full 100/100/100/100 coverage evidence, manual temp-dir smoke evidence, changelog regeneration, Sentry/telemetry verification, and related closed Windows-nightly lineage.
@sourcery-ai

sourcery-ai Bot commented Jun 21, 2026 •

Copy link
Copy Markdown

Reviewer's Guide

Makes Windows nightly tests portable by guarding POSIX-only permission/FS behaviors, normalizing path-based assertions, stabilizing telemetry/mcp integration tests with retry/timeout tweaks, and recording the work in pm-83rt plus the changelog.

Flow diagram for stabilized Windows nightly tests and telemetry/MCP adjustments

flowchart TD
    A[Windows nightly test run] --> B[Normalize eval path assertions]
    B --> C[Guard POSIX-only chmod-denial coverage]
    C --> D[Retry telemetry OTLP temp cleanup]
    D --> E[Extend MCP dynamic package error-path timeout]
    E --> F[Stable cross-platform nightly and coverage CI]
Loading

File-Level Changes

Change Details Files
Guard POSIX-only chmod/lock failure coverage in extension command tests so they skip on Windows.
  • Wrap readonly-root chmod denial scenario in a process.platform !== "win32" conditional.
  • Wrap cleanup lock-root chmod calls in process.platform !== "win32" conditionals to avoid Windows permission semantics issues.
tests/unit/extensions/extension-command.spec.ts
Harden telemetry OTLP non-blocking integration cleanup with retry/backoff to reduce flakiness.
  • Replace single rm call on the telemetry temp root with a bounded retry loop (up to 5 attempts) and incremental delay backoff before failing.
tests/integration/telemetry-otel-nonblocking.spec.ts
Normalize eval-command tests to be path-separator agnostic for Windows compatibility.
  • Capture the target path from readFileMock and normalize path separators with replaceAll(path.sep, "/").
  • Assert on normalized paths for custom eval JSON and default pm root eval-queries.json instead of raw OS-specific paths.
tests/unit/commands/eval-command.spec.ts
Skip POSIX-specific telemetry and search-cache behaviors on Windows using shared helpers.
  • Introduce itOnPosix alias (it or it.skip depending on platform) in telemetry-runtime tests and use it for queue rewrite and primitive flush coverage cases.
  • Introduce itOnPosix alias in search-cache tests and use it for ledger write warning behavior that depends on POSIX semantics.
tests/unit/core/telemetry/telemetry-runtime.spec.ts
tests/unit/core/search/search-cache.spec.ts
Stabilize slow MCP dynamic package integration test and document the fix via pm-83rt artifacts and changelog.
  • Extend the MCP dynamic package actions suite timeout to 60 seconds to avoid timeouts under load/CI.
  • Add pm-83rt issue and history artifacts under .agents/pm for tracking.
  • Add a Fixed entry in CHANGELOG.md describing the Windows nightly path/permission fix referencing pm-83rt.
tests/integration/mcp-dynamic-package-actions.spec.ts
CHANGELOG.md
.agents/pm/history/pm-83rt.jsonl
.agents/pm/issues/pm-83rt.toon

Possibly linked issues

  • #N/A: PR adjusts eval path assertions, chmod-based tests, and telemetry cleanup to fix Windows nightly CI failures.
  • #(none provided): PR normalizes paths, skips POSIX-only chmod tests on Windows, and stabilizes telemetry cleanup, fixing the failing Windows nightly.

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@unbraind

Copy link
Copy Markdown
Owner Author

@codex review
/gemini review
@gemini-code-assist
@coderabbitai full review
@sourcery-ai review

@chatgpt-codex-connector

Copy link
Copy Markdown

To use Codex here, create a Codex account and connect to github.

@coderabbitai

coderabbitai Bot commented Jun 21, 2026 •

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro

Run ID: 6f479841-1ea5-46e8-b962-83c4e308d8f8

📥 Commits

Reviewing files that changed from the base of the PR and between eb0e529 and 9645438.

📒 Files selected for processing (10)
  • .agents/pm/history/pm-83rt.jsonl
  • .agents/pm/issues/pm-83rt.toon
  • CHANGELOG.md
  • tests/helpers/platform.ts
  • tests/integration/mcp-dynamic-package-actions.spec.ts
  • tests/integration/telemetry-otel-nonblocking.spec.ts
  • tests/unit/commands/eval-command.spec.ts
  • tests/unit/core/search/search-cache.spec.ts
  • tests/unit/core/telemetry/telemetry-runtime.spec.ts
  • tests/unit/extensions/extension-command.spec.ts

📝 Walkthrough

Summary by CodeRabbit

  • Bug Fixes

    • Resolved Windows nightly full-test failures related to path separator handling and file permission assumptions.
  • Tests

    • Enhanced test infrastructure with cross-platform detection utilities for POSIX-specific test cases.
    • Improved test reliability through increased timeout values and retry logic for temporary file cleanup.
    • Updated assertions to normalize filesystem path separators across Windows and POSIX platforms.

Walkthrough

This PR fixes Windows nightly CI failures by adding a shared isPosix/itOnPosix platform helper in tests/helpers/platform.ts, applying it to skip or guard POSIX-specific chmod and lock tests, normalizing path separators in eval-command assertions, replacing a single temp-directory rm with an 8-attempt retry loop, and adding an explicit 60-second timeout to an MCP integration test. A CHANGELOG entry and agent issue tracking files are also included.

Changes

Windows Nightly CI Fix

Layer / File(s) Summary
Platform helper and POSIX-gated tests
tests/helpers/platform.ts, tests/unit/extensions/extension-command.spec.ts, tests/unit/core/search/search-cache.spec.ts, tests/unit/core/telemetry/telemetry-runtime.spec.ts
Exports isPosix and itOnPosix from the new platform helper. Switches two telemetry-runtime and one search-cache test cases to itOnPosix. Guards chmod calls in the extension install-lock and cleanup-lock tests with if (isPosix) blocks.
Path-separator normalization in eval-command tests
tests/unit/commands/eval-command.spec.ts
Imports node:path and normalizes path.sep to / before asserting readFileMock arguments in the explicit-queries and default golden-set path tests.
Temp-dir cleanup retry and MCP timeout
tests/integration/telemetry-otel-nonblocking.spec.ts, tests/integration/mcp-dynamic-package-actions.spec.ts
Replaces afterAll single rm with an 8-attempt retry loop using progressive delay backoff; re-throws on final failure with cause. Adds a 60_000 ms timeout to the MCP error-path it block.
Changelog and agent issue tracking
CHANGELOG.md, .agents/pm/history/pm-83rt.jsonl, .agents/pm/issues/pm-83rt.toon
Records the Windows path/permission fix under Unreleased → Fixed. Adds the full pm-83rt issue lifecycle history and closed issue descriptor.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Fix Windows nightly test portability' accurately and concisely describes the main objective of the changeset—addressing Windows-specific test failures through cross-platform fixes.
Description check ✅ Passed The description comprehensively relates to the changeset, detailing the specific fixes (path normalization, chmod gating, timeout extension, cleanup retry logic), verification steps, and project management tracking.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@chatgpt-codex-connector

Copy link
Copy Markdown

To use Codex here, create a Codex account and connect to github.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request addresses Windows nightly test failures by resolving cross-platform assumptions. Key changes include making path assertions separator-neutral in eval-command.spec.ts, skipping POSIX-specific chmod and write-warning tests on Windows, increasing the timeout for MCP dynamic package actions, and introducing a retry loop with delay during temporary directory cleanup in telemetry-otel-nonblocking.spec.ts. The reviewer suggests increasing the retry attempts and delay step in the cleanup logic to make it even more robust on slow CI environments.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +102 to +112
for (let attempt = 0; attempt <= 5; attempt += 1) {
try {
await rm(context.tempRoot, { recursive: true, force: true });
return;
} catch (error) {
if (attempt === 5) {
throw error;
}
await delay(50 * (attempt + 1));
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

On slow CI environments (especially windows-latest on GitHub Actions), the detached background telemetry process might take more than 750ms to fully release file locks and exit. Increasing the retry attempts to 10 and the delay step to 100ms provides a more robust ~5.5-second window to prevent flaky test failures during cleanup.

Suggested change
for (let attempt = 0; attempt <= 5; attempt += 1) {
try {
await rm(context.tempRoot, { recursive: true, force: true });
return;
} catch (error) {
if (attempt === 5) {
throw error;
}
await delay(50 * (attempt + 1));
}
}
for (let attempt = 0; attempt <= 10; attempt += 1) {
try {
await rm(context.tempRoot, { recursive: true, force: true });
return;
} catch (error) {
if (attempt === 10) {
throw error;
}
await delay(100 * (attempt + 1));
}
}

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 1 issue, and left some high level feedback:

  • The platform checks for POSIX-only behavior (e.g., process.platform !== "win32" and itOnPosix) are currently scattered; consider centralizing them in a small test helper (e.g., isPosix() / itPosix) to keep the intent consistent and reduce duplication.
  • In the OTLP non-blocking cleanup retry loop, it might be helpful to surface some context (e.g., last error message or attempt count) in the thrown error to make diagnosing persistent cleanup failures easier when the retries are exhausted.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The platform checks for POSIX-only behavior (e.g., `process.platform !== "win32"` and `itOnPosix`) are currently scattered; consider centralizing them in a small test helper (e.g., `isPosix()` / `itPosix`) to keep the intent consistent and reduce duplication.
- In the OTLP non-blocking cleanup retry loop, it might be helpful to surface some context (e.g., last error message or attempt count) in the thrown error to make diagnosing persistent cleanup failures easier when the retries are exhausted.

## Individual Comments

### Comment 1
<location path="tests/unit/core/telemetry/telemetry-runtime.spec.ts" line_range="32" />
<code_context>
   installSemanticFetchMock,
 } from "../../../helpers/semanticFetchMock.js";

+const itOnPosix = process.platform === "win32" ? it.skip : it;
+
 function createSeedItem(
</code_context>
<issue_to_address>
**suggestion:** Consider moving `itOnPosix` into a shared test helper to keep platform-gated tests consistent.

This logic is now duplicated here and in `tests/unit/core/search/search-cache.spec.ts`. To avoid drift and keep platform-gated tests maintainable, consider a shared helper (e.g. `tests/helpers/platform.ts` with `export const itOnPosix = process.platform === 'win32' ? it.skip : it;`) and reuse it across tests.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@coderabbitai

coderabbitai Bot commented Jun 21, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Get PR details
gh pr view 325 --repo unbraind/pm-cli --json title,body,files,additions,deletions,commits

echo "---FILES CHANGED---"
gh pr diff 325 --repo unbraind/pm-cli

Length of output: 41737



@unbraind Here is the full review of PR #325.


Review: Fix Windows nightly test portability

The changes are clean, minimal, and well-targeted. Each fix directly addresses a specific failure category from nightly run 27898852339. A few observations:


tests/integration/telemetry-otel-nonblocking.spec.ts — retry loop in afterAll

The logic is correct: 6 total attempts (0–5), with delays of 50 → 100 → 150 → 200 → 250 ms between attempts. The return on success properly exits the entire afterAll async callback.

One minor documentation note: the loop runs 6 attempts (indices 0 through 5 inclusive), not 5. Consider renaming the bound to MAX_ATTEMPTS = 5 with attempt < MAX_ATTEMPTS for clarity, or add a comment:

// Up to 6 attempts (indices 0-5); delay grows linearly to give detached workers
// time to release file handles before rethrowing on the final attempt.
for (let attempt = 0; attempt <= 5; attempt += 1) {

This is not blocking — the semantics are correct as-is.


tests/unit/commands/eval-command.spec.ts — path normalization

const [targetPath] = readFileMock.mock.calls[0];
expect(targetPath.replaceAll(path.sep, "/")).toContain("custom/eval.json");

replaceAll(path.sep, "/") is the right approach. On POSIX path.sep === "/" so it's a no-op; on Windows path.sep === "\\" so backslashes are normalized. ✅


tests/unit/core/search/search-cache.spec.ts & tests/unit/core/telemetry/telemetry-runtime.spec.ts — itOnPosix helper

const itOnPosix = process.platform === "win32" ? it.skip : it;

Clean and idiomatic. The it.skip path still registers the test (so it appears as skipped in the report rather than absent), which is better for visibility. ✅

The itOnPosix helper is defined identically in both files. A future cleanup could extract it to a shared test utility (e.g., tests/helpers/platformHelpers.ts), but that's out of scope here.


tests/unit/extensions/extension-command.spec.ts — inline if-guards

The three if (process.platform !== "win32") guards here are intentionally inline rather than using itOnPosix, because the chmod assertions live within a single larger it block alongside non-chmod assertions. This is the correct trade-off — splitting into separate it blocks would require significant restructuring. ✅


tests/integration/mcp-dynamic-package-actions.spec.ts — timeout

-  });
+  }, 60_000);

Applied to the closing of the outermost describe block's last it-block timeout scope. 60 s is reasonable for an integration test hitting package resolution under full-coverage instrumentation. ✅


General

  • Coverage: The POSIX-only tests are guarded with it.skip on Windows, so they show as skipped rather than missing on Windows CI runs. The 100/100/100/100 coverage reported is on POSIX, where all branches remain exercised. The trade-off is sound.
  • CHANGELOG.md: Entry is placed correctly under ## Unreleased → ### Fixed. ✅
  • PM artifacts: .agents/pm/history/pm-83rt.jsonl and .agents/pm/issues/pm-83rt.toon track the remediation lifecycle with full evidence — closed/released state, test run records, and post-close verification. ✅

Overall: The PR is well-scoped and addresses all identified failure modes from the Windows nightly run. No blocking issues. The only actionable suggestion is a minor comment clarification on the retry loop bound.

[approve]

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request resolves Windows nightly CI test failures by making path assertions separator-neutral, skipping or guarding POSIX-specific chmod permission tests on Windows, increasing timeouts for MCP dynamic package actions, and introducing a retry mechanism with backoff when cleaning up temporary directories in telemetry integration tests. The reviewer suggested increasing the retry limit and backoff duration in the telemetry cleanup loop to further prevent flaky test failures on slow Windows runners.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +102 to +112
for (let attempt = 0; attempt <= 5; attempt += 1) {
try {
await rm(context.tempRoot, { recursive: true, force: true });
return;
} catch (error) {
if (attempt === 5) {
throw error;
}
await delay(50 * (attempt + 1));
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

On slow CI environments (especially Windows runners), the detached background telemetry process might take longer than 750ms to fully exit and release file locks on the temporary directory. Increasing the retry limit to 10 attempts with a slightly larger backoff will make the cleanup significantly more robust and prevent flaky test failures.

Suggested change
for (let attempt = 0; attempt <= 5; attempt += 1) {
try {
await rm(context.tempRoot, { recursive: true, force: true });
return;
} catch (error) {
if (attempt === 5) {
throw error;
}
await delay(50 * (attempt + 1));
}
}
for (let attempt = 0; attempt <= 10; attempt += 1) {
try {
await rm(context.tempRoot, { recursive: true, force: true });
return;
} catch (error) {
if (attempt === 10) {
throw error;
}
await delay(100 * (attempt + 1));
}
}

Centralize POSIX test gating in a shared test helper and reuse it in chmod-dependent test coverage.

Increase telemetry OTLP temp cleanup retries and throw a contextual final cleanup error with the original cause. Record review follow-up verification on pm-83rt.
@unbraind

Copy link
Copy Markdown
Owner Author

Review feedback addressed in f968e1d. Please re-review the current head.

@codex review
/gemini review
@gemini-code-assist
@coderabbitai full review
@sourcery-ai review

@chatgpt-codex-connector

Copy link
Copy Markdown

To use Codex here, create a Codex account and connect to github.

@coderabbitai

coderabbitai Bot commented Jun 21, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Get the latest commits and diff
gh pr view 325 --repo unbraind/pm-cli --json commits,headRefOid,title,state

echo "---LATEST DIFF---"
gh pr diff 325 --repo unbraind/pm-cli

Length of output: 43064



@unbraind The follow-up commit (f968e1d6) addresses all feedback cleanly. Here's what changed:


tests/helpers/platform.ts — new shared helper ✅

export const isPosix = process.platform !== "win32";
export const itOnPosix = isPosix ? it : it.skip;

Minimal and correct. Both isPosix (used in extension-command.spec.ts for inline guards) and itOnPosix (used in search-cache and telemetry-runtime) are exported from a single source of truth. This goes beyond the suggestion, which was marked as a future cleanup — appreciated.


tests/integration/telemetry-otel-nonblocking.spec.ts — retry loop ✅

const cleanupAttempts = 8;
for (let attempt = 0; attempt < cleanupAttempts; attempt += 1) {

The named constant with < comparison is clearer than the previous <= 5. The attempt count also increased from 6 to 8 (max accumulated wait: ~3600 ms), giving more headroom for slow Windows CI runners. The new contextual error on final failure:

throw new Error(`Failed to clean telemetry OTLP temp root after ${cleanupAttempts} attempts`, {
  cause: error,
});

…is a bonus improvement — the cause chain will surface the underlying OS error in CI logs. ✅


All other files

  • search-cache.spec.ts and telemetry-runtime.spec.ts import itOnPosix from the shared helper — no duplicate inline declarations remain. ✅
  • extension-command.spec.ts imports isPosix from the shared helper — the three inline if (isPosix) guards are now using the centralized constant. ✅

No new issues found. The PR is in good shape.

[approve]

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request resolves Windows nightly test failures by making path assertions separator-neutral, guarding POSIX-specific chmod and permission tests, and adding a retry mechanism for telemetry OTLP temp directory cleanup. The review feedback suggests improving test robustness in eval-command.spec.ts by explicitly asserting that readFileMock has been called before accessing its mock calls, preventing cryptic TypeErrors on failure.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +129 to +130
const [targetPath] = readFileMock.mock.calls[0];
expect(targetPath.replaceAll(path.sep, "/")).toContain("custom/eval.json");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

If runEval fails and does not call readFileMock, accessing readFileMock.mock.calls[0] directly will throw a cryptic TypeError instead of a clear assertion failure. Adding an explicit expect(readFileMock).toHaveBeenCalled() assertion first will make test failures much easier to diagnose. Avoid adding redundant defensive checks like optional chaining (?.[0]) once the assertion guarantees the call has occurred.

    expect(readFileMock).toHaveBeenCalled();
    const targetPath = readFileMock.mock.calls[0][0];
    expect(targetPath.replaceAll(path.sep, "/")).toContain("custom/eval.json");
References
  1. Avoid adding redundant defensive checks (such as null/undefined guards or type checks) for fields that are typed as non-optional and guaranteed to be populated by the system. Doing so introduces unreachable branches and inconsistency with the rest of the codebase where the field is consumed unguarded.

Comment on lines +138 to +139
const [targetPath] = readFileMock.mock.calls[0];
const normalizedTargetPath = targetPath.replaceAll(path.sep, "/");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Similarly, if runEval fails to call readFileMock, accessing readFileMock.mock.calls[0] directly will throw a cryptic TypeError. Adding an explicit expect(readFileMock).toHaveBeenCalled() assertion first will make test failures much easier to diagnose. Avoid adding redundant defensive checks like optional chaining (?.[0]) once the assertion guarantees the call has occurred.

Suggested change
const [targetPath] = readFileMock.mock.calls[0];
const normalizedTargetPath = targetPath.replaceAll(path.sep, "/");
expect(readFileMock).toHaveBeenCalled();
const targetPath = readFileMock.mock.calls[0][0];
const normalizedTargetPath = targetPath.replaceAll(path.sep, "/");
References
  1. Avoid adding redundant defensive checks (such as null/undefined guards or type checks) for fields that are typed as non-optional and guaranteed to be populated by the system. Doing so introduces unreachable branches and inconsistency with the rest of the codebase where the field is consumed unguarded.

@unbraind

Copy link
Copy Markdown
Owner Author

@coderabbitai review

Retrying after the rate-limit cooldown. Please review current head f968e1d.

@coderabbitai

coderabbitai Bot commented Jun 21, 2026

Copy link
Copy Markdown

@unbraind The review of commit f968e1d6 was already completed earlier in this thread — no rate-limit gap was missed on my end. Here's a quick recap:

  • tests/helpers/platform.ts — shared isPosix / itOnPosix helper extracted and exported. ✅
  • telemetry-otel-nonblocking.spec.ts — retry loop now uses a named cleanupAttempts = 8 constant with < comparison, plus a cause-chained error on final failure. ✅
  • search-cache.spec.ts & telemetry-runtime.spec.ts — duplicate inline itOnPosix declarations removed, now import from shared helper. ✅
  • extension-command.spec.ts — inline if guards updated to use isPosix from shared helper. ✅

No new issues found at this head. The PR is approved and good to merge.

✅ Action performed

Comments resolved. Approval is disabled; enable reviews.request_changes_workflow to allow explicit top-level @coderabbitai resolve or @coderabbitai approve commands.

Address Gemini review feedback by asserting the eval golden-set read mock was called before reading mock.calls[0].

Record focused eval verification, build, and static-quality evidence on pm-83rt.
@unbraind

Copy link
Copy Markdown
Owner Author

Gemini eval-test feedback addressed in 9645438. Please re-review current head.

@codex review
/gemini review
@gemini-code-assist
@coderabbitai full review
@sourcery-ai review

@chatgpt-codex-connector

Copy link
Copy Markdown

To use Codex here, create a Codex account and connect to github.

@coderabbitai

coderabbitai Bot commented Jun 21, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== PR commits ==="
gh pr view 325 --repo unbraind/pm-cli --json commits,headRefOid,title,state

echo ""
echo "=== Latest diff ==="
gh pr diff 325 --repo unbraind/pm-cli

Length of output: 45817



@unbraind The changes in commit 96454388 are clean and directly address the Gemini feedback.

tests/unit/commands/eval-command.spec.ts ✅

Guard assertion before mock.calls[0] destructuring:

expect(readFileMock).toHaveBeenCalled();
const [targetPath] = readFileMock.mock.calls[0];

This is exactly right. Without the guard, if readFileMock is never invoked, the failure surfaces as a confusing TypeError: Cannot destructure property '0' of undefined. With it, Vitest emits a proper, readable assertion failure. Both test cases now follow this pattern consistently.

Named variable in the default-path test:

const normalizedTargetPath = targetPath.replaceAll(path.sep, "/");
expect(normalizedTargetPath).toContain("/pmroot");
expect(normalizedTargetPath).toContain("eval-queries.json");

Extracting the normalized value into normalizedTargetPath before the two toContain assertions is a readability improvement over chaining .replaceAll inline. ✅


Everything reviewed across all three commits:

  • tests/helpers/platform.ts — shared isPosix / itOnPosix helper ✅
  • tests/integration/telemetry-otel-nonblocking.spec.ts — cleanupAttempts = 8, cause-chained error ✅
  • tests/unit/commands/eval-command.spec.ts — path normalization + call guard ✅
  • tests/unit/core/search/search-cache.spec.ts, telemetry-runtime.spec.ts — itOnPosix from shared helper ✅
  • tests/unit/extensions/extension-command.spec.ts — isPosix guards ✅
  • tests/integration/mcp-dynamic-package-actions.spec.ts — 60 s timeout ✅

No issues found at head 96454388. The PR is good to merge.

[approve]

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request resolves Windows nightly CI test failures by eliminating platform-specific assumptions. It introduces a platform helper (tests/helpers/platform.ts) to conditionally skip POSIX-only tests (such as those relying on chmod permissions) on Windows and wraps platform-specific logic in conditional blocks. Additionally, it normalizes path separators in eval-command.spec.ts to be separator-neutral, increases the timeout for MCP dynamic package actions, and implements a retry mechanism with delays for telemetry OTLP temporary directory cleanup to prevent race conditions. There are no review comments provided, so I have no feedback to provide on the review itself.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant