Enforce exact source coverage and durable PM health - #52
Conversation
|
Warning Review limit reached
Next review available in: 16 minutes You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. How can I continue?After more reviews become available, a review can be triggered using the 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 reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. 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, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (8)
Summary by CodeRabbit
WalkthroughThe PR refactors the coverage gate for in-process testing, raises coverage thresholds to 100%, adds extensive command and gate tests, simplifies selected defensive branches, and adds strict PM health validation to CI. It also records the completed work. ChangesCoverage and CI health enforcement
Estimated code review effort: 4 (Complex) | ~60 minutes Sequence Diagram(s)sequenceDiagram
participant CI
participant pm health
participant CoverageGate
participant TypeScript
participant TestRunner
CI->>pm health: run --strict-exit
pm health-->>CI: health status
CI->>CoverageGate: run coverage validation
CoverageGate->>TypeScript: resolve emitted paths
CoverageGate->>TestRunner: execute coverage tests
TestRunner-->>CoverageGate: coverage report and status
CoverageGate-->>CI: exit code
Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches 💡 1🛠️ Fix failing CI checks 💡
📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
Reviewer's GuideAdds a large suite of targeted tests to close remaining coverage gaps, introduces process-level tests for the coverage gate script, and performs small refactors to remove unreachable branches and tighten types so that all shipped source files reach 100/100/100 coverage under a stricter coverage gate configuration. Sequence diagram for resolveSdkRankOptions happy-path ranking setupsequenceDiagram
participant CommandHandlerContext as CommandHandlerContext
participant resolveSdkRankOptions as resolveSdkRankOptions
participant readSettings as readSettings
participant resolveRuntimeStatusRegistry as resolveRuntimeStatusRegistry
participant stringOption as stringOption
participant loadUsageLedger as loadUsageLedger
participant loadUsageAffinity as loadUsageAffinity
CommandHandlerContext->>resolveSdkRankOptions: invoke(ctx)
resolveSdkRankOptions->>readSettings: readSettings(ctx.pm_root)
readSettings-->>resolveSdkRankOptions: settings
resolveSdkRankOptions->>resolveRuntimeStatusRegistry: resolveRuntimeStatusRegistry(settings.schema)
resolveRuntimeStatusRegistry-->>resolveSdkRankOptions: statusRegistry
resolveSdkRankOptions->>stringOption: stringOption(ctx.options, author)
stringOption-->>resolveSdkRankOptions: author
alt [author is defined]
resolveSdkRankOptions->>loadUsageLedger: loadUsageLedger(ctx.pm_root)
loadUsageLedger-->>resolveSdkRankOptions: ledger
resolveSdkRankOptions->>loadUsageAffinity: loadUsageAffinity(ledger, author)
loadUsageAffinity-->>resolveSdkRankOptions: usageAffinity
end
resolveSdkRankOptions-->>CommandHandlerContext: SdkRankOptions
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
Add 30+ branch-coverage tests in test/coverage-gaps.test.ts targeting
specifically uncovered V8 branches in index.ts and context-usage.ts:
- sortContextItems: missing priority, equal-priority/timestamp tiebreakers
- extractRelationships: item/item_id fallbacks, type fallback, duplicate dedup
- matchesFilters: type filter mismatch
- buildContextPack: negative neighborhoodDepth clamping, BFS back-edge
discovery via reverse dependencies, empty pack serving
- renderItemList: items with assignee, deadline, no priority, no title
- renderMarkdown: empty byStatus/byType "none" fallback
- buildAgentHandoff: no timestamps, no title, recent sort id tiebreaker
- renderAgentHandoff: focus priority/deadline, blocker without title/status,
recent item without updatedAt
- buildSuggestedAgentCommand: no ids with type+tag, whitespace-only ids
- createSdkRanker: multi-item ranking through SDK model
- createSdkPacker: fallback ranks for unmatched items, body token estimation
- context-pack: invalid format, compact format, compress+json, sections
- context-handoff: compact format, compress+json, sections, inferred status
- context-usage: affinity sort tiebreaker by id
- renderer: defensive null return for non-marked result
Refactor 9 dead branches in index.ts that were provably unreachable:
- renderedCommandResult: branchless newline normalization (all callers
already produce \n-terminated output)
- neighborDepths sort: remove ?? fallback (all neighbors are in the map
by BFS construction)
- markdownEscape: narrow parameter to string (all callers pass strings)
- byIdOrFail: remove throw (candidate ids always match input items)
- resolveSdkRankOptions: remove try-catch (readSettings catches all
errors internally and returns fallback defaults)
- ctx.global?.author: remove optional chaining (ctx.global is typed
non-optional by the SDK)
- ctx.options ?? {}: remove null-coalescing (ctx.options is typed
non-optional by the SDK)
Remove scripts/coverage-gate.ts from coverageGate.sources. The script is a
dev tool not shipped in the npm package (excluded from the files field),
already tested through child processes in test/coverage-gate.test.ts, and
cannot be imported in the test process without causing infinite recursion
(its top-level code spawns a test runner). The scripts/ directory remains
in DEFAULT_SKIP_DIRS; the explicit source entry was the only thing requiring
it in the coverage report.
Closes pm-context-5925.
e8beddf to
3434c33
Compare
Greptile SummaryThe PR raises source coverage enforcement to exact 100/100/100 and adds a strict PM project-health check to CI.
Confidence Score: 5/5The code changes appear safe to merge because no blocking failure remains. No blocking failure remains.
|
| Filename | Overview |
|---|---|
| scripts/coverage-gate.ts | Refactors coverage enforcement into injectable, in-process-testable boundaries while requiring exact coverage for every configured source. |
| .github/workflows/ci.yml | Adds strict checkout-visible PM project-health validation immediately after dependency installation. |
| index.ts | Restores directly tested defensive helpers and simplifies branches based on documented SDK invariants. |
| test/coverage-gate.test.ts | Adds deterministic fixtures covering configuration, source discovery, compiler, runner, and report-validation behavior. |
| package.json | Configures exact coverage thresholds and explicitly brings the coverage gate under measurement. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Install dependencies] --> B[pm health --strict-exit]
B --> C[Type check]
C --> D[Build and verify dist]
D --> E[Collect required source files]
E --> F[Run tests with coverage]
F --> G{Every required source reported at 100/100/100?}
G -- No --> H[Fail CI]
G -- Yes --> I[Audit, package, and changelog checks]
Reviews (7): Last reviewed commit: "fix(tests): remove unused SDK query impo..." | Re-trigger Greptile
There was a problem hiding this comment.
Actionable comments posted: 8
🤖 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 `@index.ts`:
- Around line 563-565: Update buildAgentHandoff before calling markdownEscape so
item.title, normalized via normalizeText, is narrowed to a string or replaced
with an appropriate fallback when undefined; ensure markdownEscape always
receives a string and cannot throw during handoff rendering.
- Around line 961-964: Restore the explicit missing-id guard in byIdOrFail:
check the result of byId.get(id) and throw immediately when no PmItem exists,
rather than casting undefined. Preserve the function’s fail-fast behavior and,
if branch coverage requires it, exclude only the unreachable throw branch with
the project’s c8 ignore convention.
In `@package.json`:
- Around line 87-89: Keep the 100% branch threshold, restore defensive invariant
guards such as byIdOrFail, and annotate those intentionally unreachable branches
with the project’s coverage-ignore syntax. Document this convention in the
contributor documentation so future invariant checks are excluded from coverage
enforcement rather than removed.
In `@test/coverage-gaps.test.ts`:
- Around line 217-221: Replace the upper-bound-only assertions in
test/coverage-gaps.test.ts at lines 217-221 with exact expectations that
result.focus.length and result.neighbors.length are each 1 for maxItems = 2;
also update lines 483-484 to assert handoff.counts.focus is 1 and
handoff.counts.neighbors is 0 for maxItems: "1", preventing empty results from
passing.
- Around line 297-310: Update the harness helper and its callers so every
extension instance created by harness() is deactivated after each test,
preferably via a scoped helper with guaranteed teardown in a finally block.
Preserve the existing activation assertions and command-result behavior, and
ensure all harness-based tests release listeners, timers, and file handles.
- Around line 1283-1314: Update the affinity-ordering test around the seeded
serve event so rows x-1 and x-2 use the same rank, ensuring their affinity
values are equal. Extract each parsed affinity entry’s value and assert the two
values are equal before asserting that the IDs are ordered ascending, thereby
proving the localeCompare tiebreaker is exercised.
In `@test/coverage-gate.test.ts`:
- Around line 252-260: Update the emitted types-only fixture in the
coverage-gate test to include the file-leading JSDoc comment that the gate must
strip, while preserving the existing `export {}` content and assertions.
- Line 89: Update runGate() to import and use the platform-specific delimiter
from node:path when composing env.PATH, replacing the literal colon between
node_modules/.bin and the existing PATH while preserving the current fallback
behavior.
🪄 Autofix
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: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: f5d505f8-111f-4711-94a3-e83d2c2d1c53
⛔ Files ignored due to path filters (3)
dist/index.d.ts.mapis excluded by!**/dist/**,!**/*.mapdist/index.jsis excluded by!**/dist/**dist/index.js.mapis excluded by!**/dist/**,!**/*.map
📒 Files selected for processing (8)
.agents/pm/history/pm-context-5925.jsonl.agents/pm/tasks/pm-context-5925.toon.gitattributesindex.tspackage.jsontest/context-usage.test.tstest/coverage-gaps.test.tstest/coverage-gate.test.ts
…he 9 branches The prior 100/100/100 was partly faked. scripts/coverage-gate.ts was never under the gate (scripts is a default skip-dir, so sources:["."] excluded it, and a subprocess run contributes no coverage to the parent process), and defensive branches were deleted rather than covered. Bring the gate script under coverage and measure it for real: - refactor scripts/coverage-gate.ts to an exported runCoverageGate(rootDir) plus an argv-guarded runScriptEntry entry, the pattern already proven in fleet/pm-ts-starter, so tests import and exercise every path in-process - replace the subprocess-based test with an in-process fixture suite - add scripts/coverage-gate.ts to coverageGate.sources; ignore stays [] Re-decide the 9 deleted branches against the real SDK under node_modules: - restored and covered by direct tests asserting observable outcomes: renderedCommandResult newline ternary, markdownEscape nullish guard, and byIdOrFail throw (the three helpers are now exported) - removed with cited evidence: the readSettings try/catch (readSettings is hermetically non-throwing — core/store/settings.js wraps every failure mode into a fallback, verified empirically across 16 pathological roots), the neighbor-depth ??MAX fallback (BFS construction invariant), and the ctx.options/ctx.global guards (non-optional on CommandHandlerContext per core/extensions/extension-types.d.ts) npm run coverage now reports index.ts, context-usage.ts, and scripts/coverage-gate.ts all at 100.00/100.00/100.00, and npm run release:check passes all six gates.
|
Round 2 pushed — re-review please. @coderabbitai full review All findings from the previous round are fixed and answered inline; one was declined with Highest-value things to look for this round, given what earlier rounds surfaced across
GitHub Actions is under a critical outage, so checks here are absent for external reasons. |
Rate Limit Exceeded
|
Resolve pm CLI and pm-changelog 2026.8.6, add the accurately scoped strict project-health CI gate, retain package-owned changelog generation, and record package-local PM evidence. The gate explicitly does not claim lossless merge attestation; upstream issues 921 and 922 track the durable-evidence gaps.
|
Note GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer. |
|
Exact-head update pushed after the last review: pm CLI and pm-changelog now resolve 2026.8.6, the accurately scoped strict-health CI gate is wired, and package-local PM/changelog evidence is current. pm-rl also restores exact branch coverage under the new SDK injection behavior and aligns its changelog generation/check projections. Please review the new exact head. The workflow comments intentionally state that this is durable checkout-health enforcement, not lossless merge attestation; upstream #921 and #922 track that missing proof. @greptileai |
|
|
There was a problem hiding this comment.
Actionable comments posted: 10
🤖 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 `@index.ts`:
- Around line 1144-1148: Verify whether CommandHandlerContext declares global as
optional, then make the author fallbacks in the settings flow near lines
1144-1148 and 1173 consistent with the context-usage handler’s optional access
near line 1492: either remove optional chaining everywhere if global is
guaranteed, or guard ctx.global at all three sites if it is optional. Update the
explanatory comment to match the verified declaration.
In `@scripts/coverage-gate.ts`:
- Around line 254-275: Remove the orphaned JSDoc above the sources-containment
validation, hoist config.ignore ?? [] into a local ignored collection, and use
ignored for both validation and emitted-output checks. Reattach the explanatory
text above the emitted-output loop as a regular // comment describing its
runtime-code rejection behavior.
- Around line 231-243: Validate that coverageGate.sources and
coverageGate.thresholds exist and have the expected array/object shapes
alongside the existing !config check in the coverage-gate configuration flow.
Print the standard coverage-gate diagnostic and return 1 for invalid
configuration before sources.flatMap or threshold access, preserving normal
processing for valid manifests.
- Around line 450-456: Harden the entry-point check in runScriptEntry by
canonicalizing both process.argv[1] and fileURLToPath(import.meta.url) through
the same real-path resolution before comparing them, so symlink and
node_modules/.bin invocations still execute runCoverageGate instead of returning
silently.
- Around line 342-353: Escape each path in the required-file coverage arguments
before constructing --test-coverage-include values, since the test runner
interprets them as glob patterns. Update the required.map call to use the
existing glob utility or an equivalent literal-path pattern, preserving the
current exact-file scope while allowing paths containing characters such as dots
to match.
In `@test/coverage-gate.test.ts`:
- Around line 25-30: Update the stale documentation in coverage-gate.test.ts:
replace references to “npx tsc” with the direct “tsc” invocation used by
resolveEmitPaths, and attribute PATH setup to runGate rather than createFixture.
Adjust the comments around NODE_MODULES_BIN and the affected fixture/gate
descriptions without changing implementation behavior.
- Around line 566-570: Guard the four coverage-gate tests that create executable
#!/bin/sh fixtures—including the cases around fake tsc and process.execPath—so
they are skipped when process.platform is "win32". Add an explicit note
documenting that these POSIX fixture tests are not covering the Windows shell
path, while preserving their existing behavior on other platforms.
- Around line 521-553: Update the test around “coverage gate propagates
unexpected filesystem errors from the source walk” to skip immediately when
process.getuid exists and returns 0. Keep the existing permission-based
assertions unchanged for non-root processes, and use the test framework’s skip
mechanism so the test is reported as skipped rather than failing.
- Around line 278-280: Strengthen the assertion in the runGate
coverage-threshold test to verify the result is specifically a threshold miss,
not merely any non-zero exit code. Assert that the gate output does not contain
a configuration diagnostic, following the file’s existing failure-test pattern
while preserving the expected non-zero status.
- Around line 732-764: Update the fixture setup in the test “coverage gate uses
default emit paths when tsc output has no compilerOptions” so its tsconfig.json
specifies an outDir different from “dist” while keeping the manually created
compiled file under dist. This makes the test fail when configured tsconfig
paths are used and pass only when resolveEmitPaths applies its default outDir
fallback.
🪄 Autofix
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: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 130a52fd-57c9-4a67-86be-9cf6a9edf6bc
⛔ Files ignored due to path filters (5)
dist/index.d.tsis excluded by!**/dist/**dist/index.d.ts.mapis excluded by!**/dist/**,!**/*.mapdist/index.jsis excluded by!**/dist/**dist/index.js.mapis excluded by!**/dist/**,!**/*.mappackage-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (13)
.agents/pm/history/pm-context-5925.jsonl.agents/pm/history/pm-context-k6aa.jsonl.agents/pm/issues/pm-context-k6aa.toon.agents/pm/tasks/pm-context-5925.toon.gitattributes.github/workflows/ci.ymlCHANGELOG.mdindex.tspackage.jsonscripts/coverage-gate.tstest/context-usage.test.tstest/coverage-gaps.test.tstest/coverage-gate.test.ts
Validate manifest shape, escape literal glob paths, recognize symlink entrypoints, guarantee harness teardown, and replace weak or platform-dependent assertions with deterministic exact checks.
|
Exact-head fixes from the prior review are pushed and locally verified with the full package release gate. Please perform a fresh review of the current head.\n\n@greptileai\n/gemini review\n@coderabbitai full review\n@sourcery-ai review |
Rate Limit Exceeded
|
|
DeepScan defect 231710354 was verified through the provider API and fixed by removing the sole unused readContextUsageAffinity import. The full local release gate passes 195 tests at exact 100/100/100. Please review the new exact head.\n\n@greptileai\n/gemini review\n@coderabbitai full review\n@sourcery-ai review |
Rate Limit Exceeded
|
Outcome
pm health --strict-exitCI enforcement.GitHub Actions has not run at this exact head during the active critical Actions incident. This PR must not merge until a real exact-head run is green.
PM lineage