a73x

specs/009-open-file-at-comment/review.md

Ref:   Size: 5.6 KiB

# Pre-Implementation Review

**Feature**: Open File at Inline Comment Location from Dashboard
**Artifacts reviewed**: spec.md, plan.md, tasks.md, checklists/requirements.md
**Review model**: Claude Opus 4.6 (1M context)
**Generating model**: Unknown (spec/plan), Claude Opus 4.6 (tasks)

## Summary

| Dimension | Verdict | Issues |
|-----------|---------|--------|
| Spec-Plan Alignment | PASS | All 7 FRs, both user stories, and all edge cases covered |
| Plan-Tasks Completeness | PASS | Every plan phase has corresponding tasks; all architectural components covered |
| Dependency Ordering | PASS | Correct phase ordering: setup -> US1 -> US2 -> polish |
| Parallelization Correctness | PASS | No [P] markers used; correct since all tasks touch src/tui.rs |
| Feasibility & Risk | WARN | Two design concerns with colorize_diff refactor and render_detail mutability |
| Standards Compliance | PASS | Constitution is a template (no rules to violate); no new dependencies |
| Implementation Readiness | WARN | Two tasks need more specificity around mutability and terminal lifecycle |

**Overall**: READY WITH WARNINGS

## Findings

### Critical (FAIL -- must fix before implementing)

None.

### Warnings (WARN -- recommend fixing, can proceed)

1. **T005 mutability conflict with render_detail**: The current `render_detail()` function takes `app: &App` (immutable reference). Storing `comment_positions` from `colorize_diff()` back into `app` during rendering requires either (a) changing `render_detail` to take `&mut App`, (b) moving the comment-position computation out of the render path into the pre-render cache block in `run_loop()` (around lines 241-252 where diff_cache is populated), or (c) using interior mutability (`RefCell`). Option (b) is the cleanest approach and aligns with the existing `diff_cache` pattern. The task description acknowledges this with "(requires `app` to be `&mut App` or positions stored via a different mechanism)" but should prescribe a specific approach to avoid implementation ambiguity.

2. **T008 terminal lifecycle**: The `open_editor_at()` function takes a `Terminal` reference for suspend/resume, but the actual `terminal` variable is owned by `run_loop()`, not directly accessible from a standalone function. The function signature should also include `stdout` handling (the current `run()` function calls `stdout().execute(LeaveAlternateScreen)` directly). The implementation should follow the exact pattern from lines 222-229 of `src/tui.rs` for consistency. Consider passing `terminal` as `&mut Terminal<CrosstermBackend<io::Stdout>>` and using `crossterm::execute!(io::stdout(), LeaveAlternateScreen)` directly rather than going through the terminal backend.

3. **Edge case: `$EDITOR` with arguments**: The spec (edge case 4) calls out handling editors like `code --wait`. T007 says "split on whitespace" which is a basic approach but could break paths with spaces (e.g., `/usr/local/My Editor/bin/editor`). This is an acceptable tradeoff for v1 and matches common Unix tool behavior, but worth noting.

4. **No test tasks**: The spec does not explicitly request tests and the tasks omit them. However, `find_comment_at_scroll()` and `resolve_editor()` are pure functions that would benefit from unit tests. The user's memory notes a TDD preference. Consider adding test tasks for these two helpers at minimum.

### Observations (informational)

1. **Verified struct existence**: `InlineComment` exists at `src/state.rs:50` with fields `author`, `file`, `line`, `body`, `timestamp` -- matches spec's Key Entities section exactly. No changes to `state.rs` or `event.rs` needed.

2. **Verified colorize_diff exists**: `colorize_diff()` at `src/tui.rs:706` already tracks `current_file` and `current_new_line` internally, so building the comment-position mapping (T004) is a natural extension of existing logic.

3. **No existing status_msg or InputMode**: The current `tui.rs` has no status message mechanism or input mode enum. T001 introduces `status_msg` which is the minimal approach. If feature 008 (commit browser) lands first, there may be a `status_msg` field already added -- check before implementing.

4. **Scope is well-contained**: 21 tasks, all in `src/tui.rs`, estimated at 50-100 lines of new code. This is proportional to the feature complexity.

5. **Plan phase numbering vs task phases**: The plan describes 5 phases (track positions, find nearest, editor launch, keybinding, status message) while tasks consolidate into 4 phases (setup, US1, US2, polish). This is a valid simplification -- the plan's phases 1-4 map to tasks Phase 1+2 (US1), and plan phase 5 maps to tasks Phase 3 (US2).

6. **`render_detail` currently calls `colorize_diff` inline**: The diff text is computed inside `render_detail()` at line 477. Since `render_detail` takes `&App`, the comment positions cannot be stored there. The recommended approach is to compute comment positions in the same pre-render block as `diff_cache` (lines 241-252 of `run_loop()`), or compute them alongside the diff and store both in the cache.

## Recommended Actions

- [ ] Clarify T005: prescribe computing comment positions in the `run_loop()` pre-render block (alongside `diff_cache` population at lines 241-252) rather than inside `render_detail()`
- [ ] Clarify T008: specify that `terminal` is passed as `&mut Terminal<CrosstermBackend<io::Stdout>>` and that suspend/resume uses `crossterm::execute!(io::stdout(), ...)` directly
- [ ] Consider adding unit test tasks for `find_comment_at_scroll()` and `resolve_editor()` given user's TDD preference
- [ ] Check whether feature 008 has already introduced a `status_msg` field to `App` before implementing T001