Skip to content

feat: fixture-done --dry-run + latest run auto-resolve (#30)#42

Merged
let-sunny merged 7 commits intomainfrom
feat/fixture-done-ux
Mar 25, 2026
Merged

feat: fixture-done --dry-run + latest run auto-resolve (#30)#42
let-sunny merged 7 commits intomainfrom
feat/fixture-done-ux

Conversation

@let-sunny
Copy link
Copy Markdown
Owner

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

Summary

  • fixture-done --dry-run: convergence 판정 결과만 출력, 실제 파일 이동 없음
  • --run-dir 생략 시 fixture명 기준 최신 run directory 자동 resolve
  • 판정 메시지 강화: strict/lenient 모드, applied/revised/rejected/kept 카운트 요약

새 함수

  • resolveLatestRunDir(fixtureName)logs/calibration/<name>--* 중 최신 반환
  • checkConvergence(runDir, options) — 상세 ConvergenceSummary 반환

Test plan

  • resolveLatestRunDir — 최신 선택, 미매칭 null, 빈 상태 null (3개)
  • checkConvergence — 카운트 정확성, strict/lenient 분기, skipped, no debate, no arbitrator (6개)
  • 전체 332 테스트 통과, 빌드 성공

Closes #30

https://claude.ai/code/session_01F4wtDqAS91kpr3zFoF9tvN

Summary by CodeRabbit

  • New Features

    • Convergence checking with detailed reporting (applied/revised/rejected/kept counts, mode, and reason)
    • Auto-resolution of latest calibration run and improved fixture command flow
    • Added --dry-run for previewing moves without applying changes; improved CLI messages
  • Refactor

    • Standardized import resolution across the codebase
    • Extracted visual comparison utilities into a shared helper module
  • Tests

    • Added/extended tests for convergence logic and visual scale inference

let-sunny and others added 5 commits March 25, 2026 09:32
Move pure functions from visual-compare.ts to visual-compare-helpers.ts:
- getFigmaCachePath, isCacheFresh, inferDeviceScaleFactor, padPng, compareScreenshots
- FIGMA_CACHE_DIR, FIGMA_CACHE_TTL_MS, SCALE_ROUNDING_TOLERANCE, UNITY_SCALE_TOLERANCE

Tests now import real implementation instead of mirrored copies.
Added 6 new inferDeviceScaleFactor tests (2x, 3x, 1x, zero, fractional).

Closes #33

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

1. isCacheFresh: try/catch instead of existsSync+statSync (TOCTOU race)
2. compareScreenshots: floor instead of round for similarity
   (100 reserved for exact match only, diffPixels===0)
3. @/ alias for visual-compare-helpers imports
4. padPng: note about theoretical magenta collision
5. Remove unused existsSync import

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Codebase uses relative paths (217 files) not @/ alias (21 files).
Revert review-driven alias change and update CLAUDE.md to reflect
actual convention: "Use relative paths for imports (not @/* alias)".

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

Previous revert (e29313c) only fixed visual-compare files.
12 files in src/agents/ still used @/ alias (25 occurrences).
Convert all to relative paths to match codebase convention.

All 323 tests pass, build succeeds.

https://claude.ai/code/session_01F4wtDqAS91kpr3zFoF9tvN
…summary (#30)

- Add resolveLatestRunDir(): auto-finds latest calibration run by fixture name
- Add checkConvergence(): returns detailed summary with decision counts
  (applied/revised/rejected/kept, strict/lenient mode, reason string)
- fixture-done: auto-resolve --run-dir from latest run when omitted
- fixture-done --dry-run: show convergence judgment without moving files
- Enhanced CLI output with mode, counts, and verdict
- 9 new tests for resolveLatestRunDir and checkConvergence

Closes #30

https://claude.ai/code/session_01F4wtDqAS91kpr3zFoF9tvN
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 25, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: e2167af6-9f2c-4aee-a740-26da4fa7597b

📥 Commits

Reviewing files that changed from the base of the PR and between 442b815 and 6e64f47.

📒 Files selected for processing (1)
  • src/cli/index.ts

📝 Walkthrough

Walkthrough

Refactors alias imports to relative paths, extracts visual-compare helpers into a new module, adds run-directory utilities (resolveLatestRunDir, checkConvergence) with test coverage, and updates the CLI fixture-done flow to support auto-resolving latest runs and --dry-run/lenient options.

Changes

Cohort / File(s) Summary
Documentation & Convention
CLAUDE.md
Replaced guidance to use @/* path alias with recommendation to use relative imports.
Import Path Migration
src/agents/..., src/agents/contracts/..., src/agents/*test.ts, src/agents/code-renderer.ts, src/agents/report-generator.ts
Converted @/ alias imports to relative paths across agent modules and tests (type-only and runtime imports).
Run Directory Convergence
src/agents/run-directory.ts, src/agents/run-directory.test.ts
Added resolveLatestRunDir(fixtureName), exported ConvergenceSummary interface, and checkConvergence(runDir, options?) with tests covering success, missing/invalid debate.json, skipped debates, and edge cases.
CLI Enhancement
src/cli/index.ts
Refactored fixture-done to derive fixture name, optionally auto-resolve latest run via resolveLatestRunDir, call checkConvergence, support --dry-run and --force, and improve messaging and dry-run behavior.
Visual Compare Helpers (new)
src/core/engine/visual-compare-helpers.ts
New module exporting cache constants, scale tolerances, getFigmaCachePath, isCacheFresh, inferDeviceScaleFactor, padPng, and compareScreenshots with file I/O and pixel-diff logic.
Visual Compare Refactor & Tests
src/core/engine/visual-compare.ts, src/core/engine/visual-compare.test.ts
Delegated caching/scale/diff logic to the new helpers module; removed duplicated local helper implementations and updated tests to use the extracted helpers.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant CLI
    participant RunDir as RunDirectory
    participant Convergence as ConvergenceCheck
    participant FS as FileSystem

    User->>CLI: fixture-done [--dry-run] [--force] [--run-dir]
    activate CLI

    CLI->>CLI: extractFixtureName(fixturePath)

    alt --force set or explicit --run-dir
        CLI->>Convergence: checkConvergence(explicit run-dir, options)
    else
        CLI->>RunDir: resolveLatestRunDir(fixtureName)
        activate RunDir
        RunDir->>FS: listCalibrationRuns()
        RunDir-->>CLI: latestRunDir | null
        deactivate RunDir
        CLI->>Convergence: checkConvergence(latestRunDir, options)
    end

    activate Convergence
    Convergence->>FS: read debate.json
    Convergence->>Convergence: count decisions (applied,revised,rejected), compute kept/total, apply strict/lenient rules
    Convergence-->>CLI: ConvergenceSummary {converged, mode, counts, reason}
    deactivate Convergence

    alt Converged
        alt --dry-run
            CLI->>User: "Would move files" (no FS changes)
        else
            CLI->>FS: move fixture files
            CLI->>User: "Files moved"
        end
    else Not converged
        CLI->>User: "Not converged" (mode, reason, suggestion for --force/--lenient-convergence)
    end

    deactivate CLI
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related issues

Possibly related PRs

Poem

🐰 I hopped through paths both near and far,
Replaced the @/ with .. and a star.
I cached, I padded, I counted with care,
Convergence and dry-runs now bloom in the air.
Hop, hop—CI smiles, the logs are fair!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: fixture-done --dry-run + latest run auto-resolve (#30)' directly and concisely captures the main features added in this PR.
Linked Issues check ✅ Passed All coding requirements from issue #30 are met: --dry-run flag with output only, auto-resolved latest run directory, and enhanced convergence messaging with strict/lenient modes and decision counts.
Out of Scope Changes check ✅ Passed All changes align with issue #30 objectives: import path refactoring supports the codebase reorganization needed for new helpers; visual-compare and run-directory changes directly enable the feature; CLI changes implement the specified requirements.
Docstring Coverage ✅ Passed Docstring coverage is 91.67% which is sufficient. The required threshold is 80.00%.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/fixture-done-ux

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

@let-sunny
Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 25, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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 `@src/cli/index.ts`:
- Around line 664-688: The error message when no run directory is found is
unclear; update the message emitted when !options.force && !runDir to indicate
the CLI attempted to auto-resolve a matching run directory but failed. Locate
the block using options.force, runDir and checkConvergence (the code that prints
the convergence summary and exits) and change the console.error text to
something like: "Error: no run directory found (auto-resolution attempted but no
matching run). Specify --run-dir, or use --force to skip check." Ensure the
message references auto-resolution and still suggests --run-dir or --force,
keeping fixturePath/log context unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 5682e6d3-a366-424c-b500-8357acab54f9

📥 Commits

Reviewing files that changed from the base of the PR and between d97e9b3 and 442b815.

📒 Files selected for processing (19)
  • CLAUDE.md
  • src/agents/analysis-agent.test.ts
  • src/agents/analysis-agent.ts
  • src/agents/code-renderer.ts
  • src/agents/contracts/analysis-agent.ts
  • src/agents/contracts/evaluation-agent.ts
  • src/agents/contracts/tuning-agent.ts
  • src/agents/evaluation-agent.ts
  • src/agents/orchestrator.test.ts
  • src/agents/orchestrator.ts
  • src/agents/report-generator.test.ts
  • src/agents/report-generator.ts
  • src/agents/run-directory.test.ts
  • src/agents/run-directory.ts
  • src/agents/tuning-agent.ts
  • src/cli/index.ts
  • src/core/engine/visual-compare-helpers.ts
  • src/core/engine/visual-compare.test.ts
  • src/core/engine/visual-compare.ts

Comment on lines 664 to 688
if (!options.force) {
if (!options.runDir) {
console.error("Error: --run-dir required to check convergence (or use --force to skip check)");
if (!runDir) {
console.error("Error: no run directory found. Specify --run-dir, or use --force to skip check.");
process.exit(1);
}
if (!isConverged(resolve(options.runDir), { lenient: options.lenientConvergence })) {
const debate = parseDebateResult(resolve(options.runDir));
const summary = debate?.arbitrator?.summary ?? debate?.skipped ?? "no debate.json found";
console.error(`Error: fixture has not converged (${summary}). Use --force to override.`);
const summary = checkConvergence(runDir, { lenient: options.lenientConvergence });
console.log(`\nConvergence check (${summary.mode}):`);
console.log(` ${summary.reason}`);
if (summary.total > 0) {
console.log(` applied=${summary.applied} revised=${summary.revised} rejected=${summary.rejected} kept=${summary.kept}`);
}

if (options.dryRun) {
console.log(`\n[dry-run] Would ${summary.converged ? "move" : "NOT move"} fixture: ${fixturePath}`);
return;
}

if (!summary.converged) {
console.error(`\nError: fixture has not converged. Use --force to override or --lenient-convergence.`);
process.exit(1);
}
} else if (options.dryRun) {
console.log(`[dry-run] --force: would move fixture without convergence check: ${fixturePath}`);
return;
}
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

Consider improving the error message for clarity.

When auto-resolution fails (no matching runs exist), the error at line 666 says "no run directory found" without indicating that auto-resolution was attempted. Users might not realize the CLI tried to find a matching run.

Consider:

      if (!runDir) {
-        console.error("Error: no run directory found. Specify --run-dir, or use --force to skip check.");
+        console.error(`Error: no run directory found for fixture "${fixtureName}". Specify --run-dir, or use --force to skip check.`);
        process.exit(1);
      }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/cli/index.ts` around lines 664 - 688, The error message when no run
directory is found is unclear; update the message emitted when !options.force &&
!runDir to indicate the CLI attempted to auto-resolve a matching run directory
but failed. Locate the block using options.force, runDir and checkConvergence
(the code that prints the convergence summary and exits) and change the
console.error text to something like: "Error: no run directory found
(auto-resolution attempted but no matching run). Specify --run-dir, or use
--force to skip check." Ensure the message references auto-resolution and still
suggests --run-dir or --force, keeping fixturePath/log context unchanged.

Addresses CodeRabbit review: clarifies that auto-resolution was
attempted but no matching run was found for the given fixture.

https://claude.ai/code/session_01F4wtDqAS91kpr3zFoF9tvN
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.

feat: calibration CLI 운영 UX 개선 (fixture-done --dry-run + latest run 자동 resolve)

2 participants