Skip to content

docs: update docs and templates for category reclassification#83

Closed
let-sunny wants to merge 13 commits intomainfrom
chore/update-docs-for-category-reclassification
Closed

docs: update docs and templates for category reclassification#83
let-sunny wants to merge 13 commits intomainfrom
chore/update-docs-for-category-reclassification

Conversation

@let-sunny
Copy link
Copy Markdown
Owner

@let-sunny let-sunny commented Mar 25, 2026

Summary

  • Update all docs, templates, and agent prompts to reflect the category reclassification: layout + ai-readability merged into structure, handoff-risk renamed to behavior (6 categories to 5, 32 rules to 29)
  • Update rule tables in REFERENCE.md with new/merged/deleted rule IDs (9:7:4:5:4 distribution)
  • Update category references in SCORING.md, CALIBRATION.md, MCP-VS-CLI.md, bug template, converter agent, designer agent, and fixture feedback docs

Closes #79

Note: Depends on #81 (refactor/category-reclassification)

Test plan

  • pnpm test:run passes (590 tests, 0 failures)
  • Verify no stale category/rule references remain in docs

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added behavior-focused detections (overflow & wrap) and a component variant-structure mismatch check; enhanced unnecessary/empty-node detection.
  • Improvements

    • Consolidated categories to five: Structure, Token, Component, Naming, Behavior.
    • Updated scoring, category gauges, and overall score to reflect the new category set and counts.
  • Documentation

    • Updated docs, issue templates, fixtures, and CLI/result tables to use the new taxonomy and rule names.
  • Refactor

    • Reorganized rule surface and test coverage to align with the new taxonomy and rule responsibilities.

let-sunny and others added 9 commits March 26, 2026 04:19
Reclassify categories: layout + ai-readability → structure, handoff-risk → behavior.
Merge overlapping rules: no-auto-layout absorbs ambiguous-structure + missing-layout-hint,
fixed-size-in-auto-layout absorbs fixed-width-in-responsive-context,
missing-min-width + missing-max-width → missing-size-constraint,
invisible-layer + empty-frame → unnecessary-node,
hardcode-risk removed (covered by absolute-position-in-auto-layout).
Add 3 new rules: overflow-behavior-unknown, wrap-behavior-unknown, variant-structure-mismatch.
Final count: structure(9) token(7) component(4) naming(5) behavior(4) = 29 rules.

Closes #79

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…-size)

Merged rules should provide more detailed fix guidance that covers
all absorbed symptoms, not just the base rule's original fix.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Was too vague ("Use a consistent naming convention"). Now includes
specific examples and explains why AI needs consistent naming.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…checks, test fixes

- Add INSTANCE to isContainerNode helper (structure rules)
- Guard noUncheckedIndexedAccess: early continue for undefined children
- Skip wrap-behavior-unknown when children lack bounding box data
- Add +1 tolerance comment for floating-point rounding in overflow check
- Fix misleading test title for hidden overlapping children case
- Add 48x48 boundary test for unnecessary-node placeholder exemption

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…c assertions

- Add boundary-condition tests for text-truncation-unhandled (length=50, width=300, length=51)
- Fix non-deterministic test in responsive-fields: remove if-guard, assert deterministically
- Rename misleading test title to match actual expectation

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
TypeScript strict types + JSDoc on public APIs serve as documentation.
The 80% threshold wasn't respecting the configured 40% override anyway.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… accuracy

- Rename test titles to match actual scenarios (both missing vs one missing)
- Add minWidth to fixture that tests maxWidth-only path
- Add "only minWidth missing" test for complete coverage of 3 violation paths

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…fication

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 25, 2026

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

Refactors rule taxonomy from six categories to five: merges "Layout" + "AI Readability" → "Structure", renames "Handoff Risk" → "Behavior", moves/merges many rules (deleted old modules, added structure module, expanded behavior), updates scoring/weights/tests/docs/configs/fixtures accordingly.

Changes

Cohort / File(s) Summary
Category Contracts & UI
src/core/contracts/category.ts, src/core/ui-constants.ts, src/core/report-html/index.ts
Replaced layout/ai-readability/handoff-risk with structure/behavior in enums, labels, and descriptions; adjusted category grid from 6→5 columns.
Rule IDs & Core Contracts
src/core/contracts/rule.ts
Updated RuleId union (remove/rename many rule IDs), changed DEPTH_WEIGHT_CATEGORIES to ["structure","behavior"].
Rule Modules: removed
src/core/rules/layout/index.ts, src/core/rules/ai-readability/index.ts, src/core/rules/handoff-risk/*
Removed legacy modules and their exported rules (layout/ai-readability/handoff-risk rules deleted).
Rule Modules: added/changed
src/core/rules/structure/index.ts, src/core/rules/behavior/index.ts, src/core/rules/component/index.ts
Added structure module consolidating many former layout/readability rules (no-auto-layout, fixed-size-in-auto-layout, unnecessary-node, etc.); added/updated behavior rules (overflow-behavior-unknown, wrap-behavior-unknown, moved/updated others); added variant-structure-mismatch in component rules.
Rule Config & Presets
src/core/rules/rule-config.ts
Reworked RULE_CONFIGS: removed layout/ai-readability/hardcode entries; added/renamed structure/behavior rules; adjusted severities/options and preset filtering/boost logic.
Scoring & Engine
src/core/engine/scoring.ts, src/core/engine/scoring.test.ts, src/core/engine/integration.test.ts, src/core/engine/rule-engine.test.ts
Switched to 5-category scoring (TOTAL_RULES_PER_CATEGORY, CATEGORY_WEIGHT, overall average over 5 categories); updated many tests and expectations accordingly.
Tests & Fixtures (agents/tests)
src/agents/..., src/core/.../*.test.ts
Updated numerous fixtures and assertions to use structure/behavior instead of old categories; removed many old test suites and added tests for new/merged rules (structure/behavior).
Deleted Old Rule Tests
src/core/rules/layout/*.test.ts, src/core/rules/ai-readability/*.test.ts, src/core/rules/handoff-risk/*.test.ts
Removed test suites corresponding to the deleted rule modules.
Docs, Templates & Calibration
docs/REFERENCE.md, docs/SCORING.md, docs/CALIBRATION.md, docs/MCP-VS-CLI.md, docs/fixtures/*, .claude/agents/*, .github/ISSUE_TEMPLATE/bug.yml
Updated docs, examples, calibration notes, agent prompts, and templates to reflect new categories, merged/renamed rule IDs (e.g., unnecessary-node) and 5-category scoring.
Tooling / CI Config
.coderabbit.yaml
Disabled docstring coverage pre-merge check (docstrings.mode: "off").

Sequence Diagram(s)

(omitted)

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰 I hopped through code and renamed the land,

Layout and Readability joined Structure's band.
Behavior now dances where handoff once stood,
Tests grew new roots, docs trimmed to the good.
A tiny rabbit applauds this tidy strand.

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'docs: update docs and templates for category reclassification' accurately summarizes the primary change—updating documentation and templates to reflect the 6→5 category taxonomy shift.
Linked Issues check ✅ Passed The changeset fully implements the coding requirements from issue #79: restructures CategorySchema enum, updates TOTAL_RULES_PER_CATEGORY and CATEGORY_WEIGHT scoring constants, migrates rules to new categories (Structure/Behavior), updates rule configs, and modifies tests accordingly.
Out of Scope Changes check ✅ Passed Changes remain focused on the 6→5 category reclassification objective. Modifications include rule implementations (merging layout/ai-readability into structure), rule deletions, new rule additions, configuration updates, documentation, and corresponding test adjustments—all directly supporting the stated refactoring goal.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/update-docs-for-category-reclassification
⚔️ Resolve merge conflicts
  • Resolve merge conflict in branch chore/update-docs-for-category-reclassification

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

@let-sunny let-sunny marked this pull request as ready for review March 25, 2026 20:12
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 9

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (5)
src/agents/gap-rule-report.test.ts (1)

80-81: ⚠️ Potential issue | 🟡 Minor

Inconsistent test fixture uses invalid category "spacing".

This test fixture uses category: "spacing", which is not a valid category in the new taxonomy (structure | token | component | naming | behavior). If this test is intentionally validating handling of unknown/invalid categories, consider adding a comment to clarify. Otherwise, update to a valid category like "token" or "structure".

🔧 Suggested fix if this should use a valid category
         gaps: [
           {
-            category: "spacing",
+            category: "token",
             description: "Padding off by 4px",
             actionable: true,
           },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/agents/gap-rule-report.test.ts` around lines 80 - 81, The test fixture in
src/agents/gap-rule-report.test.ts is using an invalid category value "spacing";
update the fixture's category field to one of the valid taxonomy values (e.g.,
"token" or "structure") or, if the intent is to test handling of unknown
categories, add a concise inline comment next to the fixture's category field
clarifying that this is deliberately invalid; locate the fixture by the object
containing category and description ("Padding off by 4px") and either replace
"spacing" with the chosen valid category or add the explanatory comment.
src/core/rules/structure/z-index-dependent-layout.test.ts (1)

58-61: ⚠️ Potential issue | 🟡 Minor

Add test for 20% overlap boundary condition.

The rule flags overlaps exceeding 20% of the smaller element's area (implementation: overlapArea > smallerArea * 0.2), but the test suite lacks a case for exactly 20% overlap. Add a test verifying that 20% overlap returns null to prevent regression if the threshold comparison is inadvertently changed.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/core/rules/structure/z-index-dependent-layout.test.ts` around lines 58 -
61, Add a test in z-index-dependent-layout.test.ts that constructs two sibling
nodes with sizes and positions producing exactly 20% overlap of the smaller
element (use the existing helpers makeNode and makeContext) and call
zIndexDependentLayout.check(node, makeContext()) asserting it returns null;
ensure the test description mentions the "20% overlap boundary" and use the same
FRAME parent pattern as the other tests so it guards against changing the strict
greater-than comparison.
src/core/rules/structure/responsive-fields.test.ts (1)

129-152: 🧹 Nitpick | 🔵 Trivial

Consider parameterizing the duplicated “missing max-width with only minWidth” scenarios.

These two cases validate the same condition and could be folded into a table-driven test to reduce maintenance overhead.

Also applies to: 177-203

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/core/rules/structure/responsive-fields.test.ts` around lines 129 - 152,
Two tests duplicate the same assertion for "missing max-width when minWidth is
set" (one at the shown block and another at 177-203); replace them with a single
table-driven test (using test.each or similar) that iterates scenarios (e.g.,
different container widths or layoutMode) and calls makeFile/makeNode and
analyzeFile for each; for each row assert the result includes an issue with rule
id "missing-size-constraint" and that the first violation message contains
"max-width". Ensure you reference the existing helpers makeFile, makeNode, and
analyzeFile and keep the same filter on i.rule.definition.id ===
"missing-size-constraint".
docs/REFERENCE.md (1)

109-119: ⚠️ Potential issue | 🟡 Minor

Documentation severity/score mismatches for token rules.

Several token rules have incorrect severity and score values compared to src/core/rules/rule-config.ts:

Rule Doc Actual (rule-config.ts)
raw-shadow -7 / risk -3 / missing-info
raw-opacity -5 / risk -2 / missing-info
📝 Proposed fix
 | `magic-number-spacing` | -3 | missing-info |
-| `raw-shadow` | -7 | risk |
-| `raw-opacity` | -5 | risk |
+| `raw-shadow` | -3 | missing-info |
+| `raw-opacity` | -2 | missing-info |
 | `multiple-fill-colors` | -3 | missing-info |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/REFERENCE.md` around lines 109 - 119, Update the documentation entries
for the token rules `raw-shadow` and `raw-opacity` so their Default Score and
Default Severity match the canonical values defined in the rule configuration:
change `raw-shadow` from "-7 / risk" to "-3 / missing-info" and change
`raw-opacity` from "-5 / risk" to "-2 / missing-info" in the table of token
rules; ensure the table cells for those two rules exactly reflect the
rule-config values for score and severity.
src/core/rules/rule-config.ts (1)

229-261: 🧹 Nitpick | 🔵 Trivial

Consider whether the string-matching heuristics sufficiently capture the intended rules.

The preset filtering uses ruleId.includes() substring matching:

  • dev-friendly: matches auto-layout, responsive, truncation, overflow, wrap, size
  • ai-ready: matches auto-layout, structure, name, unnecessary

This approach is fragile—future rule IDs containing these substrings would be inadvertently included/boosted. Consider using an explicit allowlist of rule IDs for more predictable behavior.

♻️ Example using explicit allowlists
 case "dev-friendly":
-  // Focus on structure and behavior issues
-  for (const [id, config] of Object.entries(configs)) {
-    const ruleId = id as RuleId;
-    if (
-      !ruleId.includes("auto-layout") &&
-      !ruleId.includes("responsive") &&
-      !ruleId.includes("truncation") &&
-      !ruleId.includes("overflow") &&
-      !ruleId.includes("wrap") &&
-      !ruleId.includes("size")
-    ) {
-      configs[ruleId] = { ...config, enabled: false };
-    }
-  }
+  const devFriendlyRules: RuleId[] = [
+    "no-auto-layout",
+    "absolute-position-in-auto-layout",
+    "fixed-size-in-auto-layout",
+    "missing-size-constraint",
+    "missing-responsive-behavior",
+    "text-truncation-unhandled",
+    "overflow-behavior-unknown",
+    "wrap-behavior-unknown",
+  ];
+  for (const [id, config] of Object.entries(configs)) {
+    const ruleId = id as RuleId;
+    if (!devFriendlyRules.includes(ruleId)) {
+      configs[ruleId] = { ...config, enabled: false };
+    }
+  }
   break;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/core/rules/rule-config.ts` around lines 229 - 261, The substring-matching
in the "dev-friendly" and "ai-ready" blocks (inside the switch cases labeled
"dev-friendly" and "ai-ready", iterating over configs and using
ruleId.includes(...)) is fragile; replace the heuristic with explicit allowlists
of rule IDs (e.g., const devFriendlyAllowlist = [...]; const aiReadyAllowlist =
[...]) and test membership with devFriendlyAllowlist.includes(ruleId) and
aiReadyAllowlist.includes(ruleId) respectively, then apply the existing
mutations (set enabled: false for dev-friendly, adjust score for ai-ready) only
when the ruleId is in the corresponding allowlist; update the allowlists to
enumerate the intended RuleId values so future rule IDs won’t be accidentally
matched.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.coderabbit.yaml:
- Around line 96-98: The pre-merge check configuration uses the wrong keys:
replace the pre_merge_checks entry named docstring_coverage with the
schema-correct key docstrings and change the disabling property from enabled:
false to mode: "off" so the check is actually disabled; update the block that
references pre_merge_checks -> docstring_coverage to use pre_merge_checks ->
docstrings and set mode: "off".

In `@docs/REFERENCE.md`:
- Line 128: The docs entry for `variant-structure-mismatch` currently lists a
score of `-5` but the source constant in src/core/rules/rule-config.ts defines
it as `-4`; update the table row in docs/REFERENCE.md so the score matches the
authoritative value (`-4`) for the `variant-structure-mismatch` rule (or
alternatively update the constant in `rule-config.ts` if the intended canonical
score is `-5`)—locate the identifier `variant-structure-mismatch` in the docs
and make the numeric value consistent with the `rule-config.ts` definition.
- Around line 104-107: The docs table entry for `unnecessary-node` is out of
sync with the implementation; update the documentation to match the canonical
score in src/core/rules/rule-config.ts by changing the `unnecessary-node` score
in REFERENCE.md from `-1` to `-2` (or alternatively change the value in
rule-config.ts if the intended score is `-1`) so both sources agree; target the
`unnecessary-node` identifier in the docs or the `rule-config` definition to
resolve the mismatch.
- Around line 140-147: Update the docs table under "Behavior (4 rules)" so the
score and severity for the listed rules match the canonical values from
src/core/rules/rule-config.ts: change `prototype-link-in-design` severity from
"suggestion" to "missing-info" (score remains -2), change
`overflow-behavior-unknown` score from -5 to -3 and severity from "risk" to
"missing-info", and change `wrap-behavior-unknown` score from -5 to -3 and
severity from "risk" to "missing-info"; edit the entries for the rule IDs
`prototype-link-in-design`, `overflow-behavior-unknown`, and
`wrap-behavior-unknown` in the docs to reflect these exact values.

In `@src/core/rules/behavior/prototype-link-in-design.test.ts`:
- Line 1: Remove the unused import by editing the import statement that
currently reads "import { makeNode, makeFile, makeContext } from
"../test-helpers.js";" in prototype-link-in-design.test.ts — drop "makeFile" so
it becomes "import { makeNode, makeContext } from \"../test-helpers.js\"";
ensure there are no other references to makeFile in the file before committing.

In `@src/core/rules/behavior/wrap-behavior-unknown.test.ts`:
- Line 1: The import list includes an unused symbol makeFile; remove makeFile
from the import statement (leaving makeNode and makeContext) in the top-of-file
import that currently reads "import { makeNode, makeFile, makeContext } from
\"../test-helpers.js\";" so the test file only imports used helpers and
eliminates the unused makeFile import.

In `@src/core/rules/structure/index.ts`:
- Around line 167-236: The horizontal-only branch in fixedSizeInAutoLayoutCheck
has confusing/partially unreachable checks: when hFixed is true we should first
test whether node.layoutSizingHorizontal is defined and, if so, require it to
equal "FIXED"; otherwise (undefined) use the fallback checks on
node.layoutAlign. Update the hFixed && !vFixed block in
fixedSizeInAutoLayoutCheck to: if node.layoutSizingHorizontal !== undefined then
return null unless it equals "FIXED"; else (layoutSizingHorizontal undefined)
perform the existing layoutAlign checks (skip for "STRETCH", skip unless
"INHERIT"), keeping the excluded-name and return message logic unchanged.

In `@src/core/rules/structure/no-auto-layout.test.ts`:
- Line 1: The import statement in this test file includes an unused symbol:
remove the unused import makeFile from the import list (currently importing
makeNode, makeFile, makeContext) so only the used helpers (makeNode and
makeContext) remain; update the import line that references makeFile to exclude
it.

In `@src/core/rules/structure/unnecessary-node.test.ts`:
- Line 1: The import statement includes an unused symbol makeFile; update the
import at the top that currently reads "import { makeNode, makeFile, makeContext
} from \"../test-helpers.js\";" to remove makeFile so it only imports makeNode
and makeContext, ensuring tests still compile and no unused imports remain.

---

Outside diff comments:
In `@docs/REFERENCE.md`:
- Around line 109-119: Update the documentation entries for the token rules
`raw-shadow` and `raw-opacity` so their Default Score and Default Severity match
the canonical values defined in the rule configuration: change `raw-shadow` from
"-7 / risk" to "-3 / missing-info" and change `raw-opacity` from "-5 / risk" to
"-2 / missing-info" in the table of token rules; ensure the table cells for
those two rules exactly reflect the rule-config values for score and severity.

In `@src/agents/gap-rule-report.test.ts`:
- Around line 80-81: The test fixture in src/agents/gap-rule-report.test.ts is
using an invalid category value "spacing"; update the fixture's category field
to one of the valid taxonomy values (e.g., "token" or "structure") or, if the
intent is to test handling of unknown categories, add a concise inline comment
next to the fixture's category field clarifying that this is deliberately
invalid; locate the fixture by the object containing category and description
("Padding off by 4px") and either replace "spacing" with the chosen valid
category or add the explanatory comment.

In `@src/core/rules/rule-config.ts`:
- Around line 229-261: The substring-matching in the "dev-friendly" and
"ai-ready" blocks (inside the switch cases labeled "dev-friendly" and
"ai-ready", iterating over configs and using ruleId.includes(...)) is fragile;
replace the heuristic with explicit allowlists of rule IDs (e.g., const
devFriendlyAllowlist = [...]; const aiReadyAllowlist = [...]) and test
membership with devFriendlyAllowlist.includes(ruleId) and
aiReadyAllowlist.includes(ruleId) respectively, then apply the existing
mutations (set enabled: false for dev-friendly, adjust score for ai-ready) only
when the ruleId is in the corresponding allowlist; update the allowlists to
enumerate the intended RuleId values so future rule IDs won’t be accidentally
matched.

In `@src/core/rules/structure/responsive-fields.test.ts`:
- Around line 129-152: Two tests duplicate the same assertion for "missing
max-width when minWidth is set" (one at the shown block and another at 177-203);
replace them with a single table-driven test (using test.each or similar) that
iterates scenarios (e.g., different container widths or layoutMode) and calls
makeFile/makeNode and analyzeFile for each; for each row assert the result
includes an issue with rule id "missing-size-constraint" and that the first
violation message contains "max-width". Ensure you reference the existing
helpers makeFile, makeNode, and analyzeFile and keep the same filter on
i.rule.definition.id === "missing-size-constraint".

In `@src/core/rules/structure/z-index-dependent-layout.test.ts`:
- Around line 58-61: Add a test in z-index-dependent-layout.test.ts that
constructs two sibling nodes with sizes and positions producing exactly 20%
overlap of the smaller element (use the existing helpers makeNode and
makeContext) and call zIndexDependentLayout.check(node, makeContext()) asserting
it returns null; ensure the test description mentions the "20% overlap boundary"
and use the same FRAME parent pattern as the other tests so it guards against
changing the strict greater-than comparison.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: c089e591-38f3-4869-b93c-201901371ce1

📥 Commits

Reviewing files that changed from the base of the PR and between 0abe6b1 and 0bde3ed.

📒 Files selected for processing (52)
  • .claude/agents/calibration/converter.md
  • .claude/agents/rule-discovery/designer.md
  • .coderabbit.yaml
  • .github/ISSUE_TEMPLATE/bug.yml
  • docs/CALIBRATION.md
  • docs/MCP-VS-CLI.md
  • docs/REFERENCE.md
  • docs/SCORING.md
  • docs/fixtures/ANALYSIS-VALIDITY-FEEDBACK.md
  • src/agents/analysis-agent.test.ts
  • src/agents/evidence-collector.test.ts
  • src/agents/gap-rule-report.test.ts
  • src/agents/orchestrator.test.ts
  • src/agents/report-generator.test.ts
  • src/core/contracts/category.ts
  • src/core/contracts/rule.ts
  • src/core/engine/integration.test.ts
  • src/core/engine/rule-engine.test.ts
  • src/core/engine/scoring.test.ts
  • src/core/engine/scoring.ts
  • src/core/report-html/index.ts
  • src/core/rules/ai-readability/ambiguous-structure.test.ts
  • src/core/rules/ai-readability/empty-frame.test.ts
  • src/core/rules/ai-readability/index.ts
  • src/core/rules/ai-readability/invisible-layer.test.ts
  • src/core/rules/ai-readability/missing-layout-hint.test.ts
  • src/core/rules/behavior/index.ts
  • src/core/rules/behavior/overflow-behavior-unknown.test.ts
  • src/core/rules/behavior/prototype-link-in-design.test.ts
  • src/core/rules/behavior/text-truncation-unhandled.test.ts
  • src/core/rules/behavior/wrap-behavior-unknown.test.ts
  • src/core/rules/component/index.ts
  • src/core/rules/component/variant-structure-mismatch.test.ts
  • src/core/rules/custom/custom-rule-loader.test.ts
  • src/core/rules/handoff-risk/hardcode-risk.test.ts
  • src/core/rules/handoff-risk/prototype-link-in-design.test.ts
  • src/core/rules/index.ts
  • src/core/rules/layout/absolute-position.test.ts
  • src/core/rules/layout/deep-nesting.test.ts
  • src/core/rules/layout/fixed-width-in-responsive-context.test.ts
  • src/core/rules/layout/group-usage.test.ts
  • src/core/rules/layout/index.ts
  • src/core/rules/layout/missing-responsive-behavior.test.ts
  • src/core/rules/layout/no-auto-layout.test.ts
  • src/core/rules/naming/index.ts
  • src/core/rules/rule-config.ts
  • src/core/rules/structure/index.ts
  • src/core/rules/structure/no-auto-layout.test.ts
  • src/core/rules/structure/responsive-fields.test.ts
  • src/core/rules/structure/unnecessary-node.test.ts
  • src/core/rules/structure/z-index-dependent-layout.test.ts
  • src/core/ui-constants.ts
💤 Files with no reviewable changes (14)
  • src/core/rules/ai-readability/empty-frame.test.ts
  • src/core/rules/layout/group-usage.test.ts
  • src/core/rules/layout/no-auto-layout.test.ts
  • src/core/rules/layout/absolute-position.test.ts
  • src/core/rules/layout/fixed-width-in-responsive-context.test.ts
  • src/core/rules/layout/missing-responsive-behavior.test.ts
  • src/core/rules/ai-readability/ambiguous-structure.test.ts
  • src/core/rules/handoff-risk/hardcode-risk.test.ts
  • src/core/rules/ai-readability/missing-layout-hint.test.ts
  • src/core/rules/layout/deep-nesting.test.ts
  • src/core/rules/ai-readability/index.ts
  • src/core/rules/handoff-risk/prototype-link-in-design.test.ts
  • src/core/rules/ai-readability/invisible-layer.test.ts
  • src/core/rules/layout/index.ts

@@ -0,0 +1,54 @@
import { makeNode, makeFile, makeContext } from "../test-helpers.js";
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Remove unused import makeFile.

makeFile is imported but never used in any test case. This will likely trigger lint warnings.

🧹 Proposed fix
-import { makeNode, makeFile, makeContext } from "../test-helpers.js";
+import { makeNode, makeContext } from "../test-helpers.js";
📝 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.

Suggested change
import { makeNode, makeFile, makeContext } from "../test-helpers.js";
import { makeNode, makeContext } from "../test-helpers.js";
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/core/rules/behavior/prototype-link-in-design.test.ts` at line 1, Remove
the unused import by editing the import statement that currently reads "import {
makeNode, makeFile, makeContext } from "../test-helpers.js";" in
prototype-link-in-design.test.ts — drop "makeFile" so it becomes "import {
makeNode, makeContext } from \"../test-helpers.js\""; ensure there are no other
references to makeFile in the file before committing.

@@ -0,0 +1,121 @@
import { makeNode, makeFile, makeContext } from "../test-helpers.js";
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Remove unused import makeFile.

makeFile is imported but never used in this test file.

🧹 Proposed fix
-import { makeNode, makeFile, makeContext } from "../test-helpers.js";
+import { makeNode, makeContext } from "../test-helpers.js";
📝 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.

Suggested change
import { makeNode, makeFile, makeContext } from "../test-helpers.js";
import { makeNode, makeContext } from "../test-helpers.js";
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/core/rules/behavior/wrap-behavior-unknown.test.ts` at line 1, The import
list includes an unused symbol makeFile; remove makeFile from the import
statement (leaving makeNode and makeContext) in the top-of-file import that
currently reads "import { makeNode, makeFile, makeContext } from
\"../test-helpers.js\";" so the test file only imports used helpers and
eliminates the unused makeFile import.

Comment on lines +167 to +236
// ============================================
// fixed-size-in-auto-layout (merged: absorbs fixed-width-in-responsive-context)
// ============================================

const fixedSizeInAutoLayoutDef: RuleDefinition = {
id: "fixed-size-in-auto-layout",
name: "Fixed Size in Auto Layout",
category: "structure",
why: "Fixed sizing inside Auto Layout contradicts the flexible layout intent",
impact: "AI generates a rigid element inside a flex container — the layout won't respond to content changes",
fix: "Use 'Hug' or 'Fill' for at least one axis. Both-axes FIXED → layout completely rigid; horizontal-only FIXED → width won't adapt to parent resize",
};

const fixedSizeInAutoLayoutCheck: RuleCheckFn = (node, context) => {
if (!context.parent) return null;
if (!hasAutoLayout(context.parent)) return null;
if (!isContainerNode(node)) return null;
if (!node.absoluteBoundingBox) return null;

// Skip if it's intentionally a small fixed element (icon, avatar, etc.)
const { width, height } = node.absoluteBoundingBox;
if (width <= 48 && height <= 48) return null;

// Check both axes FIXED (stronger case)
const hFixed =
node.layoutSizingHorizontal === "FIXED" || node.layoutSizingHorizontal === undefined;
const vFixed =
node.layoutSizingVertical === "FIXED" || node.layoutSizingVertical === undefined;

if (hFixed && vFixed) {
// Skip if it has its own auto-layout
if (node.layoutMode && node.layoutMode !== "NONE") return null;

return {
ruleId: fixedSizeInAutoLayoutDef.id,
nodeId: node.id,
nodePath: context.path.join(" > "),
message: `Container "${node.name}" (${width}×${height}) uses fixed size on both axes inside Auto Layout. Consider HUG or FILL for at least one axis.`,
};
}

// Check horizontal-only FIXED (lighter case, from fixed-width-in-responsive-context)
if (hFixed && !vFixed) {
// Use layoutSizingHorizontal if available (accurate)
if (node.layoutSizingHorizontal) {
if (node.layoutSizingHorizontal !== "FIXED") return null;
} else {
// Fallback: STRETCH means fill, skip
if (node.layoutAlign === "STRETCH") return null;
if (node.layoutAlign !== "INHERIT") return null;
}

// Excluded names (nav, header, etc.)
if (isExcludedName(node.name)) return null;

return {
ruleId: fixedSizeInAutoLayoutDef.id,
nodeId: node.id,
nodePath: context.path.join(" > "),
message: `"${node.name}" has fixed width inside Auto Layout`,
};
}

return null;
};

export const fixedSizeInAutoLayout = defineRule({
definition: fixedSizeInAutoLayoutDef,
check: fixedSizeInAutoLayoutCheck,
});
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Inconsistent logic path in the horizontal-only FIXED check.

Lines 209-228: When hFixed && !vFixed, the logic has an inconsistency:

  • Line 211 checks if node.layoutSizingHorizontal is truthy
  • Line 212 returns null if it's NOT "FIXED" (correct)
  • But line 211's truthiness check already passed, so layoutSizingHorizontal exists
  • Lines 214-216 in the else branch will never execute because if layoutSizingHorizontal is undefined, it would fail the truthiness check but hFixed would be true due to line 191-192's fallback

The else branch (lines 213-217) handles the case where layoutSizingHorizontal is undefined but hFixed is true due to the fallback on line 192. However, the current condition structure is confusing.

♻️ Clearer condition structure
   // Check horizontal-only FIXED (lighter case, from fixed-width-in-responsive-context)
   if (hFixed && !vFixed) {
-    // Use layoutSizingHorizontal if available (accurate)
-    if (node.layoutSizingHorizontal) {
-      if (node.layoutSizingHorizontal !== "FIXED") return null;
-    } else {
-      // Fallback: STRETCH means fill, skip
-      if (node.layoutAlign === "STRETCH") return null;
-      if (node.layoutAlign !== "INHERIT") return null;
-    }
+    // If layoutSizingHorizontal is explicitly set and not FIXED, skip
+    if (node.layoutSizingHorizontal !== undefined && node.layoutSizingHorizontal !== "FIXED") {
+      return null;
+    }
+    // Fallback for older Figma data: use layoutAlign heuristic
+    if (node.layoutSizingHorizontal === undefined) {
+      if (node.layoutAlign === "STRETCH") return null;
+      if (node.layoutAlign !== "INHERIT") return null;
+    }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/core/rules/structure/index.ts` around lines 167 - 236, The
horizontal-only branch in fixedSizeInAutoLayoutCheck has confusing/partially
unreachable checks: when hFixed is true we should first test whether
node.layoutSizingHorizontal is defined and, if so, require it to equal "FIXED";
otherwise (undefined) use the fallback checks on node.layoutAlign. Update the
hFixed && !vFixed block in fixedSizeInAutoLayoutCheck to: if
node.layoutSizingHorizontal !== undefined then return null unless it equals
"FIXED"; else (layoutSizingHorizontal undefined) perform the existing
layoutAlign checks (skip for "STRETCH", skip unless "INHERIT"), keeping the
excluded-name and return message logic unchanged.

@@ -0,0 +1,140 @@
import { makeNode, makeFile, makeContext } from "../test-helpers.js";
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Remove unused import makeFile.

makeFile is imported but never used in this test file.

🧹 Proposed fix
-import { makeNode, makeFile, makeContext } from "../test-helpers.js";
+import { makeNode, makeContext } from "../test-helpers.js";
📝 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.

Suggested change
import { makeNode, makeFile, makeContext } from "../test-helpers.js";
import { makeNode, makeContext } from "../test-helpers.js";
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/core/rules/structure/no-auto-layout.test.ts` at line 1, The import
statement in this test file includes an unused symbol: remove the unused import
makeFile from the import list (currently importing makeNode, makeFile,
makeContext) so only the used helpers (makeNode and makeContext) remain; update
the import line that references makeFile to exclude it.

@@ -0,0 +1,110 @@
import { makeNode, makeFile, makeContext } from "../test-helpers.js";
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Remove unused import makeFile.

makeFile is imported but never used in this test file.

🧹 Proposed fix
-import { makeNode, makeFile, makeContext } from "../test-helpers.js";
+import { makeNode, makeContext } from "../test-helpers.js";
📝 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.

Suggested change
import { makeNode, makeFile, makeContext } from "../test-helpers.js";
import { makeNode, makeContext } from "../test-helpers.js";
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/core/rules/structure/unnecessary-node.test.ts` at line 1, The import
statement includes an unused symbol makeFile; update the import at the top that
currently reads "import { makeNode, makeFile, makeContext } from
\"../test-helpers.js\";" to remove makeFile so it only imports makeNode and
makeContext, ensuring tests still compile and no unused imports remain.

@let-sunny let-sunny marked this pull request as draft March 25, 2026 20:43
- REFERENCE.md: fix scores/severity to match rule-config.ts
  - unnecessary-node: -1 → -2
  - variant-structure-mismatch: -5 → -4
  - prototype-link-in-design: suggestion → missing-info
  - overflow/wrap-behavior-unknown: -5 risk → -3 missing-info
- .coderabbit.yaml: fix pre_merge_checks schema (docstrings.mode: off)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@let-sunny let-sunny marked this pull request as ready for review March 25, 2026 20:45
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/REFERENCE.md`:
- Around line 174-175: Add a blank line between the preceding paragraph
"**Mobile-first (focus on structure):**" and the fenced code block opener
"```json" so the markdown has an empty line before the code fence; update the
docs/REFERENCE.md content to insert that single blank line immediately before
the "```json" fence.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 90e8116e-785a-4d94-afa4-d0e378bd0aa0

📥 Commits

Reviewing files that changed from the base of the PR and between 0bde3ed and 52417d1.

📒 Files selected for processing (2)
  • .coderabbit.yaml
  • docs/REFERENCE.md

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@let-sunny
Copy link
Copy Markdown
Owner Author

Replaced by new PR with clean rebase on main (after #81 merge).

@let-sunny let-sunny closed this Mar 25, 2026
@let-sunny let-sunny deleted the chore/update-docs-for-category-reclassification branch March 26, 2026 08:50
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.

refactor: 룰 카테고리 재분류 — AI 구현 관점으로 통합

1 participant