Skip to content

feat(core): extract read handlers (doctor, query)#165

Open
galligan wants to merge 1 commit into
fire-4/handler-contractfrom
fire-5/read-handlers
Open

feat(core): extract read handlers (doctor, query)#165
galligan wants to merge 1 commit into
fire-4/handler-contractfrom
fire-5/read-handlers

Conversation

@galligan

@galligan galligan commented Feb 22, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Extract doctorHandler and queryHandler to packages/core/src/handlers/
  • Both CLI and MCP surfaces call the same handlers
  • Handlers return Result<T, E> with typed inputs/outputs
  • Move shared query helpers (bot filters, sync scopes, state resolution) into handlers (FIRE-5)

Test plan

  • bun run check passes
  • bun test passes (288 tests)

🤘🏻 In-collaboration-with: Claude Code

Greptile Summary

Extracts doctorHandler and queryHandler to packages/core/src/handlers/, implementing the handler contract pattern. Both CLI and MCP surfaces now call the same core handlers with typed Result<T, E> return values. Shared query logic (bot filters, sync scopes, state resolution) has been consolidated into the handlers as planned in FIRE-5.

Key changes:

  • Created packages/core/src/handlers/doctor.ts with diagnostic checks
  • Created packages/core/src/handlers/query.ts with query logic consolidation
  • Refactored apps/cli/src/commands/doctor.ts to use doctorHandler (removed 165 lines)
  • Refactored apps/mcp/src/index.ts to use doctorHandler with formatting helpers (removed 72 lines)
  • Exported new handlers and types from core package

The refactoring successfully eliminates duplication while maintaining the same functionality across both surfaces.

Confidence Score: 5/5

  • This PR is safe to merge with minimal risk
  • Clean refactoring that extracts duplicate logic to core handlers. The code moves existing, tested logic without changing behavior. All tests pass (288 tests), and the handler contract pattern is consistently applied.
  • No files require special attention

Important Files Changed

Filename Overview
apps/cli/src/commands/doctor.ts Refactored to use doctorHandler from core, removed 165 lines of duplicated logic
apps/mcp/src/index.ts Refactored to use doctorHandler, simplified with formatting helpers, removed 72 lines
packages/core/src/handlers/doctor.ts New handler implementing diagnostic checks with Result types, 246 lines of well-structured logic
packages/core/src/handlers/query.ts New handler consolidating query logic with typed inputs/outputs, 342 lines of extraction

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    CLI[CLI doctor command] --> DH[doctorHandler]
    MCP[MCP fw_doctor tool] --> DH
    
    DH --> CH1[checkGithubReachable]
    DH --> CH2[checkAuth]
    DH --> CH3[checkConfigParse]
    DH --> CH4[checkCacheWritable]
    DH --> CH5[checkRepoDetection]
    DH --> CH6[checkGraphiteCli]
    DH --> GI[getGraphiteStackInfo]
    
    DH --> DO[DoctorOutput]
    DO --> |Result&lt;T, E&gt;| CLI
    DO --> |Result&lt;T, E&gt;| MCP
    
    CLI2[CLI query command] -.future.-> QH[queryHandler]
    MCP2[MCP fw_query tool] -.future.-> QH
    
    QH -.-> QE[queryEntries]
    QH -.-> CSF[applyClientSideFilters]
    QH -.-> BW[buildWorklist]
    QH -.-> QO[QueryOutput]
    
    style DH fill:#a8dadc
    style QH fill:#a8dadc
    style DO fill:#f1faee
    style QO fill:#f1faee
Loading

Last reviewed commit: e353d4e

@linear

linear Bot commented Feb 22, 2026

Copy link
Copy Markdown

Add doctorHandler and queryHandler as transport-agnostic handlers that
return Result<T, E> and receive HandlerContext.

doctorHandler:
- Runs 6 diagnostic checks (GitHub API, auth, config, cache, repo, Graphite)
- Wired into CLI doctor command (270 lines → 101 lines)
- Wired into MCP handleDoctor

queryHandler:
- Validates input, builds QueryOptions, runs queryEntries
- Applies client-side filters (PR list, types, authors, perspective)
- Optionally builds worklist summary
- Not yet wired into CLI/MCP query flows (requires sync untangling)

View and list handlers deferred — their heavy transport-specific logic
(stack handling, formatting) would push this PR beyond the 300 LOC budget.

🤘🏻 In-collaboration-with: [Claude Code](https://claude.com/claude-code)
@galligan galligan force-pushed the fire-4/handler-contract branch from dbcaf82 to f07a741 Compare February 22, 2026 03:51
@galligan galligan force-pushed the fire-5/read-handlers branch from 289ae13 to e353d4e Compare February 22, 2026 03:51
@galligan galligan changed the title feat(core): extract read handlers to core feat(core): extract read handlers (doctor, query) Feb 22, 2026
@galligan galligan marked this pull request as ready for review February 22, 2026 04:07

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e353d4ecb8

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +84 to +88
const login = loginResult.isOk() ? loginResult.value : "unknown";
return {
name: "Auth valid",
ok: true,
message: `${login} via ${auth.value.source}`,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Treat viewer lookup failures as auth check failures

fetchViewerLogin() returns a Result, but this branch maps an Err to "unknown" and still reports ok: true; with an expired or invalid token, doctor will incorrectly claim auth is valid. This makes diagnostics unreliable for real auth outages because the failing API call is swallowed instead of surfaced as a failed check.

Useful? React with 👍 / 👎.

Comment on lines +125 to +127
if (!username) {
return entries;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Reject mine/reviews filtering when username is missing

When mine or reviews is requested but no configured username is available, this returns all entries unchanged, so callers get silently unfiltered results while believing the perspective filter was applied. Existing query flows treat missing user.github_username as an error, so this behavior introduces incorrect query results rather than a clear failure.

Useful? React with 👍 / 👎.

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.

1 participant