feat: store reviews and capture human feedback#33
Conversation
Aligns the default with the documented value in CLAUDE.md. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Creates pr_reviews, pr_review_findings, and review_feedback tables to persist Canon reviews and capture human replies to findings. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
storeReview() inserts a review with all findings in a single transaction. storeFeedback() links a human reply to a stored finding, idempotent via ON CONFLICT DO NOTHING. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Returns review ID, inline comment IDs, deduped findings, and event type instead of a boolean. Fetches comment IDs via listCommentsForReview after posting so they can be linked to stored findings. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- pr-handler calls storeReview after posting (graceful on failure) - feedback-handler captures human replies to Canon inline comments - index.ts registers pull_request_review_comment.created event Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Found 3 pattern deviations: ⚪ 3 low
Additional findings
⚪ src/github/pr-handler.ts — Style Inconsistency · confidence: 98%
Config is imported as a value import even though it is only used as a type; this deviates from existing type-only import usage.
Suggested fix:
import type { Config } from "../config";
Reference: src/review/reviewer.ts
| @@ -0,0 +1,105 @@ | |||
| import { getPool } from "../lib/db-client"; | |||
| import { Finding } from "../review/reviewer"; | |||
There was a problem hiding this comment.
⚪ Style Inconsistency · low · confidence: 99%
Type import is not using the repo’s type-only import pattern for TypeScript types.
Existing pattern: Types are imported with import type where appropriate.
Reference: src/review/reviewer.ts
| import { Finding } from "../review/reviewer"; | |
| import type { Finding } from "../review/reviewer"; |
| @@ -0,0 +1,63 @@ | |||
| import { Context } from "probot"; | |||
There was a problem hiding this comment.
⚪ Style Inconsistency · low · confidence: 98%
Type import from Probot is not using type-only import syntax, which is used in the codebase for type-only dependencies.
Existing pattern: Type-only imports are preferred for types/interfaces.
Reference: src/review/reviewer.ts
| import { Context } from "probot"; | |
| import type { Context } from "probot"; |
Applies Canon review feedback — Finding, Context, and Config are only used as types and should use import type syntax. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
/canon review |
There was a problem hiding this comment.
Found 2 pattern deviations: 🟡 1 medium · ⚪ 1 low
Additional findings
⚪ tests/github/pr-handler.test.ts — Style Inconsistency · confidence: 98%
Type import style is inconsistent with the established pattern; Config should be imported as type-only.
Suggested fix:
import type { Config } from "../../src/config";
Reference: src/github/pr-handler.ts
| } | ||
|
|
||
| await client.query("COMMIT"); | ||
| } catch (err) { |
There was a problem hiding this comment.
🟡 Pattern Violation · medium · confidence: 95%
Catch variable name deviates from the repository’s DB transaction error-handling pattern (error + throw error).
Existing pattern: Transactional DB flows use catch (error) { await client.query("ROLLBACK"); throw error; } for consistency.
Reference: src/db/migrate.ts
| } catch (err) { | |
| } catch (error) { | |
| await client.query("ROLLBACK"); | |
| throw error; | |
| } |
Summary
pull_request_review_comment.createdwebhook handler for feedback captureSchema
Changes
0002_review-storage.sql— 3 new tables with indexessrc/db/review-store.ts—storeReview()(transactional) +storeFeedback()(idempotent)src/github/feedback-handler.ts— validates parent is Canon bot comment, stores feedbacksrc/review/commenter.ts—postReviewreturnsPostReviewResultwith review ID, comment IDs, findings, eventsrc/github/pr-handler.ts— callsstoreReviewafter posting (graceful on failure)src/index.ts— registers new webhook eventTest plan
npm run lintpasses (tsc --noEmit)npm test— 306 tests across 28 suites passnpm run buildcompiles cleanly🤖 Generated with Claude Code