Repository navigation
Conversation
Turns the W11-style hand analysis of infrastructure_failure artifacts into a tool: node tools/diagnose.mjs <artifact-dir> prints, per run, the decision, one line per stage failure and coverage gap with terminal reason, HTTP status, model, attempts and retryable when the artifact carries them, and an explicit final status that never lets "unclassified" read as "clean". Classification reads the diagnostic events (init model, api_retry trail, confirmed result envelope with the engine's own one-result disclosure gate), not the collapsed "after N attempts: claude exited 1" string. Pre-contract artifacts recover terminal reason, status code and model from the events, and the retry trail; engine-level attempts and retryable are only in the new structured fields and are reported unknown rather than guessed. Failures and gaps without a diagnostic are UNCLASSIFIED with the reason named - absence of evidence is not evidence of health. Validated against the W11-known runs: PR 2025 summary 503, PR 2026 plan 503, PR 1993 decided with one unclassifiable find:correctness gap. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: DIAGNOSTIC-TOOL
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
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 (2)
📝 WalkthroughWalkthrough新增 Changes诊断工具与验证
Estimated code review effort: 3 (Moderate) | ~25 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1📝 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 |
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 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 `@test/diagnose.test.mjs`:
- Around line 131-136: Update classifyReview so the clean decision requires
decision === 'approve' in addition to empty failures and coverageGaps; preserve
the existing CLEAN status behavior for valid approvals. Extend the diagnose
tests with a request_changes fixture or case having both arrays empty and assert
that it is not classified as clean.
- Around line 187-189: Add the required tracked placeholder file at
test/fixtures/diagnose/empty/.gitkeep so the empty fixture directory exists in
clean checkouts and loadReview(fixtures('empty')) reaches the expected “no
review.json found” error.
In `@test/fixtures/diagnose/new-structured-cpu-gate/review.json`:
- Around line 12-18: 更新 new-structured-cpu-gate fixture 的 diagnostic 内容,使其中的
apiErrorStatus、terminalReason、model 和 apiErrorMessage 与外层结构化字段存在冲突;同时调整
test/diagnose.test.mjs 中对应断言,明确验证诊断结果优先采用外层结构化字段,而不是 diagnostic 内的值。
In `@tools/diagnose.mjs`:
- Around line 283-285: Update the entry-point guard surrounding main to use Node
24’s native import.meta.main check instead of comparing import.meta.url with a
manually constructed process.argv path, preserving the existing
main(process.argv.slice(2)) invocation.
🪄 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: ed3476ec-5f8f-4862-9e1b-6648d076fc54
📒 Files selected for processing (16)
test/diagnose.test.mjstest/fixtures/diagnose/approve-clean/review.jsontest/fixtures/diagnose/corrupt-diag/review.jsontest/fixtures/diagnose/empty/.keeptest/fixtures/diagnose/malformed-infra/review.jsontest/fixtures/diagnose/new-gap-with-diagnostic/review.jsontest/fixtures/diagnose/new-structured-cpu-gate/review.jsontest/fixtures/diagnose/old-400-toolchoice/review.jsontest/fixtures/diagnose/old-503-plan/review.jsontest/fixtures/diagnose/old-503-summary/manifest.jsontest/fixtures/diagnose/old-503-summary/review.jsontest/fixtures/diagnose/old-gap-correctness/manifest.jsontest/fixtures/diagnose/old-gap-correctness/review.jsontest/fixtures/diagnose/old-no-diag-infra/review.jsontest/fixtures/diagnose/schema-exhausted/review.jsontools/diagnose.mjs
| test('an approve run with no failures and no gaps is the only thing that reads clean', async () => { | ||
| const review = await loadFixture('approve-clean'); | ||
| const classified = classifyReview(review); | ||
| assert.equal(classified.clean, true); | ||
| assert.match(classified.status, /CLEAN/); | ||
| }); |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
修正 clean 的决策条件并添加反例测试。
Line 131 声明只有 approve 可以是 clean。tools/diagnose.mjs:153-156 当前只检查 failures 和 coverageGaps。因此,无失败且无 coverage gap 的 request_changes 结果会被报告为 CLEAN。
让 decision === 'approve' 成为 clean 的必要条件。添加 request_changes 且两个数组为空的断言。
建议的测试补充
test('an approve run with no failures and no gaps is the only thing that reads clean', async () => {
const review = await loadFixture('approve-clean');
const classified = classifyReview(review);
assert.equal(classified.clean, true);
assert.match(classified.status, /CLEAN/);
+
+ const requestChanges = classifyReview({
+ decision: 'request_changes',
+ failures: [],
+ coverageGaps: [],
+ });
+ assert.equal(requestChanges.clean, false);
});📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| test('an approve run with no failures and no gaps is the only thing that reads clean', async () => { | |
| const review = await loadFixture('approve-clean'); | |
| const classified = classifyReview(review); | |
| assert.equal(classified.clean, true); | |
| assert.match(classified.status, /CLEAN/); | |
| }); | |
| test('an approve run with no failures and no gaps is the only thing that reads clean', async () => { | |
| const review = await loadFixture('approve-clean'); | |
| const classified = classifyReview(review); | |
| assert.equal(classified.clean, true); | |
| assert.match(classified.status, /CLEAN/); | |
| const requestChanges = classifyReview({ | |
| decision: 'request_changes', | |
| failures: [], | |
| coverageGaps: [], | |
| }); | |
| assert.equal(requestChanges.clean, false); | |
| }); |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@test/diagnose.test.mjs` around lines 131 - 136, Update classifyReview so the
clean decision requires decision === 'approve' in addition to empty failures and
coverageGaps; preserve the existing CLEAN status behavior for valid approvals.
Extend the diagnose tests with a request_changes fixture or case having both
arrays empty and assert that it is not classified as clean.
| test('a missing review.json is an error, not a clean result', async () => { | ||
| await assert.rejects(loadReview(fixtures('empty')), /no review.json found/); | ||
| }); |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
提交 empty fixture 的占位文件。
Git 不保留空目录。当前变更没有提交 test/fixtures/diagnose/empty 的可跟踪文件。干净检出后,loadReview() 会抛出 cannot read artifact directory,所以此断言不会匹配 no review.json found。
添加 test/fixtures/diagnose/empty/.gitkeep,以保留该目录。
建议的 fixture 文件
+++ test/fixtures/diagnose/empty/.gitkeep
+Keep this directory in Git for the missing-review fixture.📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| test('a missing review.json is an error, not a clean result', async () => { | |
| await assert.rejects(loadReview(fixtures('empty')), /no review.json found/); | |
| }); | |
| Keep this directory in Git for the missing-review fixture. |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@test/diagnose.test.mjs` around lines 187 - 189, Add the required tracked
placeholder file at test/fixtures/diagnose/empty/.gitkeep so the empty fixture
directory exists in clean checkouts and loadReview(fixtures('empty')) reaches
the expected “no review.json found” error.
| "diagnostic": "{\"events\":[{\"type\":\"result\",\"subtype\":\"success\",\"isError\":true,\"apiErrorStatus\":503,\"terminalReason\":\"api_error\"}],\"stderr\":\"\"}", | ||
| "apiErrorStatus": 503, | ||
| "apiErrorMessage": "Service Unavailable", | ||
| "terminalReason": "api_error", | ||
| "model": "cc-review", | ||
| "attempts": 1, | ||
| "retryable": true |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
让 fixture 真正验证结构化字段优先级。
当前 diagnostic 中的 apiErrorStatus 和 terminalReason 与结构化字段相同。diagnostic 也没有 model 或 apiErrorMessage。因此,test/diagnose.test.mjs 的 Line 103-114 不能证明冲突时结构化字段优先。错误地优先读取 diagnostic 的实现仍可能通过状态和终止原因断言。请加入带有冲突值的 diagnostic,或增加专门的冲突 fixture,并断言结构化字段覆盖 diagnostic。
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@test/fixtures/diagnose/new-structured-cpu-gate/review.json` around lines 12 -
18, 更新 new-structured-cpu-gate fixture 的 diagnostic 内容,使其中的
apiErrorStatus、terminalReason、model 和 apiErrorMessage 与外层结构化字段存在冲突;同时调整
test/diagnose.test.mjs 中对应断言,明确验证诊断结果优先采用外层结构化字段,而不是 diagnostic 内的值。
| if (import.meta.url === `file://${process.argv[1]}`) { | ||
| await main(process.argv.slice(2)); | ||
| } |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🌐 Web query:
Node.js detect ES module run as main script import.meta.filename pathToFileURL
💡 Result:
To determine if an ES module is being run as the main script in Node.js, you can use the import.meta.main property, which was added to stabilize this pattern in newer versions of Node.js [1][2]. For environments or Node.js versions where import.meta.main is not yet available, the standard approach is to compare the module's URL to the entry point path [3][4]. Using import.meta.main (Recommended for modern Node.js) As of Node.js v24+, import.meta.main provides a direct, native boolean check, serving as the ESM equivalent to the CommonJS require.main === module pattern [1][2]. if (import.meta.main) { // Module is run as the main entry point } Alternative Method (For older Node.js versions) In environments without import.meta.main, you can compare import.meta.filename (or fileURLToPath(import.meta.url)) against the process entry point found in process.argv[1] [2][5][4]. import { pathToFileURL } from 'node:url'; // Using import.meta.filename (Node.js v20.11.0+) if (import.meta.filename === process.argv[1]) { // Module is run as the main entry point } // Universal approach (using URL comparison) if (import.meta.url === pathToFileURL(process.argv[1]).href) { // Module is run as the main entry point } Note: import.meta.filename is available as a stable property in recent Node.js versions (v24.0.0+) and provides the absolute path to the module, equivalent to filename in CommonJS [5][6]. If you are working with symlinks or specific CLI tools, ensuring path resolution is handled consistently via realpathSync or similar utilities can help prevent mismatches [1].
Citations:
- 1: https://stackoverflow.com/questions/57838022/detect-whether-es-module-is-run-from-command-line-in-node
- 2: https://nodejs.github.io/package-examples/05-cjs-esm-migration/migrating-context-local-variables/
- 3: How to determine whether a file has been run directly inside ES module nodejs/help#2065
- 4: https://stackoverflow.com/questions/45136831/node-js-require-main-module
- 5: http://nodejs.org/docs/latest/api/esm.html
- 6: https://nodejs.org/download/release/latest-v24.x/docs/api/esm.html
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf 'Node version:\n'
node -e 'console.log(process.version)'
printf '\nNode pathToFileURL behavior for Windows-style path (simulated environment):\n'
node - <<'JS'
const { pathToFileURL } = await import('node:url');
const inputs = [
'tools/diagnose.mjs',
'/absolute/tools/diagnose.mjs',
'C:\\path\\tools\\diagnose.mjs',
'C:/path/tools/diagnose.mjs',
'/path/with spaces/tools/diagnose.mjs',
'/path/中文/tools/diagnose.mjs'
];
for (const input of inputs) {
try {
console.log(`${input} -> ${pathToFileURL(input).href}`);
} catch (error) {
console.log(`${input} -> error: ${error.name}: ${error.message}`);
}
}
JS
printf '\nStatic diff/stat context:\n'
git diff --stat HEAD~1..HEAD -- tools/diagnose.mjs || true
printf '\nRelevant source lines:\n'
cat -n tools/diagnose.mjs | sed -n '1,20p;270,288p'Repository: Kizunad/review
Length of output: 2484
🌐 Web query:
Node.js import.meta.main added when deprecated import.meta.url comparison paths
💡 Result:
The import.meta.main property was introduced in Node.js to provide a standard, reliable way to determine if an ES module is the entry point of the current process, serving as the ESM equivalent to the CommonJS require.main === module check [1][2]. Before the introduction of import.meta.main, developers frequently used a comparison between import.meta.url and process.argv[3] (often converted to a file URL) to detect if a script was executed directly [4][5]. However, this approach was widely considered fragile because it could fail in various scenarios, such as when dealing with symbolic links (e.g., npm bin scripts) or different module resolution contexts [5]. With the release of Node.js v24.2.0 and v22.18.0, import.meta.main was implemented as a native, boolean property on the import.meta object [3][1]. This implementation aligns with established patterns in other runtimes like Deno, providing a consistent and robust mechanism for this common requirement [6][5][7]. While the earlier comparison-based methods are not explicitly deprecated in a formal API sense, they are effectively superseded by import.meta.main, which is now the recommended approach for detecting the entry point in ESM [1]. Developers are encouraged to transition to import.meta.main to avoid the pitfalls associated with manual path comparisons [5][8].
Citations:
- 1: https://nodejs.org/api/esm.html
- 2: https://nodejs.org/download/release/latest-v24.x/docs/api/esm.html
- 3: https://nodejs.org/en/blog/release/v24.2.0/
- 4: https://stackoverflow.com/questions/57838022/detect-whether-es-module-is-run-from-command-line-in-node
- 5: Provide an equivalent of require.main for ESM nodejs/node#57616
- 6: import.meta.main nodejs/node#57226
- 7: https://docs.deno.com/examples/module_metadata_tutorial/
- 8: https://nodejs.github.io/package-examples/05-cjs-esm-migration/migrating-context-local-variables/
🌐 Web query:
node 24.15 import.meta.main
💡 Result:
In Node.js, import.meta.main is a boolean property available within ECMAScript modules (ESM) that indicates whether the current module is the entry point of the Node.js process [1][2]. It evaluates to true if the module is the entry point and false otherwise [1][2]. This feature was introduced in Node.js v24.2.0 (and backported to v22.18.0) to provide an ESM-native equivalent to the CommonJS pattern of checking require.main === module [1][3][2]. It is also analogous to Python's if name == "main": idiom [1][2]. Usage Example: export function foo { return 'Hello, world'; } function main { console.log(foo); } // Only execute main if this module is the entry point if (import.meta.main) { main; } The property is currently marked as having an early development stability status (1.0) [1][2].
Citations:
- 1: https://nodejs.org/dist/latest-v24.x/docs/api/esm.html
- 2: https://nodejs.org/api/esm.html
- 3: https://nodejs.org/en/blog/release/v24.2.0/
🌐 Web query:
Node v24.15.0 release notes import.meta.main
💡 Result:
Node.js v24.15.0, released on April 15, 2026, does not introduce the import.meta.main property [1][2]. The import.meta.main property was introduced earlier in Node.js v24.2.0 [3][4]. In Node.js, import.meta.main is a boolean property available within ECMAScript modules (ESM) [4]. It returns true if the current module is the entry point of the process and false otherwise [4]. It serves as an ESM-compatible alternative to the CommonJS require.main === module pattern, and is also analogous to the name == "main" check used in Python [4]. Since its introduction in v24.2.0, this property has been a standard feature in all subsequent versions of Node.js, including v24.15.0 [4][5].
Citations:
- 1: https://nodejs.org/en/blog/release/v24.15.0
- 2: 2026-04-15, Version 24.15.0 'Krypton' (LTS) nodejs/node#62681
- 3: https://nodejs.org/en/blog/release/v24.2.0/
- 4: https://nodejs.org/api/esm.html
- 5: https://nodejs.org/download/release/latest-v24.x/docs/api/esm.html
🌐 Web query:
Node.js v24.15.0 changelog import.meta.main
💡 Result:
The import.meta.main property was not introduced in Node.js v24.15.0; it was originally implemented and added in Node.js v24.2.0 [1][2][3]. In Node.js, import.meta.main is a boolean property available in ECMAScript modules (ESM) that indicates whether the current module is the entry point of the current process [4][1]. It serves as the ESM equivalent to the CommonJS require.main === module check [4][5]. Key details regarding import.meta.main include: - Functionality: Returns true if the module is the entry point, and false otherwise [4]. - History: It was implemented in Node.js v24.2.0 and later backported to v22.18.0 [4][1][6]. - Usage: It is designed to allow developers to conditionally run code only when a file is executed directly from the command line, rather than when it is imported as a module [4][1]. The v24.15.0 release (April 2026) focused on other updates, such as the addition of the --max-heap-size option, --require-module/--no-require-module, and various other minor improvements and bug fixes, but it did not introduce import.meta.main [7][8].
Citations:
- 1: https://nodejs.org/blog/release/v24.2.0
- 2: https://nodejs.org/en/blog/release/v24.2.0
- 3: https://nodejs.org/en/blog/release/v24.2.0/
- 4: https://nodejs.org/api/esm.html
- 5: https://stackoverflow.com/questions/57838022/detect-whether-es-module-is-run-from-command-line-in-node
- 6: [v22.x backport] esm: implement import.meta.main nodejs/node#58693
- 7: https://nodejs.org/en/blog/release/v24.15.0
- 8: 2026-04-15, Version 24.15.0 'Krypton' (LTS) nodejs/node#62681
入口判断不可移植,使用 import.meta.main。
直接比较 import.meta.url === file://${process.argv[1]} 会因为手工拼接 URL、路径百分号编码、Windows 路径格式等原因失败,导致诊断 CLI 在部分环境不执行。本项目使用 Node 24,可改用 ESM 原生的入口判断方式 if (import.meta.main),无需手动比较文件系统路径。
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@tools/diagnose.mjs` around lines 283 - 285, Update the entry-point guard
surrounding main to use Node 24’s native import.meta.main check instead of
comparing import.meta.url with a manually constructed process.argv path,
preserving the existing main(process.argv.slice(2)) invocation.
…n they are The classifier previously reported a classification and left the reading to the reader. A failure is only legible when the tool also says what the symptom historically meant and when that reading stops holding. Each entry encodes a symptom class from the corpus that pointed somewhere other than the fault: - 400 + api_error was the forced tool_choice class (thinking block echoed into a second request the upstream rejected); the #45 --json-schema removal retires it, so a 400 now is flagged as a NEW, uncharacterized cause - 503 + cpu overload is the host CPU gate, not an upstream outage - schema_error is the model misreading the contract, deterministic, not infra - 402 is the balance class; 524 is the relay origin timeout - the collapsed "after N attempts: claude exited 1" hides five causes Also tightens the shape-change canary: events with no recognized shapes now report that the artifact shape may have changed, so a future diagnostic format degrades loudly to unclassified rather than silently misreading. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: ENGINE-43-RECONCILE
Summary
The W11 hand analysis — digging terminal reason / status code / model out of
infrastructure_failureartifacts — is now mechanical:node tools/diagnose.mjs <artifact-dir>prints the decision, one line per stage failure and coverage gap (terminal reason, HTTP status, model, attempts, retryable where the artifact carries them), and an explicit final status.after N attempts: claude exited 1string:initmodel,api_retrytrail, and the confirmed single-resultenvelope under the engine's own disclosure gate (10f9ef7)unknownrather than guessedUNCLASSIFIEDwith the reason named, and the run status line only ever says CLEAN when there are literally no failures and no gaps — the exact confusion W11 hit (coverage gap with no diagnostic reading as clean) is the sixth instance, this is not the seventhTest plan
request_changeswith one unclassifiablefind:correctnessgap — all three reproduced exactlyno review.json found🤖 Generated with Claude Code
Summary by CodeRabbit
新功能
测试