Skip to content

fix(release): bound Sentry gate to a recent-activity window + alert on blocked daily releases - #305

Merged
unbraind merged 4 commits into
mainfrom
fix/auto-release-sentry-gate-window-and-alerting
Jun 19, 2026
Merged

unbraind merged 4 commits into
mainfrom
fix/auto-release-sentry-gate-window-and-alerting

Conversation

@unbraind

@unbraind unbraind commented Jun 19, 2026 •

Copy link
Copy Markdown
Owner

Summary

Hardens daily auto-release reliability so a single stale Sentry error can no longer silently block every release, and so blocked scheduled releases are surfaced instead of skipped. Also folds in the verifiable cross-platform test fixes for the Windows nightly.

Closes pm-nb08; partial progress on pm-i84i (separator portion).

pm-nb08 — Sentry gate recent-activity window + blocked-release alerting

The sentry-telemetry-gate queried is:unresolved level:[fatal,error] with no time bound, so any lingering unresolved fatal/error issue blocked every scheduled release until someone resolved it in Sentry — silently, with no alert (3 releases skipped 06-14..16, per pm-nb08).

  • scripts/release/sentry-telemetry-gate.mjs: new --sentry-window-days flag (default 14, 0 = unbounded legacy) appends Sentry's lastSeen:-Nd relative-date filter. A stale benign issue that stopped firing no longer gates; an actively firing error still does. window_days is surfaced in the JSON + human-readable output.
  • scripts/release/run-gates.mjs + .github/workflows/release.yml: thread / invoke the gate with --sentry-window-days 14.
  • .github/workflows/auto-release.yml: opens/updates an "Auto Release blocked" GitHub issue on scheduled-run failure (mirrors the existing pm-ehbb nightly-failure alert) so a blocked daily release is never silently skipped.
  • docs/RELEASING.md: documents the window + alerting.

lastSeen (not age/firstSeen) is deliberate: it gates on recent activity, so an old issue first seen long ago but still erroring continues to block, while one that aged out does not.

pm-i84i — cross-platform test hardening (partial)

Fixes the two hardcoded POSIX-separator assertions that fail the windows-latest nightly:

  • init-command.spec.ts now asserts path.resolve("/repo", "/repo/.agents/pm") (the actual resolvePmRoot output) instead of a forward-slash literal.
  • schema-command.spec.ts now asserts path.join(".agents", "pm", "schema", "types.json") (the path.join-built hint path) instead of a forward-slash literal.
  • New runtime-schema-path-win32-guard.spec.ts mocks node:path → path.win32 so a POSIX per-PR run catches a schema-path separator regression rather than only the nightly.

The file://-URL TS dynamic-import cluster (the bulk of the nightly failures) stays open in pm-i84i — it needs a Windows runner to verify, and a per-PR windows-latest matrix decision.

Verification

  • ✅ Live Sentry: lastSeen:-14d query accepted, checked=true, critical=0 high=0.
  • ✅ Coverage 100/100/100/100 (4687 tests); static quality gate; typecheck.
  • ✅ pnpm changelog:pm:check passes (CHANGELOG regenerated with the pm-nb08 Fixed entry).
  • ✅ Full manual smoke test in a temp dir: init, create, custom schema type, invalid-type hint, update, search, close, validate (ok:true), health, gc — all green.

Contract coverage

  • release-automation-contract.spec.ts: new test locks buildSentryGateQuery + the --sentry-window-days 14 invocation in release.yml/run-gates.
  • ci-workflow-contract.spec.ts: locks the release.yml gate invocation and the new auto-release blocked-release alert step.

🤖 Generated with Claude Code

Summary by Sourcery

Bound the Sentry-based release reliability gate to a configurable recent-activity window and added alerting for blocked scheduled auto-releases, while hardening tests for cross-platform path handling and release automation contracts.

Bug Fixes:

  • Prevent stale unresolved Sentry issues from indefinitely blocking daily auto-releases by introducing a recent-activity window on the Sentry gate query.
  • Fix POSIX-only path assertions in init and schema command tests so they pass on Windows runners.

Enhancements:

  • Expose a configurable --sentry-window-days flag in the Sentry telemetry gate and thread it through the release gates script and workflow, including JSON and human-readable output.
  • Add GitHub workflow logic to open or update an 'Auto Release blocked' issue when scheduled auto-release runs fail before publishing.
  • Expand contract tests to lock in Sentry gate query construction, gate invocation parameters, and blocked auto-release alerting behavior.

Documentation:

  • Document the Sentry reliability gate’s recent-activity window and the new auto-release blocked issue alerting in the releasing guide.

Tests:

  • Add unit tests for the Sentry gate recent-activity window behavior and validation of the new flag, update run-gates tests for the threaded window parameter, and introduce a win32-mocked schema path guard test to catch separator regressions on POSIX CI.

…n blocked daily releases

Daily auto-release reliability (pm-nb08): the sentry-telemetry-gate queried
`is:unresolved level:[fatal,error]` with no time bound, so any single stale
unresolved fatal/error issue blocked *every* scheduled release until manually
resolved in Sentry — silently, with no alerting (3 releases skipped 06-14..16).

- sentry-telemetry-gate.mjs: new `--sentry-window-days` flag (default 14, 0 =
  unbounded legacy) appends Sentry's `lastSeen:-Nd` relative-date filter so a
  stale benign issue that stopped firing no longer blocks releases; an actively
  firing error still gates. `window_days` surfaced in JSON + text output.
- run-gates.mjs + release.yml: thread/invoke the gate with `--sentry-window-days 14`.
- auto-release.yml: open/update an "Auto Release blocked" GitHub issue on
  scheduled failure (mirrors the pm-ehbb nightly-failure alert) so blocked daily
  releases are never silently skipped.
- docs/RELEASING.md: document the window + blocked-release alerting.

Cross-platform test hardening (pm-i84i, partial): fix the two hardcoded
POSIX-separator assertions that fail the windows-latest nightly — init-command
asserts `path.resolve(...)` and schema-command asserts `path.join(...)` instead
of forward-slash literals — and add a win32-simulated guard
(runtime-schema-path-win32-guard.spec.ts) so a POSIX per-PR run catches a
schema-path separator regression. The `file://`-URL TS dynamic-import cluster
remains open (needs a Windows runner to verify).

Verified live against Sentry (lastSeen:-14d query accepted, high=0), full smoke
test green, coverage 100/100/100/100 (4687 tests), static gate + changelog check pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RRyLiTvXUw6EQRTvXSufn3
@sourcery-ai

sourcery-ai Bot commented Jun 19, 2026 •

Copy link
Copy Markdown

Reviewer's Guide

Adds a configurable recent-activity window to the Sentry release gate and wires it through release/auto-release workflows with alerting for blocked scheduled runs, plus fixes and guards around path-separator-sensitive tests to keep Windows CI green.

Sequence diagram for auto-release blocked-run GitHub alert

sequenceDiagram
  actor Scheduler
  participant GitHub_Actions as GitHub_Actions_auto-release
  participant Release_Job as release_job
  participant Alert_Step as Alert_on_blocked_scheduled_auto-release
  participant GitHub_API as GitHub_API

  Scheduler->>GitHub_Actions: schedule event
  GitHub_Actions->>Release_Job: run jobs
  Release_Job-->>GitHub_Actions: failure()
  GitHub_Actions->>Alert_Step: run bash alert step
  Alert_Step->>GitHub_API: gh issue list --search Auto Release blocked
  GitHub_API-->>Alert_Step: existing issue number or empty
  alt existing issue
    Alert_Step->>GitHub_API: gh issue comment <number>
  else no existing issue
    Alert_Step->>GitHub_API: gh issue create --title Auto Release blocked
  end
Loading

Flow diagram for Sentry gate recent-activity window usage

flowchart LR
  A[run-gates.mjs] -->|reads --sentry-window-days| B[sentry-telemetry-gate.mjs]
  B -->|parseNumber sentry-window-days| C[sentryWindowDays]
  C --> D[buildSentryGateQuery]
  D -->|returns query with lastSeen:-Nd when windowDays>0| E[fetchSentryIssues]
  E -->|query Sentry API| F[Sentry]
  E --> G[sentrySummary]
  G --> H[release gate decision]
Loading

File-Level Changes

Change Details Files
Introduce a configurable Sentry recent-activity window for the release reliability gate and surface it in outputs.
  • Add buildSentryGateQuery(windowDays) to construct the Sentry search query using lastSeen with a default 14-day window and support for 0 = unbounded.
  • Extend CLI parsing and usage in the Sentry gate script to accept --sentry-window-days, defaulting to 14 and validating against negative values.
  • Pass the computed sentryWindowDays into fetchSentryIssues, include window_days in the JSON payload, and log sentry_window_days in human-readable success/failure messages.
  • Add unit tests to verify default/custom/zero-window behavior and validation errors for negative --sentry-window-days values.
scripts/release/sentry-telemetry-gate.mjs
tests/unit/scripts/release/sentry-telemetry-gate.spec.ts
Thread the Sentry window configuration through the gates runner and CI workflows, and document the behavior.
  • Add --sentry-window-days support and defaulting in run-gates.mjs and propagate it to the sentry-telemetry-gate invocation.
  • Update release.yml and its contract tests to invoke the Sentry gate with --sentry-window-days 14.
  • Extend the run-gates unit test to assert the full Sentry gate command including the window flag.
  • Document the Sentry recent-activity window and auto-release blocked-issue alerting in RELEASING.md and add a corresponding changelog entry.
scripts/release/run-gates.mjs
.github/workflows/release.yml
tests/unit/scripts/release/run-gates.spec.ts
tests/integration/release-automation-contract.spec.ts
CHANGELOG.md
docs/RELEASING.md
Alert when scheduled auto-release runs are blocked instead of silently skipping releases.
  • Add a GitHub Actions step that runs on scheduled failures to open or update an "Auto Release blocked" issue with run and commit details.
  • Update CI workflow contract tests to lock the new alerting step and its key strings/conditions.
.github/workflows/auto-release.yml
tests/integration/ci-workflow-contract.spec.ts
Harden cross-platform tests around path separators and add a Windows-specific guard for schema paths.
  • Update init-command tests to assert platform-native pmRoot via path.resolve instead of a POSIX-only literal.
  • Update schema-command tests to assert the schema types.json hint path using path.join instead of a hardcoded forward-slash path.
  • Add a runtime-schema-path-win32-guard.spec.ts test that mocks node:path to path.win32 so POSIX CI can catch Windows separator regressions.
tests/unit/commands/init-command.spec.ts
tests/unit/commands/schema-command.spec.ts
tests/unit/core/schema/runtime-schema-path-win32-guard.spec.ts

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

@coderabbitai full review

@unbraind

Copy link
Copy Markdown
Owner Author

@codex review

@unbraind

Copy link
Copy Markdown
Owner Author

/gemini 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 19, 2026 •

Copy link
Copy Markdown
✅ Action performed

Full review finished.

@coderabbitai

coderabbitai Bot commented Jun 19, 2026 •

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@unbraind, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 22 minutes and 18 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, the refill rate gradually slows as usage increases. The highest same-day bursts are limited more strictly.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

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

Review profile: CHILL

Plan: Pro

Run ID: 345d8a7b-d4d2-4e13-a5a1-6c4be7820d66

📥 Commits

Reviewing files that changed from the base of the PR and between c9a0a73 and 447816d.

📒 Files selected for processing (17)
  • .agents/pm/history/pm-i84i.jsonl
  • .agents/pm/history/pm-nb08.jsonl
  • .agents/pm/issues/pm-i84i.toon
  • .agents/pm/issues/pm-nb08.toon
  • .github/workflows/auto-release.yml
  • .github/workflows/release.yml
  • CHANGELOG.md
  • docs/RELEASING.md
  • scripts/release/run-gates.mjs
  • scripts/release/sentry-telemetry-gate.mjs
  • tests/integration/ci-workflow-contract.spec.ts
  • tests/integration/release-automation-contract.spec.ts
  • tests/unit/commands/init-command.spec.ts
  • tests/unit/commands/schema-command.spec.ts
  • tests/unit/core/schema/runtime-schema-path-win32-guard.spec.ts
  • tests/unit/scripts/release/run-gates.spec.ts
  • tests/unit/scripts/release/sentry-telemetry-gate.spec.ts
📝 Walkthrough

Walkthrough

Two independent fixes are shipped together. First, the Sentry telemetry release gate gains a --sentry-window-days flag (default 14) that bounds the unresolved-issue query to recent activity, replacing the previously unbounded query that caused silent auto-release blockage; a new alerting step in auto-release.yml opens or updates a GitHub issue on scheduled failures. Second, unit tests replace hardcoded POSIX paths with platform-native path.resolve/path.join calls and a new win32-mocked regression guard spec is added for filePathForSchemaSection.

Changes

Sentry Gate Windowing and Blocked-Release Alerting

Layer / File(s) Summary
buildSentryGateQuery and --sentry-window-days implementation
scripts/release/sentry-telemetry-gate.mjs
Adds buildSentryGateQuery(windowDays) to construct an optional lastSeen:-Nd bounded Sentry query; extends parseNumber with an { integer: true } option; parses --sentry-window-days (default 14); threads the query into fetchSentryIssues; emits window_days in JSON and console output.
Gate wiring through run-gates.mjs and release.yml
scripts/release/run-gates.mjs, .github/workflows/release.yml
run-gates.mjs parses and forwards --sentry-window-days to sentry-telemetry-gate; release.yml invokes the gate with --sentry-window-days 14.
Blocked scheduled-release alerting step
.github/workflows/auto-release.yml
Adds a if: failure() && github.event_name == 'schedule' step that uses gh issue list, gh issue comment, and gh issue create to open or update an "Auto Release blocked" issue with run URL and commit SHA.
Unit and integration tests for windowing and alerting
tests/unit/scripts/release/sentry-telemetry-gate.spec.ts, tests/unit/scripts/release/run-gates.spec.ts, tests/integration/ci-workflow-contract.spec.ts, tests/integration/release-automation-contract.spec.ts
Unit tests cover --sentry-window-days arg validation, 14-day default, custom window, and 0 (unbounded) behavior. Integration contract tests assert --sentry-window-days 14 in release.yml/run-gates.mjs and verify the alert step structure in auto-release.yml.
Docs, CHANGELOG, and PM tracking
docs/RELEASING.md, CHANGELOG.md, .agents/pm/issues/pm-nb08.toon, .agents/pm/history/pm-nb08.jsonl
RELEASING.md documents --sentry-window-days bounding and the blocked-release alerting behavior; CHANGELOG.md records the fix; pm-nb08 issue and history records are closed with resolution details and PR reference.

Windows Path Separator Fixes and Regression Guard

Layer / File(s) Summary
Platform-native path assertions and win32 guard spec
tests/unit/commands/init-command.spec.ts, tests/unit/commands/schema-command.spec.ts, tests/unit/core/schema/runtime-schema-path-win32-guard.spec.ts, .agents/pm/issues/pm-i84i.toon, .agents/pm/history/pm-i84i.jsonl
init-command.spec.ts and schema-command.spec.ts replace hardcoded POSIX strings with path.resolve/path.join calls. A new win32 guard spec mocks node:path to win32 and asserts filePathForSchemaSection uses backslash separators. pm-i84i tracking records are updated with the shipped files and remaining open work.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 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 clearly and specifically summarizes the two main changes: bounding the Sentry gate to a recent-activity window and adding alerting for blocked daily releases, which directly align with the primary objectives of the changeset.
Description check ✅ Passed The description is comprehensive and directly related to the changeset, clearly explaining the motivation, implementation details, and verification for both the Sentry gate window and blocked-release alerting features, as well as the cross-platform test fixes.
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.


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.

@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 release-automation-contract test that checks for "`${baseQuery} lastSeen:-${windowDays}d`" in sentry-telemetry-gate.mjs is quite brittle to any refactor of spacing or interpolation; consider asserting on a more stable snippet (e.g., just lastSeen:-${windowDays}d or using a small regex) so the contract still holds if the implementation is reformatted.
  • The run-gates.spec.ts expectation that joins the entire spawn command and looks for the full sentry-telemetry-gate.mjs --json --telemetry-mode best-effort --sentry-window-days 14 string is sensitive to argument ordering changes; you could make this more robust by asserting presence of individual args/values in the array instead of a single concatenated substring.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The `release-automation-contract` test that checks for ``"`${baseQuery} lastSeen:-${windowDays}d`"`` in `sentry-telemetry-gate.mjs` is quite brittle to any refactor of spacing or interpolation; consider asserting on a more stable snippet (e.g., just `lastSeen:-${windowDays}d` or using a small regex) so the contract still holds if the implementation is reformatted.
- The `run-gates.spec.ts` expectation that joins the entire spawn command and looks for the full `sentry-telemetry-gate.mjs --json --telemetry-mode best-effort --sentry-window-days 14` string is sensitive to argument ordering changes; you could make this more robust by asserting presence of individual args/values in the array instead of a single concatenated substring.

## Individual Comments

### Comment 1
<location path="CHANGELOG.md" line_range="22" />
<code_context>

 ### Fixed

+- Daily auto-release silently blocked 06-14..16 by a single stale unresolved Sentry error \(sentry-telemetry-gate is:unresolved has no time window\) ([pm-nb08](https://github.com/unbraind/pm-cli/blob/main/.agents/pm/issues/pm-nb08.toon))
 - appendLineAtomic is not truly atomic: concurrent appends to history JSONL can interleave ([pm-xy9n](https://github.com/unbraind/pm-cli/blob/main/.agents/pm/issues/pm-xy9n.toon))
 - Project-scope extension install writes ~69MB node\_modules per workspace \(peer pm-cli + transitive Sentry/OTel\) ([pm-oxq2](https://github.com/unbraind/pm-cli/blob/main/.agents/pm/issues/pm-oxq2.toon))
</code_context>
<issue_to_address>
**issue (typo):** Add a missing verb and optional comma for grammatical clarity.

The sentence is missing a verb. Consider: “Daily auto-release was silently blocked … by a single stale, unresolved Sentry error …” for grammatical completeness and clarity.

```suggestion
- Daily auto-release was silently blocked 06-14..16 by a single stale, unresolved Sentry error \(sentry-telemetry-gate is:unresolved has no time window\) ([pm-nb08](https://github.com/unbraind/pm-cli/blob/main/.agents/pm/issues/pm-nb08.toon))
```
</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.

Comment thread CHANGELOG.md Resolved

@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 implements a durable fix for daily auto-releases being blocked by stale unresolved Sentry errors by introducing a configurable recent-activity window (--sentry-window-days, defaulting to 14 days) to the Sentry telemetry gate. It also addresses Windows-specific path separator failures in the test suite by replacing hardcoded POSIX separators with platform-native path utilities and adding a simulated win32 regression guard. The review feedback suggests validating that the --sentry-window-days parameter is an integer to prevent Sentry API errors, and adding corresponding unit tests while ensuring dash-prefixed argument values are handled unambiguously.

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.

const outputJson = flagBool(flags, "json", false);
const sentryProject = flagString(flags, "sentry-project", "unbrained/pm-cli");
const sentryLimit = parseNumber(flagString(flags, "sentry-limit", null), "sentry-limit", 200);
const sentryWindowDays = parseNumber(flagString(flags, "sentry-window-days", null), "sentry-window-days", 14);

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

The --sentry-window-days parameter is parsed as a generic number, but Sentry's relative date query syntax (e.g., lastSeen:-Nd) expects an integer number of days. If a decimal value (such as 14.5) is provided, Sentry may return a 400 Bad Request or ignore the filter, leading to unexpected gate failures or bypasses.

Consider validating that sentryWindowDays is an integer.

Suggested change
const sentryWindowDays = parseNumber(flagString(flags, "sentry-window-days", null), "sentry-window-days", 14);
const sentryWindowDays = parseNumber(flagString(flags, "sentry-window-days", null), "sentry-window-days", 14);
if (!Number.isInteger(sentryWindowDays)) {
fail("Invalid --sentry-window-days value \"" + sentryWindowDays + "\". Expected an integer.");
}

Comment on lines +137 to +140
it("fails on a negative --sentry-window-days value", async () => {
const { errors } = await runSentryGate({ argv: ["--sentry-window-days", "-3"] });
expect(errors.join("\n")).toContain('Invalid --sentry-window-days value "-3"');
});

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

To complement the integer validation for --sentry-window-days, we should add a unit test to verify that decimal values are rejected. Note that when passing dash-prefixed values (like negative numbers) in command-line arguments, we should use the unambiguous key=value format (e.g., --sentry-window-days=-3) instead of passing them as separate positional tokens, to prevent them from being mistaken for flags.

  it("fails on a negative --sentry-window-days value", async () => {
    const { errors } = await runSentryGate({ argv: ["--sentry-window-days=-3"] });
    expect(errors.join("\n")).toContain('Invalid --sentry-window-days value "-3"');
  });

  it("fails on a non-integer --sentry-window-days value", async () => {
    const { errors } = await runSentryGate({ argv: ["--sentry-window-days=14.5"] });
    expect(errors.join("\n")).toContain('Invalid --sentry-window-days value "14.5"');
  });
References
  1. When pre-parsing or normalizing command-line arguments, avoid treating dash-prefixed tokens (starting with "-") as positional values to prevent them from being mistaken for actual flags. Direct users to unambiguous formats (e.g., "key=value" or JSON) for dash-leading values.

@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 introduces a configurable recent-activity window (--sentry-window-days, defaulting to 14 days) to the Sentry telemetry gate query to prevent stale, benign unresolved issues from blocking scheduled releases. It also adds alerting for blocked scheduled releases by opening or updating a GitHub issue on failure, and resolves cross-platform test failures on Windows by replacing hardcoded POSIX path separators with OS-native path helpers and adding a win32-simulated regression guard. The review feedback suggests truncating the windowDays parameter to an integer to prevent invalid Sentry query syntax if a non-integer value is provided.

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 +215 to +217
if (windowDays <= 0) {
return baseQuery;
}

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 a non-integer value is passed to --sentry-window-days (e.g., 14.5), the generated Sentry query will contain lastSeen:-14.5d, which is invalid in Sentry's relative date query syntax and can cause the API request to fail. To prevent this, we should ensure windowDays is truncated to an integer using Math.floor() before constructing the query.

Suggested change
if (windowDays <= 0) {
return baseQuery;
}
if (windowDays <= 0) {
return baseQuery;
}
windowDays = Math.floor(windowDays);

@unbraind

Copy link
Copy Markdown
Owner Author

Thanks for the reviews. Addressed in the follow-up commit:

Gemini (medium) — integer validation for --sentry-window-days: valid. Sentry's lastSeen:-Nd relative-date syntax only accepts whole days, so a decimal window would produce a malformed query (400 / ignored filter). parseNumber now takes an opt-in { integer: true } and the window flag uses it; added a unit test asserting --sentry-window-days 14.5 is rejected. (Note: the gate's parseFlags only supports --key value, not --key=value; single-dash values like -3 are already captured correctly as values rather than flags, so the existing negative test stays as-is.)

Sourcery — CHANGELOG.md grammar: declined. CHANGELOG.md is fully auto-generated by pm-changelog from closed tracker-item titles (regenerated every release); a hand-edit there would be overwritten on the next pnpm changelog:pm. The wording comes from the pm-nb08 item title and is intentionally terse.

Re-running the bots below.

Sentry's `lastSeen:-Nd` relative-date syntax only accepts whole days, so a
decimal window (e.g. 14.5) would produce a malformed query that Sentry rejects
(400) or silently ignores. parseNumber gains an opt-in `{ integer: true }` and
the window flag uses it; added a unit test asserting `--sentry-window-days 14.5`
is rejected.

Coverage 100/100/100/100.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RRyLiTvXUw6EQRTvXSufn3
@unbraind

Copy link
Copy Markdown
Owner Author

@coderabbitai full review

@unbraind

Copy link
Copy Markdown
Owner Author

/gemini review

@coderabbitai

coderabbitai Bot commented Jun 19, 2026 •

Copy link
Copy Markdown
✅ Action performed

Full review finished.

@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 introduces a configurable recent-activity window (--sentry-window-days, defaulting to 14 days) to the Sentry release gate to prevent stale, unresolved errors from blocking scheduled releases, and adds GitHub issue alerting for blocked auto-releases. It also resolves cross-platform test failures on Windows by normalizing hardcoded POSIX path separators and introducing a win32-simulated regression guard. The code review feedback correctly identifies that the updated parseNumber utility in sentry-telemetry-gate.mjs silently converts empty or whitespace-only strings to 0 (unbounded) instead of throwing an error, and suggests explicitly validating against empty strings.

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 +356 to 364
function parseNumber(value, key, fallback, { integer = false } = {}) {
if (value === null) {
return fallback;
}
const parsed = Number(value);
if (!Number.isFinite(parsed) || parsed < 0) {
if (!Number.isFinite(parsed) || parsed < 0 || (integer && !Number.isInteger(parsed))) {
fail(`Invalid --${key} value "${value}".`);
}
return parsed;

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

The parseNumber function currently converts empty or whitespace-only strings to 0 because Number("") and Number(" ") evaluate to 0. This can lead to unexpected behavior where passing an empty string to --sentry-window-days (or other numeric flags) silently disables the window (setting it to 0 / unbounded) instead of failing with an invalid value error.

Consider explicitly rejecting empty or whitespace-only strings before passing them to Number().

function parseNumber(value, key, fallback, { integer = false } = {}) {
  if (value === null) {
    return fallback;
  }
  if (typeof value === "string" && value.trim() === "") {
    fail("Invalid --" + key + " value \"" + value + "\".");
  }
  const parsed = Number(value);
  if (!Number.isFinite(parsed) || parsed < 0 || (integer && !Number.isInteger(parsed))) {
    fail("Invalid --" + key + " value \"" + value + "\".");
  }
  return parsed;
}

Reject blank numeric Sentry window values instead of coercing them to zero, and make the Sentry window contract tests less brittle about command argument ordering and source formatting.

Regenerate the pm-changelog-owned changelog from the corrected pm-nb08 title and record PR #305 verification, temp-dir smoke, GitHub alert, dependency, Sentry, telemetry, and coverage evidence on pm-i84i.
@unbraind

Copy link
Copy Markdown
Owner Author

@coderabbitai full review

@unbraind

Copy link
Copy Markdown
Owner Author

@codex review

@unbraind

Copy link
Copy Markdown
Owner Author

@gemini-code-assist

@unbraind

Copy link
Copy Markdown
Owner Author

/gemini review

@chatgpt-codex-connector

Copy link
Copy Markdown

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

@gemini-code-assist

Copy link
Copy Markdown

Thanks for the update, @unbraind. I've reviewed the final state of the pull request, including the follow-up commit addressing the integer validation for --sentry-window-days and the robust cross-platform test fixes. The implementation is clean, follows best practices, and the added regression guard for Windows path separators is a great proactive measure. The changes effectively resolve the issues described in pm-nb08 and pm-i84i while maintaining test coverage. Everything looks solid and ready for merge.

@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 issues with the daily auto-release being silently blocked by stale Sentry errors and addresses Windows-specific test failures due to hardcoded POSIX path separators. It introduces a configurable --sentry-window-days flag (defaulting to 14 days) to bound Sentry queries to a recent-activity window, adds alerting to open GitHub issues on scheduled release failures, and normalizes path assertions in unit tests using platform-native helpers. The review feedback correctly points out a potential TypeError in sentry-telemetry-gate.mjs where checking value === null fails to guard against undefined values before calling value.trim(), and suggests using loose equality value == null as a fix.

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 357 to 359
if (value === null) {
return fallback;
}

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

Using strict equality value === null does not guard against undefined values. If value is undefined, calling value.trim() on line 363 will throw a TypeError: Cannot read properties of undefined (reading 'trim'). Using loose equality value == null is the idiomatic way in JavaScript to safely check for both null and undefined.

Suggested change
if (value === null) {
return fallback;
}
if (value == null) {
return fallback;
}

@coderabbitai

coderabbitai Bot commented Jun 19, 2026 •

Copy link
Copy Markdown
✅ Action performed

Full review finished.

Treat null and undefined numeric flag values as missing before trimming in the Sentry telemetry gate parser, addressing the Gemini current-head defensive review.

Verified with the Sentry gate focused spec, static quality, changelog check, and full 100/100/100/100 coverage.
@unbraind

Copy link
Copy Markdown
Owner Author

/gemini review

@unbraind

Copy link
Copy Markdown
Owner Author

@codex review

@unbraind

Copy link
Copy Markdown
Owner Author

@gemini-code-assist

@unbraind

Copy link
Copy Markdown
Owner Author

@coderabbitai full 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 19, 2026 •

Copy link
Copy Markdown
✅ Action performed

Full review finished.

@gemini-code-assist

Copy link
Copy Markdown

Thanks for re-triggering the review, @unbraind. As I noted previously, the changes look solid and address the identified issues effectively. Since all feedback has been incorporated and the test suite is passing, my assessment remains that this pull request is ready for merge.

@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 cross-platform test failures on Windows (pm-i84i) and scheduled auto-releases being silently blocked by stale Sentry errors (pm-nb08). To resolve the Windows test failures, hardcoded POSIX path separators in unit tests were replaced with platform-native path utilities, and a simulated win32 path regression guard was introduced. To prevent stale Sentry errors from blocking releases, a new --sentry-window-days flag (defaulting to 14 days) was added to bound the unresolved error query using Sentry's lastSeen syntax, and a GitHub issue alerting mechanism was introduced for scheduled auto-release failures. There are no review comments provided, so no further feedback is available.

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.

@unbraind
unbraind merged commit 54fc791 into main Jun 19, 2026
15 checks passed
@unbraind
unbraind deleted the fix/auto-release-sentry-gate-window-and-alerting branch June 19, 2026 20:23
unbraind added a commit that referenced this pull request Jun 19, 2026
Record the merged PR #305 evidence and release the active pm-i84i claim while leaving the broader Windows file:// TypeScript dynamic import item open for the remaining acceptance work.
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