Conversation
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: trueThanks 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 |
Address-review summaryScan scope: full PR review history through 2026-09-02T11:41:23Z. Status: cutoff-safe summary. Detailed review outcomes are collapsed below. Detailed review outcomesMattered
Optional
Skipped
Deferred-work tracking: PR summary comment only. Next default scan starts after this comment. Say |
|
CLEAN (exact-head review, head ff8ae5e):
|
…nter-advice * origin/main: Deduplicate batch-title contracts and restore prompt headroom (#662)
|
Reconciled exact origin/main commit f15211f into PR head 98dee35 and pushed it to jg-codex/issue-468-linter-advice. Focused seam-doctor linter-advice tests passed (AgentWorkflowSeamDoctorLinterAdviceTest plus the new numeric-literal regression), bin/lint passed cleanly, and all review threads are resolved. Live hosted state is still queued on GitHub Actions for validate, Lint, and claude-review; CodeRabbit is green but skipped because the PR is draft. Smallest remaining action: wait for GitHub Actions to leave the queue. |
| return advice unless advice.empty? | ||
|
|
||
| [{ "message" => "No recognized RuboCop or ESLint config found." }] | ||
| rescue StandardError |
There was a problem hiding this comment.
call wraps the entire advisory computation in a blanket rescue StandardError. Every helper it calls into (rubocop, eslint, etc.) already rescues a narrow, intentional list of exceptions (ArgumentError, EncodingError, Psych::Exception, SystemCallError, TypeError) — this outer rescue StandardError is much broader and will also catch genuine programming bugs (e.g. NoMethodError from a future edit).
Because advice is designed to never affect seam-doctor's pass/fail status, a regression caught here just prints "Linter settings advice is unavailable..." and exits 0 — silently, with no test failure or visible error, potentially for a long time. Consider narrowing this to the same exception set used elsewhere, so real bugs surface instead of being swallowed as "advice unavailable".
| threshold = threshold(policy, "rubocop", rule, default) | ||
| state = if enabled | ||
| "invalid" | ||
| elsif setting.is_a?(Hash) || department_disabled |
There was a problem hiding this comment.
When a RuboCop cop entry exists but isn't a Hash (e.g. Metrics/AbcSize: 15 instead of Metrics/AbcSize: {Enabled: true, Max: 15}), this falls through to state = "missing" — the same label used when the cop isn't mentioned in the config at all.
setting.is_a?(Hash) is false, department_disabled is false, so the elsif branch is skipped and it lands on "missing". That's a bit misleading: the user does have an entry for this cop, it's just malformed (and RuboCop itself would likely reject/ignore it). Worth considering a distinct state (e.g. "invalid") for "key present but not a Hash", separate from "key absent entirely", so the advisory output doesn't imply nothing was configured when something (broken) actually was.
| def exported_javascript_expression(source) | ||
| start = javascript_export_start(source) | ||
| return unless start | ||
|
|
||
| javascript_expression(source, start) | ||
| end | ||
|
|
||
| def javascript_export_start(source) |
There was a problem hiding this comment.
exported_javascript_expression/javascript_export_start only resolve the literal expression written directly after export default / module.exports =. A very common flat-config idiom — building the config in a variable and exporting it by name:
const config = [{ rules: { complexity: ["error", 8], "max-lines": ["error", 240] } }];
export default config;resolves start to just past export default, and javascript_expression then captures the bare identifier config (no {). javascript_object_bodies("config") finds no {, so javascript_rule_bodies returns [], and every rule in ESLINT_LIMITS is reported "missing" even though everything is fully configured — with no note indicating the file couldn't be resolved (unlike the JSON/YAML path, which surfaces "Could not inspect linter settings" on genuine parse failure).
The PR description's Risk section does call out that "imported, computed, or spread-provided values" may be reported as missing, so this is a known/accepted v1 boundary — but worth double-checking whether this exact const config = ...; export default config shape (arguably the most common flat-config pattern in ESLint's own docs) is the intended scope, since it means the advisory silently reports "unconfigured" for a large share of real-world configs rather than surfacing an inspection-failure note.
| source[start..] | ||
| end | ||
|
|
||
| def javascript_object_bodies(source) |
There was a problem hiding this comment.
Minor duplication note: javascript_export_start, javascript_expression, javascript_object_bodies, javascript_array_end, javascript_object_body, and eslint_rule_expression each hand-roll their own char-by-char scanning loop that separately tracks quote/regex/escape state (via the shared javascript_literal_state helper) and depth/exit conditions. That's ~6 near-identical loops (~250 lines) instead of one shared tokenizer/segment-scanner that the callers configure with a stop condition.
Not blocking, but a fix to one edge case (e.g. resolving named exports, per the other comment on this file) would need to be replicated across every one of these scanners individually, and it's easy for them to silently drift out of sync over time.
Review summaryReviewed the non-failing linter advisory feature (RuboCop + ESLint settings analyzer). Overall the design is sound: advice is cleanly separated from the seam-doctor Left 4 inline comments on
No security concerns — the analyzer is purely static/non-executing as intended, and file reads are scoped to the repo root's known config filenames. |
Why
The seam doctor currently verifies that a repository exposes a lint command, but it cannot show whether agent-written code is bounded by complexity, size, or parameter limits. This adds actionable linter posture without converting quality guidance into a seam-contract failure.
Fixes #468
What changed
adviceJSON channel and matching standalone seam-doctor human output. Advice never entersissuesand never changes the seam-doctor exit status.workflows.seam.detailswhile preserving the stack check'shealthystatus.lint_advicepolicy..rubocop.yml,eslint.config.*, and.eslintrc*files. It does not evaluate JavaScript, rewrite consumer configs, add broader linter ecosystems, or re-enable this repository's RuboCop metrics.How to review and verify
bin/agent_doctor/linter_advice.rbfor the parser boundary andbin/agent-workflow-seam-doctorfor the non-failing output integration.PASS, reports all eight disabledMetrics/*cops, and links Refactor oversized Ruby files and re-enable default RuboCop metrics #309.Test plan
ruby bin/agent-workflow-seam-doctor-test.rb— 354 runs, 2788 assertions, 0 failures, 0 errors, 0 skips.bin/agent-workflows-doctor-test.bash— PASS.bash -n bin/agent-workflows-doctor-test.bash— PASS.bin/agent-workflow-seam-doctor --root . --shared . --json— PASS with 0 issues and all eight expected RuboCop recommendations.git diff --check— PASS.bin/validateintentionally not run locally per lane instruction; hosted CI is the full-suite source because current main has the known prompt-headroom failure owned by Deduplicate batch-title contracts and restore prompt headroom #662.validateran the full suite and failed only at the known Deduplicate batch-title contracts and restore prompt headroom #662 baseline:pr-batch Codex goal prompt template has 299 chars of headroom, must keep at least 300.deferred_to_update_changelog;CHANGELOG.mdis untouched.Integration note
This isolated lane does not modify the overlapping PRs. Later integration must reconcile these exact shared paths:
bin/agent-workflow-seam-doctor,bin/agent-workflow-seam-doctor-test.rbbin/agent-workflow-seam-doctor,bin/agent-workflow-seam-doctor-test.rb,docs/seam-design.mdbin/agent-workflow-seam-doctor,bin/agent-workflow-seam-doctor-test.rb,docs/seam-design.mdbin/agent-workflow-seam-doctor,bin/agent-workflow-seam-doctor-test.rb,docs/seam-design.mdRisk
The ESLint analyzer intentionally recognizes literal rule settings only. Imported, computed, or spread-provided values are never executed and may be reported as missing; repositories can suppress a recommendation when that static result is intentional. Inherited RuboCop settings are identified but not resolved; recommendations then reflect only the root file. Advice-only parsing failures remain informational and cannot degrade doctor health.
Agent details
Commands and results
db989c34d6910095a066beef07b67fb6be657c94.5639dbca.ff8ae5ec.Decision log
.standard.yml, and broader ecosystems would add unverified scope.adviceand copy it into healthyworkflows.seam.details.issuesand exit-status contract without a stack schema/status change.Coordination and reviewer telemetry
aw-medium-wave12-20260902codex-m5-issue468-linter-advice5960ac20-452a-4b6d-bbac-6172cd4fad71