Commit Graph

215 Commits

Author SHA1 Message Date
claw 8eeab96364 fix(cmd): remove duplicate doc comment and double blank line
CI / test (pull_request) Successful in 18s
PR Ready Gate / clear-labels (pull_request) Successful in 1s
CI / review (anthropic--claude-4.6-sonnet, sonnet, SONNET_REVIEW_TOKEN) (pull_request) Successful in 1m2s
CI / review (gpt-5, security, ., rodin/security-patterns, SECURITY_REVIEW.md, SECURITY_REVIEW_TOKEN) (pull_request) Successful in 1m31s
CI / review (gpt-5, gpt, GPT_REVIEW_TOKEN) (pull_request) Successful in 3m13s
2026-05-13 06:47:34 -07:00
claw b7f108faf6 docs(cmd,github): clarify type assertion and parameter usage in review superseding
Address sonnet-review feedback on PR #106:

- Document that the type assertion in supersedeOldReviews is guaranteed to
  succeed given the caller's provider switch, with the !ok branch guarding
  against future refactors (comment 18889).
- Clarify that vcsURL is only used in the Gitea path for constructing
  review permalink URLs (comment 18890).
- Add note explaining why the page-limit warning in ListReviews only fires
  when the final page is full, confirming the logic is intentional
  (comment 18891).
2026-05-13 06:47:34 -07:00
claw 528d29b63d fix: address self-review findings
- Remove dead code: findOwnReview (replaced by findAllOwnReviews)
- Check SetRetryBackoff return value in doJSONRequest tests
- Extract doWithRetry shared helper to eliminate ~100 lines of
  duplicated 429-retry/backoff/Retry-After logic between doRequest
  and doJSONRequest
- Fix import order: context before encoding/json (goimports)
- Add slog.Warn when ListReviews hits maxReviewPages limit
2026-05-13 06:47:28 -07:00
claw 0e503357ed fix: address review feedback on PR #106
- Add 429 rate-limit retry logic to doJSONRequest (matching doRequest
  behavior) so write operations (PostReview, DismissReview) properly
  retry when rate-limited by GitHub
- Remove redundant explicit case for ReviewEventComment in
  translateReviewEvent (default already handles it)
- Add ordering comment on --gitea-url alias registration explaining
  the dependency on registration-before-parse evaluation order
- Add tests for doJSONRequest retry/exhaust behavior
2026-05-13 06:46:17 -07:00
claw f50920333f fix(review): address bot review feedback on PR #106
- Document --gitea-url/--vcs-url last-one-wins behavior when both flags
  are passed simultaneously (sonnet MINOR #1)
- Move doJSONRequest from github/reviews.go to github/client.go where
  other HTTP helpers live (sonnet MINOR #2)
- Return joined error from supersedeOldReviews GitHub case instead of
  silently swallowing DismissReview failures (sonnet MINOR #3)
- Fix evaluateCIStatus to distinguish 'all checks passed' from 'no
  failures (N pending)' to avoid misleading status (gpt MINOR #2)
- Extract reviewsPerPage and maxReviewPages named constants for
  ListReviews pagination (gpt NIT #3)
2026-05-13 06:45:55 -07:00
claw b47bab08d6 fix(review): address inline review feedback on PR #106
- Reword misleading 'Fall through' comment to 'Continue to' in
  supersedeOldReviews (comment #18704)
- Add shared-pointer explanation comment for --gitea-url alias
  registration (comment #18703)
- Add comment clarifying CommitID same-commit expectation in
  PostReview (comment #18705)
- Rename 'hidden alias' to 'backward-compatible alias' in flag
  comment (comment #18708)
2026-05-13 06:44:32 -07:00
claw 550ba44354 fix(cmd): clarify empty gitea case control flow in supersedeOldReviews
The empty case "gitea": body exits the switch and continues to the
Gitea-specific logic below. Replace the vague comment with an explicit
note about the fall-through intent, per self-review feedback.
2026-05-13 06:44:32 -07:00
claw 6a3f63a726 fix(cmd,github): address review feedback on PR #106
- Replace panic() with fmt.Fprintf+os.Exit(1) in provider switch default
  (repo convention: never panic)
- Remove spurious 'event' field from DismissReview payload (GitHub dismiss
  endpoint only documents 'message')
- Change translateReviewEvent default to return 'COMMENT' as canonical
  fallback instead of passing unknown events through to GitHub API
- Refactor supersedeOldReviews to use explicit switch/case with default
  error for exhaustiveness
2026-05-13 06:44:32 -07:00
claw 0ea9c93af6 fix: address review feedback on PR #106
- Replace interface{} with any in github/reviews.go (Go 1.18+ idiom)
- Add default panic case to VCS client init switch
- Refactor supersedeOldReviews to return error instead of os.Exit(1)
- Remove spurious blank lines in formatter.go and formatter_test.go
- Add doc comment to DeleteReview explaining when to use vs DismissReview
- Sanitize extractSentinelName output to prevent log injection
2026-05-13 06:44:32 -07:00
claw bee4d98b8c feat(cmd): wire --provider and --base-url flags into CLI
- Add --provider flag (gitea|github) for VCS backend selection
- Add --base-url flag for GitHub API endpoint configuration
- Rename --gitea-url to --vcs-url with backward-compatible alias
- Replace direct gitea.Client usage with vcs.Client interface
- Create vcs.Client via factory switch based on --provider value
- Implement Reviewer + Identity interfaces on github.Client
- Add verdictToEvent() using canonical vcs.ReviewEvent types
- Remove review.GiteaEvent() (replaced by verdictToEvent)
- GitHub supersede uses DismissReview; Gitea keeps EditComment flow
- Add VCS_PROVIDER, VCS_BASE_URL, VCS_URL env var support

Closes #82
2026-05-13 06:44:32 -07:00
claw 691788833e docs(deps): update CONVENTIONS.md allowlist for go-yaml
Update the approved dependency table to document go-yaml subpackage
usage (ast, parser) and remove the deviation comment now that the
proper allowlist process is being followed.

Closes #91
2026-05-13 06:44:13 -07:00
claw d8c8a743ed fix: address review #2888 findings (comment clarity, test cleanup)
- Clarify depth-aware short-circuit comment to unambiguously describe
  the relationship between current depth and previous validation depth
- Add comment to MappingValueNode case explaining intentional depth+2
  behavior from parent MappingNode perspective
- Restructure unmarshalYAMLWithDepthLimit doc comment as bullet list
  covering all three safety checks (depth, multi-doc, strict fields)
- Replace t.Error with t.Fatal in TestYAMLEmptyFileRejection to remove
  redundant nil guard on subsequent err.Error() call
2026-05-13 06:44:13 -07:00
claw 629e29806c fix: handle MergeKeyNode explicitly in depth check, add size limit to ParsePersonaBytes
- Add explicit case for *ast.MergeKeyNode in checkYAMLDepth switch to
  make it clear this is an intentional leaf (no children to recurse)
  rather than relying on the default case. Prevents future library
  changes from silently bypassing depth checks.

- Add MaxPersonaFileSize bound check at the top of ParsePersonaBytes.
  While callers already check size, the public API should defend itself
  (defense in depth) against arbitrarily large inputs that could cause
  excessive memory/CPU before AST validation runs.

- Add tests for both behaviors.

Addresses review #2879 findings.
2026-05-13 06:44:13 -07:00
claw 787ac3b736 docs: address review findings on YAML depth validation
- Add safety note on Strict() decoder not expanding aliases recursively,
  since alias resolution uses the pre-validated AST (finding #1)
- Document that ast.Node map keys rely on pointer identity, which holds
  because all goccy/go-yaml AST types are pointer receivers (finding #2)
- Clarify AnchorNode comment: effective depth budget is reduced for
  anchor+alias pairs, not literally halved (finding #3)
- Improve test depth trace comment for accuracy (finding #4)
- Add HTML comment in CONVENTIONS.md referencing #91 for the two-step
  process deviation (finding #5)
2026-05-13 06:44:13 -07:00
claw 1200ef700d test: use per-subtest TempDir in TestYAMLEmptyFileRejection
Move t.TempDir() inside each subtest for idiomatic test isolation,
as suggested by reviewers.
2026-05-13 06:44:13 -07:00
claw 5e36547a1c fix: correct comment accuracy and improve trailing-content check clarity
- Fix validated map comment: says 'minimum depth' but stores the maximum
  depth at which a node was validated (overwritten on deeper visits).
- Replace dec.More() with explicit dec.Decode check for trailing JSON
  content. More() is documented for use inside arrays/objects; the
  explicit EOF check is clearer at the top-level stream.
2026-05-13 06:44:13 -07:00
claw 0522cfe3cb address self-review findings on PR #89
MINOR fixes:
- docs/DESIGN-57-yaml-persona.md: fix Error Cases table entry to reflect
  custom AST walk (checkYAMLDepth) instead of stale library-level reference
- review/persona.go: add EOF check after JSON decode to reject trailing
  garbage after a valid JSON object (prevents silent acceptance of malformed
  input like '{"name":"x"}garbage')
- review/persona_test.go: add TestJSONTrailingContentRejected test

NIT fixes:
- review/persona.go: add default case to checkYAMLDepth switch with
  explanatory comment about scalar leaf nodes
- review/persona.go: document AnchorNode depth+1 conservative asymmetry
- review/persona.go: simplify redundant if-guard in ListBuiltinPersonas
2026-05-13 06:44:13 -07:00
claw ee84c64151 fix(review): address review 2792 feedback
- Document nodeCount overcounting as intentional conservative behavior
  (bounds total validation work, not unique nodes)
- Improve TestYAMLDeeplyNestedRejection comment with concrete depth trace
- Replace outdated gopkg.in/yaml.v3 pseudocode in design doc with
  reference to authoritative implementation
- Update PR description to clarify pre-approval via issue #57
2026-05-13 06:44:13 -07:00
claw 3a1e5e443e fix(review): address feedback from reviews 2788, 2789, 2791
- Move nodeCount increment after cycle detection to avoid over-counting
  cyclic references (sonnet #2)
- Use underscores in test case names used as filenames (sonnet #3)
- Fix function comment: 'prevent silent data loss' → 'prevent confusing
  behavior where additional documents are silently ignored' (sonnet #4)
- Mark design doc pseudocode as historical since implementation uses
  goccy/go-yaml ast.Node, not gopkg.in/yaml.v3 yaml.Node (sonnet #5)
2026-05-13 06:44:13 -07:00
claw 9b1e93bfde fix(security): prevent alias depth bypass in YAML validator
The global 'seen' set allowed anchored subtrees validated at a shallow
depth to be skipped when later referenced via alias at a greater depth.
This could let effective nesting exceed MaxYAMLDepth, enabling DoS.

Fix: replace the single 'seen' set with two tracking maps:
- validated (node -> min depth): only short-circuits when current depth
  <= previously validated depth; re-checks at deeper contexts.
- visiting (node -> bool): per-path recursion stack for true cycle
  detection (breaks alias loops without suppressing depth checks).

Add TestYAMLAliasDepthBypass that constructs a document with an
anchored 15-level subtree referenced via alias under 6 levels of
nesting, verifying the combined effective depth (22) is rejected.

Addresses security-review-bot findings on review #2774.
2026-05-13 06:44:13 -07:00
rodin dbbc7bda6a docs: update DESIGN-57 to reflect goccy/go-yaml as the supported YAML library 2026-05-13 06:44:13 -07:00
rodin 93e2fbd58d docs: update YAML library to github.com/goccy/go-yaml in CONVENTIONS.md 2026-05-13 06:44:13 -07:00
claw 6f4461b0f7 fix(review): address review feedback on persona YAML handling
- Reorder empty doc check before multi-doc check for natural flow
- Detect nil-body docs (whitespace-only, comment-only input)
- Add explanatory comment on pointer identity for cycle detection map
- Improve depth-counting test comment with AST walker specifics
- Add TestYAMLEmptyFileRejection covering empty/whitespace/comment inputs

Addresses MINOR and NIT findings from sonnet, gpt, and security reviews.
MAJOR (allowlist violation) tracked in issue #91.
2026-05-13 06:44:13 -07:00
claw 32c89330aa fix(deps): replace gopkg.in/yaml.v3 with github.com/goccy/go-yaml
Fixes #87.

PR #58 incorrectly added gopkg.in/yaml.v3 (abandoned library) instead of
github.com/goccy/go-yaml as required by issue #57.

Changes:
- Replace gopkg.in/yaml.v3 with github.com/goccy/go-yaml v1.19.2
- Update review/persona.go to use goccy/go-yaml API:
  - parser.ParseBytes for AST-based depth/node count checking
  - yaml.Strict() decoder option instead of KnownFields(true)
  - ast.Node types instead of yaml.Node for tree walking
- Update review/persona_test.go to use ast types for cycle tests
- Remove gopkg.in/yaml.v3 from go.mod and go.sum

All existing YAML tests pass with the new library.
2026-05-13 06:44:13 -07:00
rodin 2036f57011 fix(patterns): default patterns-files to empty (fetch all) (#77) 2026-05-13 06:44:13 -07:00
aweiker 4e8c676515 Merge pull request 'feat(github): implement Reviewer and Identity interfaces (#81)' (#105) from review-bot-issue-81 into feature/github-support
Reviewed-on: #105
Reviewed-by: security-review-bot <10+security-review-bot@noreply.gitea.weiker.me>
Reviewed-by: Aaron Weiker <aaron@weiker.org>
2026-05-13 13:39:13 +00:00
claw 027bad2f7c fix(github): add DismissReview Event comment; use t.Fatalf for routing assertions
PR Ready Gate / clear-labels (pull_request) Successful in 2s
CI / test (pull_request) Successful in 19s
CI / review (anthropic--claude-4.6-sonnet, sonnet, SONNET_REVIEW_TOKEN) (pull_request) Successful in 33s
CI / review (gpt-5, security, ., rodin/security-patterns, SECURITY_REVIEW.md, SECURITY_REVIEW_TOKEN) (pull_request) Successful in 50s
CI / review (gpt-5, gpt, GPT_REVIEW_TOKEN) (pull_request) Successful in 1m48s
- Add comment in DismissReview explaining why the Event field is required
  by the GitHub API even though DISMISS is the only valid value (#18652).
- Change t.Errorf to t.Fatalf for method/path routing assertions in test
  handlers so failures are immediately fatal instead of silently
  continuing handler execution (#18653).
2026-05-13 13:18:46 +00:00
claw cd8a1becb3 test(github): use t.Run subtests in TestTranslateGitHubReviewState; doc: note nil body in DeleteReview 2026-05-13 13:18:46 +00:00
claw 9dd5e8dbac fix(github): validate conflicting commit IDs and extract test helper
Address review findings from sonnet-review-bot (review 3086):

- PostReview now returns ErrConflictingCommitIDs when comments specify
  different non-empty CommitIDs, since the GitHub API accepts only a
  single commit_id per review. Previously the discrepancy was silently
  ignored, using only the first commit's ID.

- Extract newTestClient into helpers_test.go to make cross-file sharing
  between review_test.go and identity_test.go explicit.

Refs: #81
2026-05-13 13:18:46 +00:00
claw 8b256360bf fix(github): clarify PostReview doc comment, rename test field to 'want'
Address review feedback from round-3 sonnet review:
- PostReview doc comment now accurately describes vcs.ReviewEvent → GitHub
  wire-format string cast and notes nil-Comments omitempty behavior.
- Rename 'expected' field to 'want' in TestTranslateGitHubReviewState to
  match the project's established naming convention.
2026-05-13 13:18:46 +00:00
claw 293296b50c address review feedback: wrap ErrCannotDeleteSubmittedReview, fix nits
- Wrap ErrCannotDeleteSubmittedReview with operation context via fmt.Errorf
  so callers get both sentinel identity and context (MINOR fix)
- Combine double iteration in PostReview into single loop (NIT)
- Remove extra trailing blank line in review_test.go (NIT)
- Clarify translateGitHubReviewState comment re: PENDING state (NIT)
- Update requestOptions.bodyFn comment to mention DELETE-with-body (NIT)
2026-05-13 13:18:46 +00:00
claw eba97321ad refactor(github): extract doRequestCore, address review feedback
- MAJOR: Extract doRequestCore to eliminate doRequest/doRequestWithBody
  duplication. Both now delegate to a shared implementation with the
  retry/backoff logic in a single place.

- MINOR: Replace custom containsStr/containsSubstring helpers with
  strings.Contains in review_test.go.

- MINOR: Use http.Method* constants (MethodPost, MethodDelete, MethodPut)
  in review.go for consistency with doGet.

- MINOR: Remove redundant APPROVED/DISMISSED cases from
  translateGitHubReviewState that were identical to the default passthrough.

- NIT: Clarify DeleteReview comment about COMMENTED being a GitHub API
  state name.

- DismissReview Event field verified as required by GitHub API docs;
  kept as-is.
2026-05-13 13:18:46 +00:00
claw be3f696a70 feat(github): implement Reviewer and Identity interfaces (#81)
Implement the remaining vcs.Client interface methods for github.Client:

Reviewer:
- PostReview: POST /repos/{owner}/{repo}/pulls/{number}/reviews
- ListReviews: GET /repos/{owner}/{repo}/pulls/{number}/reviews
  with state translation (CHANGES_REQUESTED → REQUEST_CHANGES, etc.)
- DeleteReview: DELETE /repos/{owner}/{repo}/pulls/{number}/reviews/{id}
  Returns ErrCannotDeleteSubmittedReview on 422
- DismissReview: PUT /repos/{owner}/{repo}/pulls/{number}/reviews/{id}/dismissals

Identity:
- GetAuthenticatedUser: GET /user

Infrastructure:
- Add doRequestWithBody helper for POST/PUT/DELETE with JSON bodies
- Update conformance_test.go: var _ vcs.Client = (*github.Client)(nil)

All unit tests pass including error cases (401, 404, 422, malformed).
2026-05-13 13:18:46 +00:00
aweiker 65ba8af244 Merge pull request 'fix(gitea): map hunk-header positions in BuildPositionToLineMap' (#104) from review-bot-issue-97 into feature/github-support
Reviewed-on: #104
Reviewed-by: security-review-bot <10+security-review-bot@noreply.gitea.weiker.me>
Reviewed-by: Aaron Weiker <aaron@weiker.org>
2026-05-13 13:15:30 +00:00
claw 02bdd701a5 test(gitea): add hunk-header-at-end error path test
PR Ready Gate / clear-labels (pull_request) Successful in 2s
CI / test (pull_request) Successful in 20s
CI / review (anthropic--claude-4.6-sonnet, sonnet, SONNET_REVIEW_TOKEN) (pull_request) Successful in 23s
CI / review (gpt-5, security, ., rodin/security-patterns, SECURITY_REVIEW.md, SECURITY_REVIEW_TOKEN) (pull_request) Successful in 34s
CI / review (gpt-5, gpt, GPT_REVIEW_TOKEN) (pull_request) Successful in 1m39s
Adds TestTranslate_HunkHeaderAtEnd covering the edge case where a
hunk-header is the last position in the file with no subsequent
new-file line. Mirrors TestBuildPositionToLineMap_DeletionAtEnd for
the hunk-header code path.

Addresses NIT from sonnet-review-bot on PR #104 (comment 18412).
2026-05-12 23:32:22 -07:00
claw 23dc781908 fix(gitea): map hunk-header positions in BuildPositionToLineMap
CI / test (pull_request) Successful in 28s
CI / review (anthropic--claude-4.6-sonnet, sonnet, SONNET_REVIEW_TOKEN) (pull_request) Successful in 27s
CI / review (gpt-5, security, ., rodin/security-patterns, SECURITY_REVIEW.md, SECURITY_REVIEW_TOKEN) (pull_request) Successful in 44s
CI / review (gpt-5, gpt, GPT_REVIEW_TOKEN) (pull_request) Successful in 1m49s
BuildPositionToLineMap incremented position and updated maxPositions for
@@ hunk-header lines but did not store a map entry, causing Translate()
to return a hard error for any comment positioned at a hunk header.

Store sentinel value 0 for hunk-header positions (analogous to -1 for
deletions) and extend Translate() to fall through to the nearest
context/addition line below, matching the existing deletion-line
behavior.

Fixes #97
2026-05-12 23:13:28 -07:00
aweiker 1960d987ed Merge pull request 'feat(github): implement FileReader interface' (#103) from issue-80-c-file-reader into feature/github-support
Reviewed-on: #103
Reviewed-by: Aaron Weiker <aaron@weiker.org>
Reviewed-by: security-review-bot <10+security-review-bot@noreply.gitea.weiker.me>
2026-05-13 06:05:58 +00:00
claw dca260f582 fix(test): SetRetryBackoff with correct slice length
PR Ready Gate / clear-labels (pull_request) Successful in 1s
CI / test (pull_request) Successful in 19s
CI / review (anthropic--claude-4.6-sonnet, sonnet, SONNET_REVIEW_TOKEN) (pull_request) Successful in 32s
CI / review (gpt-5, security, ., rodin/security-patterns, SECURITY_REVIEW.md, SECURITY_REVIEW_TOKEN) (pull_request) Successful in 1m56s
CI / review (gpt-5, gpt, GPT_REVIEW_TOKEN) (pull_request) Successful in 2m33s
Pass 2 elements to SetRetryBackoff (matching maxRetryAttempts-1 = 2)
and check the error return. Previously passing 1 element silently
failed, causing tests to fall back to default {1s, 2s} backoffs.

Fixes self-review finding: 429Retry tests now run in <10ms instead
of ~1s.
2026-05-12 22:47:31 -07:00
aweiker 921599542d feat(github): implement FileReader interface (#80)
PR Ready Gate / clear-labels (pull_request) Successful in 2s
CI / test (pull_request) Successful in 21s
CI / review (anthropic--claude-4.6-sonnet, sonnet, SONNET_REVIEW_TOKEN) (pull_request) Successful in 34s
CI / review (gpt-5, security, ., rodin/security-patterns, SECURITY_REVIEW.md, SECURITY_REVIEW_TOKEN) (pull_request) Successful in 1m6s
CI / review (gpt-5, gpt, GPT_REVIEW_TOKEN) (pull_request) Successful in 2m53s
Implement FileReader conformance on the GitHub client: GetFileContent,
ListContents, path helpers, base64 decode. Includes compile-time
conformance checks for both PRReader and FileReader.

Requires PR B (#102). Part 3 of 3 for #80.
2026-05-13 05:33:30 +00:00
aweiker 71bb33b6fd Merge pull request 'feat(github): implement PRReader interface' (#102) from issue-80-b-pr-reader into feature/github-support
Reviewed-on: #102
Reviewed-by: security-review-bot <10+security-review-bot@noreply.gitea.weiker.me>
Reviewed-by: Aaron Weiker <aaron@weiker.org>
2026-05-13 05:30:37 +00:00
claw 55366b3431 fix: address review feedback on PRReader implementation
PR Ready Gate / clear-labels (pull_request) Successful in 2s
CI / test (pull_request) Successful in 19s
CI / review (anthropic--claude-4.6-sonnet, sonnet, SONNET_REVIEW_TOKEN) (pull_request) Successful in 45s
CI / review (gpt-5, gpt, GPT_REVIEW_TOKEN) (pull_request) Successful in 1m55s
CI / review (gpt-5, security, ., rodin/security-patterns, SECURITY_REVIEW.md, SECURITY_REVIEW_TOKEN) (pull_request) Successful in 1m55s
- Add maxFileContentSize (10 MB) limit to decodeBase64Content to prevent
  resource exhaustion from oversized file content (security MINOR)
- Fix reversed NewClient arg order in TestGetFileContentAtRef_DotSegmentError
  (GPT MINOR + Sonnet NIT)
- Remove 'waiting' from mapCheckRunStatus conclusion cases since it is a
  status value not a conclusion, update comment (GPT NIT)
- Add TestDecodeBase64Content_SizeLimit test
2026-05-12 22:17:32 -07:00
claw 3cd5ae594e fix(github): escapePath returns error on dot-segments, fix Description semantics
PR Ready Gate / clear-labels (pull_request) Successful in 1s
CI / test (pull_request) Successful in 23s
CI / review (anthropic--claude-4.6-sonnet, sonnet, SONNET_REVIEW_TOKEN) (pull_request) Successful in 33s
CI / review (gpt-5, security, ., rodin/security-patterns, SECURITY_REVIEW.md, SECURITY_REVIEW_TOKEN) (pull_request) Successful in 1m24s
CI / review (gpt-5, gpt, GPT_REVIEW_TOKEN) (pull_request) Successful in 1m44s
- escapePath now returns an error when paths contain dot-segments
  (".", "..") instead of silently rewriting them. This prevents
  subtle API misses where callers pass "foo/../bar" expecting to
  hit "bar" but the old code produced "foo/bar".
- Uses path.Clean for canonical form after validation.
- CommitStatus.Description for check runs is now empty string
  instead of the raw conclusion enum. The conclusion is already
  captured in the Status field via mapCheckRunStatus; storing it
  again in Description was semantically inconsistent with commit
  statuses where Description carries a human-readable narrative.
- Removed unused derefString helper.
- Added tests for escapePath valid paths, dot-segment rejection,
  and GetFileContentAtRef dot-segment error propagation.
2026-05-12 22:03:52 -07:00
claw eaccc96073 fix: address review feedback on PR #102
PR Ready Gate / clear-labels (pull_request) Successful in 2s
CI / test (pull_request) Successful in 27s
CI / review (anthropic--claude-4.6-sonnet, sonnet, SONNET_REVIEW_TOKEN) (pull_request) Successful in 42s
CI / review (gpt-5, gpt, GPT_REVIEW_TOKEN) (pull_request) Successful in 1m11s
CI / review (gpt-5, security, ., rodin/security-patterns, SECURITY_REVIEW.md, SECURITY_REVIEW_TOKEN) (pull_request) Successful in 1m13s
- Separate maxPages into maxFilesPages and maxCheckRunPages constants
  for clarity (sonnet MINOR #1)
- Add parallel to CheckRunConclusions subtests (sonnet MINOR #2)
- Add TestGetCommitStatuses_CheckRunsErrorAfterStatusesSucceed test
  covering check-runs 500 after statuses succeed (sonnet MINOR #2)
- Expand mapCheckRunStatus doc comment with full mapping rules including
  cancelled/skipped/neutral rationale and unknown value behavior
  (sonnet MINOR #3, gpt MINOR #1)
- Expand GetPullRequest doc comment to mention error types returned
  (sonnet NIT #4)
- Add inline comment on Description field clarifying it holds raw
  conclusion value (gpt NIT #3)
2026-05-13 04:47:15 +00:00
claw 289b400bfd fix(github): add GetFileContentAtRef and fix conformance test
- Implement GetFileContentAtRef on *Client to satisfy vcs.PRReader interface
- Add escapePath and decodeBase64Content helpers
- Fix conformance_test.go to properly import and qualify github.Client
  (was using unqualified Client in package github_test)

Fixes CI failure: the PRReader interface requires GetFileContentAtRef
but it was missing from this PR (only present in the file-reader PR).
2026-05-13 04:47:15 +00:00
aweiker d0b7f09772 feat(github): implement PRReader interface (#80)
Implement PRReader conformance on the GitHub client: GetPullRequest,
GetPullRequestDiff, GetPullRequestFiles (paginated, populates Patch),
GetCommitStatuses (merges commit statuses + check runs).
Adds compile-time PRReader conformance check.

Requires PR A. Part 2 of 3 for #80.
2026-05-13 04:47:15 +00:00
aweiker 377da8ca3a Merge pull request 'feat(github): implement GitHub API client foundation' (#101) from issue-80-a-client into feature/github-support
Reviewed-on: #101
Reviewed-by: security-review-bot <10+security-review-bot@noreply.gitea.weiker.me>
Reviewed-by: Aaron Weiker <aaron@weiker.org>
2026-05-13 04:46:46 +00:00
claw 61819ac3e3 fix(github): address review findings - remove panic, validate at config time
PR Ready Gate / clear-labels (pull_request) Successful in 2s
CI / test (pull_request) Successful in 17s
CI / review (anthropic--claude-4.6-sonnet, sonnet, SONNET_REVIEW_TOKEN) (pull_request) Successful in 36s
CI / review (gpt-5, gpt, GPT_REVIEW_TOKEN) (pull_request) Successful in 1m35s
CI / review (gpt-5, security, ., rodin/security-patterns, SECURITY_REVIEW.md, SECURITY_REVIEW_TOKEN) (pull_request) Successful in 2m7s
- MAJOR #1: Replace panic in doRequest with safe default fallback.
  Validation now happens in SetRetryBackoff (returns error on invalid
  length). doRequest gracefully falls back to default backoff if the
  configured slice is somehow invalid.

- MINOR #2: SetRetryBackoff validates slice length at configuration
  time, making the coupling between maxRetryAttempts and backoff
  explicit and catching mismatches early with a clear error.

- MINOR #4: Reword oversized response error to remove '(truncated)'
  which implied truncated data was returned when actually only an
  error is returned.

- MINOR #5: Functional options kept as-is - idiomatic Go pattern
  that allows future growth without breaking the API.
2026-05-12 21:31:45 -07:00
claw 3d1260d3b2 fix(github): clarify response ownership and validate backoff length
PR Ready Gate / clear-labels (pull_request) Successful in 2s
CI / test (pull_request) Successful in 18s
CI / review (anthropic--claude-4.6-sonnet, sonnet, SONNET_REVIEW_TOKEN) (pull_request) Successful in 40s
CI / review (gpt-5, gpt, GPT_REVIEW_TOKEN) (pull_request) Successful in 1m22s
CI / review (gpt-5, security, ., rodin/security-patterns, SECURITY_REVIEW.md, SECURITY_REVIEW_TOKEN) (pull_request) Successful in 1m51s
Address review feedback on PR #101:

1. Capture resp.StatusCode and Retry-After header *before* passing resp
   to handleResponse, making ownership transfer explicit. Previously the
   caller read resp.StatusCode after handleResponse had closed the body —
   correct but fragile coupling.

2. Add panic guard ensuring backoff slice length equals maxAttempts-1.
   Previously the relationship was implicit and could silently break if
   maxAttempts were changed without updating the default backoff.
2026-05-12 21:26:39 -07:00
aweiker 0e7e12a99c feat(github): implement GitHub API client foundation (#80)
CI / test (pull_request) Successful in 18s
CI / review (anthropic--claude-4.6-sonnet, sonnet, SONNET_REVIEW_TOKEN) (pull_request) Successful in 41s
CI / review (gpt-5, security, ., rodin/security-patterns, SECURITY_REVIEW.md, SECURITY_REVIEW_TOKEN) (pull_request) Successful in 1m7s
CI / review (gpt-5, gpt, GPT_REVIEW_TOKEN) (pull_request) Successful in 1m11s
Add GitHub API client with configurable base URL and GHE support,
HTTP helpers with 429 retry and Retry-After handling.
Also adds Patch field to vcs.ChangedFile.

Part 1 of 3 for #80.
2026-05-13 04:11:53 +00:00
aweiker 1862dc999d Merge pull request 'feat(vcs): Gitea adapter with diff-position translation (Phase 2)' (#90) from review-bot-issue-79 into feature/github-support
Reviewed-on: #90
Reviewed-by: security-review-bot <10+security-review-bot@noreply.gitea.weiker.me>
Reviewed-by: Aaron Weiker <aaron@weiker.org>
2026-05-13 00:18:05 +00:00