@humanbased/crosscheck 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENT.md +207 -0
- package/ISSUE.md +234 -0
- package/LICENSE +21 -0
- package/README.md +234 -0
- package/README.zh.md +169 -0
- package/assets/logo.png +0 -0
- package/assets/screenshot-watch-timing.png +0 -0
- package/assets/screenshot-watch-timing.svg +1 -0
- package/assets/screenshot-watch.png +0 -0
- package/crosscheck.config.example.yml +214 -0
- package/dist/__tests__/annotation.test.d.ts +2 -0
- package/dist/__tests__/annotation.test.d.ts.map +1 -0
- package/dist/__tests__/annotation.test.js +134 -0
- package/dist/__tests__/annotation.test.js.map +1 -0
- package/dist/__tests__/backtrace.test.d.ts +2 -0
- package/dist/__tests__/backtrace.test.d.ts.map +1 -0
- package/dist/__tests__/backtrace.test.js +280 -0
- package/dist/__tests__/backtrace.test.js.map +1 -0
- package/dist/__tests__/board.test.d.ts +2 -0
- package/dist/__tests__/board.test.d.ts.map +1 -0
- package/dist/__tests__/board.test.js +149 -0
- package/dist/__tests__/board.test.js.map +1 -0
- package/dist/__tests__/codex.test.d.ts +2 -0
- package/dist/__tests__/codex.test.d.ts.map +1 -0
- package/dist/__tests__/codex.test.js +92 -0
- package/dist/__tests__/codex.test.js.map +1 -0
- package/dist/__tests__/comment-bodies.test.d.ts +2 -0
- package/dist/__tests__/comment-bodies.test.d.ts.map +1 -0
- package/dist/__tests__/comment-bodies.test.js +75 -0
- package/dist/__tests__/comment-bodies.test.js.map +1 -0
- package/dist/__tests__/conflict-resolve.test.d.ts +2 -0
- package/dist/__tests__/conflict-resolve.test.d.ts.map +1 -0
- package/dist/__tests__/conflict-resolve.test.js +123 -0
- package/dist/__tests__/conflict-resolve.test.js.map +1 -0
- package/dist/__tests__/crosscheck-commit.test.d.ts +2 -0
- package/dist/__tests__/crosscheck-commit.test.d.ts.map +1 -0
- package/dist/__tests__/crosscheck-commit.test.js +13 -0
- package/dist/__tests__/crosscheck-commit.test.js.map +1 -0
- package/dist/__tests__/detector.test.d.ts +2 -0
- package/dist/__tests__/detector.test.d.ts.map +1 -0
- package/dist/__tests__/detector.test.js +112 -0
- package/dist/__tests__/detector.test.js.map +1 -0
- package/dist/__tests__/diagnose.test.d.ts +2 -0
- package/dist/__tests__/diagnose.test.d.ts.map +1 -0
- package/dist/__tests__/diagnose.test.js +164 -0
- package/dist/__tests__/diagnose.test.js.map +1 -0
- package/dist/__tests__/diff-hash.test.d.ts +2 -0
- package/dist/__tests__/diff-hash.test.d.ts.map +1 -0
- package/dist/__tests__/diff-hash.test.js +126 -0
- package/dist/__tests__/diff-hash.test.js.map +1 -0
- package/dist/__tests__/durations.test.d.ts +2 -0
- package/dist/__tests__/durations.test.d.ts.map +1 -0
- package/dist/__tests__/durations.test.js +26 -0
- package/dist/__tests__/durations.test.js.map +1 -0
- package/dist/__tests__/event-fields.test.d.ts +2 -0
- package/dist/__tests__/event-fields.test.d.ts.map +1 -0
- package/dist/__tests__/event-fields.test.js +50 -0
- package/dist/__tests__/event-fields.test.js.map +1 -0
- package/dist/__tests__/filter.test.d.ts +2 -0
- package/dist/__tests__/filter.test.d.ts.map +1 -0
- package/dist/__tests__/filter.test.js +21 -0
- package/dist/__tests__/filter.test.js.map +1 -0
- package/dist/__tests__/fix.test.d.ts +2 -0
- package/dist/__tests__/fix.test.d.ts.map +1 -0
- package/dist/__tests__/fix.test.js +124 -0
- package/dist/__tests__/fix.test.js.map +1 -0
- package/dist/__tests__/github-client.test.d.ts +2 -0
- package/dist/__tests__/github-client.test.d.ts.map +1 -0
- package/dist/__tests__/github-client.test.js +22 -0
- package/dist/__tests__/github-client.test.js.map +1 -0
- package/dist/__tests__/github-scan-client.test.d.ts +2 -0
- package/dist/__tests__/github-scan-client.test.d.ts.map +1 -0
- package/dist/__tests__/github-scan-client.test.js +100 -0
- package/dist/__tests__/github-scan-client.test.js.map +1 -0
- package/dist/__tests__/is-fresh-review-comment.test.d.ts +2 -0
- package/dist/__tests__/is-fresh-review-comment.test.d.ts.map +1 -0
- package/dist/__tests__/is-fresh-review-comment.test.js +86 -0
- package/dist/__tests__/is-fresh-review-comment.test.js.map +1 -0
- package/dist/__tests__/issue.test.d.ts +2 -0
- package/dist/__tests__/issue.test.d.ts.map +1 -0
- package/dist/__tests__/issue.test.js +259 -0
- package/dist/__tests__/issue.test.js.map +1 -0
- package/dist/__tests__/kickass.test.d.ts +2 -0
- package/dist/__tests__/kickass.test.d.ts.map +1 -0
- package/dist/__tests__/kickass.test.js +268 -0
- package/dist/__tests__/kickass.test.js.map +1 -0
- package/dist/__tests__/loader.test.d.ts +2 -0
- package/dist/__tests__/loader.test.d.ts.map +1 -0
- package/dist/__tests__/loader.test.js +180 -0
- package/dist/__tests__/loader.test.js.map +1 -0
- package/dist/__tests__/onboard-preservation.test.d.ts +2 -0
- package/dist/__tests__/onboard-preservation.test.d.ts.map +1 -0
- package/dist/__tests__/onboard-preservation.test.js +506 -0
- package/dist/__tests__/onboard-preservation.test.js.map +1 -0
- package/dist/__tests__/optimize.test.d.ts +2 -0
- package/dist/__tests__/optimize.test.d.ts.map +1 -0
- package/dist/__tests__/optimize.test.js +101 -0
- package/dist/__tests__/optimize.test.js.map +1 -0
- package/dist/__tests__/post-review-comment.test.d.ts +2 -0
- package/dist/__tests__/post-review-comment.test.d.ts.map +1 -0
- package/dist/__tests__/post-review-comment.test.js +44 -0
- package/dist/__tests__/post-review-comment.test.js.map +1 -0
- package/dist/__tests__/pr-lock.test.d.ts +2 -0
- package/dist/__tests__/pr-lock.test.d.ts.map +1 -0
- package/dist/__tests__/pr-lock.test.js +115 -0
- package/dist/__tests__/pr-lock.test.js.map +1 -0
- package/dist/__tests__/pr-picker.test.d.ts +2 -0
- package/dist/__tests__/pr-picker.test.d.ts.map +1 -0
- package/dist/__tests__/pr-picker.test.js +57 -0
- package/dist/__tests__/pr-picker.test.js.map +1 -0
- package/dist/__tests__/pr-status-scan.test.d.ts +2 -0
- package/dist/__tests__/pr-status-scan.test.d.ts.map +1 -0
- package/dist/__tests__/pr-status-scan.test.js +92 -0
- package/dist/__tests__/pr-status-scan.test.js.map +1 -0
- package/dist/__tests__/pr-status.test.d.ts +2 -0
- package/dist/__tests__/pr-status.test.d.ts.map +1 -0
- package/dist/__tests__/pr-status.test.js +346 -0
- package/dist/__tests__/pr-status.test.js.map +1 -0
- package/dist/__tests__/repo-picker.test.d.ts +2 -0
- package/dist/__tests__/repo-picker.test.d.ts.map +1 -0
- package/dist/__tests__/repo-picker.test.js +115 -0
- package/dist/__tests__/repo-picker.test.js.map +1 -0
- package/dist/__tests__/review-comment-body.test.d.ts +2 -0
- package/dist/__tests__/review-comment-body.test.d.ts.map +1 -0
- package/dist/__tests__/review-comment-body.test.js +54 -0
- package/dist/__tests__/review-comment-body.test.js.map +1 -0
- package/dist/__tests__/review-models.test.d.ts +2 -0
- package/dist/__tests__/review-models.test.d.ts.map +1 -0
- package/dist/__tests__/review-models.test.js +39 -0
- package/dist/__tests__/review-models.test.js.map +1 -0
- package/dist/__tests__/review-status.test.d.ts +2 -0
- package/dist/__tests__/review-status.test.d.ts.map +1 -0
- package/dist/__tests__/review-status.test.js +95 -0
- package/dist/__tests__/review-status.test.js.map +1 -0
- package/dist/__tests__/runner.test.d.ts +2 -0
- package/dist/__tests__/runner.test.d.ts.map +1 -0
- package/dist/__tests__/runner.test.js +204 -0
- package/dist/__tests__/runner.test.js.map +1 -0
- package/dist/__tests__/scan-cache.test.d.ts +2 -0
- package/dist/__tests__/scan-cache.test.d.ts.map +1 -0
- package/dist/__tests__/scan-cache.test.js +59 -0
- package/dist/__tests__/scan-cache.test.js.map +1 -0
- package/dist/__tests__/scan-client.test.d.ts +2 -0
- package/dist/__tests__/scan-client.test.d.ts.map +1 -0
- package/dist/__tests__/scan-client.test.js +30 -0
- package/dist/__tests__/scan-client.test.js.map +1 -0
- package/dist/__tests__/scan.test.d.ts +2 -0
- package/dist/__tests__/scan.test.d.ts.map +1 -0
- package/dist/__tests__/scan.test.js +115 -0
- package/dist/__tests__/scan.test.js.map +1 -0
- package/dist/__tests__/scopes.test.d.ts +2 -0
- package/dist/__tests__/scopes.test.d.ts.map +1 -0
- package/dist/__tests__/scopes.test.js +101 -0
- package/dist/__tests__/scopes.test.js.map +1 -0
- package/dist/__tests__/sha-cache.test.d.ts +2 -0
- package/dist/__tests__/sha-cache.test.d.ts.map +1 -0
- package/dist/__tests__/sha-cache.test.js +40 -0
- package/dist/__tests__/sha-cache.test.js.map +1 -0
- package/dist/__tests__/smart-switch.test.d.ts +2 -0
- package/dist/__tests__/smart-switch.test.d.ts.map +1 -0
- package/dist/__tests__/smart-switch.test.js +145 -0
- package/dist/__tests__/smart-switch.test.js.map +1 -0
- package/dist/ck.d.ts +3 -0
- package/dist/ck.d.ts.map +1 -0
- package/dist/ck.js +8 -0
- package/dist/ck.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +132 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/diagnose.d.ts +54 -0
- package/dist/commands/diagnose.d.ts.map +1 -0
- package/dist/commands/diagnose.js +294 -0
- package/dist/commands/diagnose.js.map +1 -0
- package/dist/commands/impact.d.ts +38 -0
- package/dist/commands/impact.d.ts.map +1 -0
- package/dist/commands/impact.js +210 -0
- package/dist/commands/impact.js.map +1 -0
- package/dist/commands/init.d.ts +12 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +183 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/issue.d.ts +25 -0
- package/dist/commands/issue.d.ts.map +1 -0
- package/dist/commands/issue.js +445 -0
- package/dist/commands/issue.js.map +1 -0
- package/dist/commands/kickass.d.ts +59 -0
- package/dist/commands/kickass.d.ts.map +1 -0
- package/dist/commands/kickass.js +288 -0
- package/dist/commands/kickass.js.map +1 -0
- package/dist/commands/onboard.d.ts +70 -0
- package/dist/commands/onboard.d.ts.map +1 -0
- package/dist/commands/onboard.js +883 -0
- package/dist/commands/onboard.js.map +1 -0
- package/dist/commands/optimize.d.ts +16 -0
- package/dist/commands/optimize.d.ts.map +1 -0
- package/dist/commands/optimize.js +244 -0
- package/dist/commands/optimize.js.map +1 -0
- package/dist/commands/review.d.ts +2 -0
- package/dist/commands/review.d.ts.map +1 -0
- package/dist/commands/review.js +118 -0
- package/dist/commands/review.js.map +1 -0
- package/dist/commands/run.d.ts +13 -0
- package/dist/commands/run.d.ts.map +1 -0
- package/dist/commands/run.js +243 -0
- package/dist/commands/run.js.map +1 -0
- package/dist/commands/scan.d.ts +94 -0
- package/dist/commands/scan.d.ts.map +1 -0
- package/dist/commands/scan.js +276 -0
- package/dist/commands/scan.js.map +1 -0
- package/dist/commands/serve.d.ts +9 -0
- package/dist/commands/serve.d.ts.map +1 -0
- package/dist/commands/serve.js +402 -0
- package/dist/commands/serve.js.map +1 -0
- package/dist/commands/status.d.ts +2 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +89 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/watch.d.ts +9 -0
- package/dist/commands/watch.d.ts.map +1 -0
- package/dist/commands/watch.js +902 -0
- package/dist/commands/watch.js.map +1 -0
- package/dist/config/loader.d.ts +47 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +334 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/config/schema.d.ts +814 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +152 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/github/client.d.ts +139 -0
- package/dist/github/client.d.ts.map +1 -0
- package/dist/github/client.js +711 -0
- package/dist/github/client.js.map +1 -0
- package/dist/github/detector.d.ts +12 -0
- package/dist/github/detector.d.ts.map +1 -0
- package/dist/github/detector.js +120 -0
- package/dist/github/detector.js.map +1 -0
- package/dist/github/merge.d.ts +9 -0
- package/dist/github/merge.d.ts.map +1 -0
- package/dist/github/merge.js +33 -0
- package/dist/github/merge.js.map +1 -0
- package/dist/github/review-status.d.ts +6 -0
- package/dist/github/review-status.d.ts.map +1 -0
- package/dist/github/review-status.js +51 -0
- package/dist/github/review-status.js.map +1 -0
- package/dist/github/webhook.d.ts +41 -0
- package/dist/github/webhook.d.ts.map +1 -0
- package/dist/github/webhook.js +50 -0
- package/dist/github/webhook.js.map +1 -0
- package/dist/lib/annotation.d.ts +23 -0
- package/dist/lib/annotation.d.ts.map +1 -0
- package/dist/lib/annotation.js +103 -0
- package/dist/lib/annotation.js.map +1 -0
- package/dist/lib/backtrace.d.ts +40 -0
- package/dist/lib/backtrace.d.ts.map +1 -0
- package/dist/lib/backtrace.js +169 -0
- package/dist/lib/backtrace.js.map +1 -0
- package/dist/lib/board.d.ts +74 -0
- package/dist/lib/board.d.ts.map +1 -0
- package/dist/lib/board.js +640 -0
- package/dist/lib/board.js.map +1 -0
- package/dist/lib/clone.d.ts +12 -0
- package/dist/lib/clone.d.ts.map +1 -0
- package/dist/lib/clone.js +30 -0
- package/dist/lib/clone.js.map +1 -0
- package/dist/lib/comment-bodies.d.ts +17 -0
- package/dist/lib/comment-bodies.d.ts.map +1 -0
- package/dist/lib/comment-bodies.js +51 -0
- package/dist/lib/comment-bodies.js.map +1 -0
- package/dist/lib/crosscheck-commit.d.ts +2 -0
- package/dist/lib/crosscheck-commit.d.ts.map +1 -0
- package/dist/lib/crosscheck-commit.js +4 -0
- package/dist/lib/crosscheck-commit.js.map +1 -0
- package/dist/lib/diff-hash.d.ts +16 -0
- package/dist/lib/diff-hash.d.ts.map +1 -0
- package/dist/lib/diff-hash.js +71 -0
- package/dist/lib/diff-hash.js.map +1 -0
- package/dist/lib/durations.d.ts +5 -0
- package/dist/lib/durations.d.ts.map +1 -0
- package/dist/lib/durations.js +39 -0
- package/dist/lib/durations.js.map +1 -0
- package/dist/lib/event-fields.d.ts +6 -0
- package/dist/lib/event-fields.d.ts.map +1 -0
- package/dist/lib/event-fields.js +20 -0
- package/dist/lib/event-fields.js.map +1 -0
- package/dist/lib/filter.d.ts +2 -0
- package/dist/lib/filter.d.ts.map +1 -0
- package/dist/lib/filter.js +4 -0
- package/dist/lib/filter.js.map +1 -0
- package/dist/lib/fortune.d.ts +2 -0
- package/dist/lib/fortune.d.ts.map +1 -0
- package/dist/lib/fortune.js +26 -0
- package/dist/lib/fortune.js.map +1 -0
- package/dist/lib/languages.d.ts +3 -0
- package/dist/lib/languages.d.ts.map +1 -0
- package/dist/lib/languages.js +26 -0
- package/dist/lib/languages.js.map +1 -0
- package/dist/lib/log-analysis.d.ts +17 -0
- package/dist/lib/log-analysis.d.ts.map +1 -0
- package/dist/lib/log-analysis.js +72 -0
- package/dist/lib/log-analysis.js.map +1 -0
- package/dist/lib/logger.d.ts +14 -0
- package/dist/lib/logger.d.ts.map +1 -0
- package/dist/lib/logger.js +84 -0
- package/dist/lib/logger.js.map +1 -0
- package/dist/lib/port.d.ts +2 -0
- package/dist/lib/port.d.ts.map +1 -0
- package/dist/lib/port.js +21 -0
- package/dist/lib/port.js.map +1 -0
- package/dist/lib/pr-lock.d.ts +4 -0
- package/dist/lib/pr-lock.d.ts.map +1 -0
- package/dist/lib/pr-lock.js +91 -0
- package/dist/lib/pr-lock.js.map +1 -0
- package/dist/lib/pr-picker.d.ts +10 -0
- package/dist/lib/pr-picker.d.ts.map +1 -0
- package/dist/lib/pr-picker.js +80 -0
- package/dist/lib/pr-picker.js.map +1 -0
- package/dist/lib/pr-status.d.ts +206 -0
- package/dist/lib/pr-status.d.ts.map +1 -0
- package/dist/lib/pr-status.js +613 -0
- package/dist/lib/pr-status.js.map +1 -0
- package/dist/lib/repo-picker.d.ts +23 -0
- package/dist/lib/repo-picker.d.ts.map +1 -0
- package/dist/lib/repo-picker.js +411 -0
- package/dist/lib/repo-picker.js.map +1 -0
- package/dist/lib/review-models.d.ts +7 -0
- package/dist/lib/review-models.d.ts.map +1 -0
- package/dist/lib/review-models.js +32 -0
- package/dist/lib/review-models.js.map +1 -0
- package/dist/lib/runner.d.ts +65 -0
- package/dist/lib/runner.d.ts.map +1 -0
- package/dist/lib/runner.js +710 -0
- package/dist/lib/runner.js.map +1 -0
- package/dist/lib/scan-cache.d.ts +31 -0
- package/dist/lib/scan-cache.d.ts.map +1 -0
- package/dist/lib/scan-cache.js +112 -0
- package/dist/lib/scan-cache.js.map +1 -0
- package/dist/lib/scopes.d.ts +16 -0
- package/dist/lib/scopes.d.ts.map +1 -0
- package/dist/lib/scopes.js +37 -0
- package/dist/lib/scopes.js.map +1 -0
- package/dist/lib/sha-cache.d.ts +7 -0
- package/dist/lib/sha-cache.d.ts.map +1 -0
- package/dist/lib/sha-cache.js +44 -0
- package/dist/lib/sha-cache.js.map +1 -0
- package/dist/lib/smart-switch.d.ts +44 -0
- package/dist/lib/smart-switch.d.ts.map +1 -0
- package/dist/lib/smart-switch.js +145 -0
- package/dist/lib/smart-switch.js.map +1 -0
- package/dist/lib/verdict.d.ts +9 -0
- package/dist/lib/verdict.d.ts.map +1 -0
- package/dist/lib/verdict.js +52 -0
- package/dist/lib/verdict.js.map +1 -0
- package/dist/lib/workflow.d.ts +85 -0
- package/dist/lib/workflow.d.ts.map +1 -0
- package/dist/lib/workflow.js +116 -0
- package/dist/lib/workflow.js.map +1 -0
- package/dist/reviewers/address.d.ts +5 -0
- package/dist/reviewers/address.d.ts.map +1 -0
- package/dist/reviewers/address.js +87 -0
- package/dist/reviewers/address.js.map +1 -0
- package/dist/reviewers/claude.d.ts +12 -0
- package/dist/reviewers/claude.d.ts.map +1 -0
- package/dist/reviewers/claude.js +78 -0
- package/dist/reviewers/claude.js.map +1 -0
- package/dist/reviewers/codex.d.ts +9 -0
- package/dist/reviewers/codex.d.ts.map +1 -0
- package/dist/reviewers/codex.js +121 -0
- package/dist/reviewers/codex.js.map +1 -0
- package/dist/reviewers/conflict-resolve.d.ts +15 -0
- package/dist/reviewers/conflict-resolve.d.ts.map +1 -0
- package/dist/reviewers/conflict-resolve.js +219 -0
- package/dist/reviewers/conflict-resolve.js.map +1 -0
- package/dist/reviewers/fix.d.ts +7 -0
- package/dist/reviewers/fix.d.ts.map +1 -0
- package/dist/reviewers/fix.js +197 -0
- package/dist/reviewers/fix.js.map +1 -0
- package/get-started.md +1271 -0
- package/get-started.zh.md +1208 -0
- package/package.json +75 -0
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import { execSync } from 'child_process';
|
|
2
|
+
import { readFileSync } from 'fs';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
import { execa } from 'execa';
|
|
5
|
+
import { applyEdit } from './fix.js';
|
|
6
|
+
// Exported so tests can verify the prompt's side-preference guidance stays in
|
|
7
|
+
// sync with the merge direction in runner.ts (origin/<base> is merged into HEAD,
|
|
8
|
+
// so HEAD is the PR side and the `>>>>>>>` side is the base branch).
|
|
9
|
+
export const PROMPT_TEMPLATE = `This pull request has merge conflicts. Resolve all conflict markers in the files listed below.
|
|
10
|
+
|
|
11
|
+
PR title: {PR_TITLE}
|
|
12
|
+
|
|
13
|
+
Conflicted files:
|
|
14
|
+
{CONFLICTED_FILES}
|
|
15
|
+
|
|
16
|
+
{EXTRA_INSTRUCTIONS}
|
|
17
|
+
|
|
18
|
+
Context: the PR's branch is checked out as HEAD, and the base branch was merged into it. That means the \`<<<<<<< HEAD\` side is the PR author's intended changes and the \`>>>>>>>\` side is the base branch. Default to preserving the PR author's intent.
|
|
19
|
+
|
|
20
|
+
Rules for resolving each conflict:
|
|
21
|
+
- Keep ALL meaningful changes from both sides if they are not directly contradictory
|
|
22
|
+
- When both sides modify the same line, prefer the PR author's changes (the \`<<<<<<< HEAD\` side) over the base branch (the \`>>>>>>>\` side), unless the PR side clearly breaks existing logic on the base
|
|
23
|
+
- Remove ALL conflict markers: <<<<<<<, =======, >>>>>>>
|
|
24
|
+
|
|
25
|
+
For each file, output ONLY the resolved conflict regions using this format:
|
|
26
|
+
|
|
27
|
+
<edit path="relative/path/to/file.ext">
|
|
28
|
+
<old>
|
|
29
|
+
exact conflict region including all markers (copy verbatim from the file)
|
|
30
|
+
</old>
|
|
31
|
+
<new>
|
|
32
|
+
resolved content with no conflict markers
|
|
33
|
+
</new>
|
|
34
|
+
</edit>
|
|
35
|
+
|
|
36
|
+
Rules for <edit> blocks:
|
|
37
|
+
- <old> must match the file content EXACTLY, including conflict markers and surrounding lines
|
|
38
|
+
- <new> must not contain ANY conflict markers
|
|
39
|
+
- Include 2–3 context lines around the conflict region to make the match unambiguous
|
|
40
|
+
- One block per conflict region; multiple blocks per file are fine
|
|
41
|
+
- Output ONLY <edit> blocks. No other text.`;
|
|
42
|
+
// Returns file paths that have unmerged conflict markers (git status: UU/AA/DD).
|
|
43
|
+
export function findConflictedFiles(tmpDir) {
|
|
44
|
+
try {
|
|
45
|
+
const out = execSync('git diff --name-only --diff-filter=U', { cwd: tmpDir, encoding: 'utf8' });
|
|
46
|
+
return out.trim().split('\n').filter(Boolean);
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
return [];
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
// Extract every conflict region in a file with a few context lines on each side.
|
|
53
|
+
// Slicing from the file prefix instead would hide conflicts that appear past the
|
|
54
|
+
// budget, so the resolver couldn't produce a matching <old> block.
|
|
55
|
+
const CONTEXT_LINES = 6;
|
|
56
|
+
const PER_FILE_MAX = 12_000;
|
|
57
|
+
export function extractConflictWindows(content) {
|
|
58
|
+
const lines = content.split('\n');
|
|
59
|
+
const starts = [];
|
|
60
|
+
for (let i = 0; i < lines.length; i++) {
|
|
61
|
+
if (lines[i].startsWith('<<<<<<<'))
|
|
62
|
+
starts.push(i);
|
|
63
|
+
}
|
|
64
|
+
if (starts.length === 0)
|
|
65
|
+
return '';
|
|
66
|
+
const ranges = [];
|
|
67
|
+
for (const start of starts) {
|
|
68
|
+
let end = start;
|
|
69
|
+
for (let i = start; i < lines.length; i++) {
|
|
70
|
+
if (lines[i].startsWith('>>>>>>>')) {
|
|
71
|
+
end = i;
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
end = i;
|
|
75
|
+
}
|
|
76
|
+
const from = Math.max(0, start - CONTEXT_LINES);
|
|
77
|
+
const to = Math.min(lines.length - 1, end + CONTEXT_LINES);
|
|
78
|
+
const prev = ranges[ranges.length - 1];
|
|
79
|
+
if (prev && from <= prev[1] + 1) {
|
|
80
|
+
prev[1] = Math.max(prev[1], to);
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
ranges.push([from, to]);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
const chunks = [];
|
|
87
|
+
let total = 0;
|
|
88
|
+
for (const [from, to] of ranges) {
|
|
89
|
+
const block = lines.slice(from, to + 1).join('\n');
|
|
90
|
+
const header = `... lines ${from + 1}-${to + 1} ...`;
|
|
91
|
+
const piece = `${header}\n${block}`;
|
|
92
|
+
if (total + piece.length > PER_FILE_MAX) {
|
|
93
|
+
chunks.push('... (remaining conflict regions truncated)');
|
|
94
|
+
break;
|
|
95
|
+
}
|
|
96
|
+
chunks.push(piece);
|
|
97
|
+
total += piece.length;
|
|
98
|
+
}
|
|
99
|
+
return chunks.join('\n\n');
|
|
100
|
+
}
|
|
101
|
+
function buildConflictedFilesBlock(tmpDir, filePaths) {
|
|
102
|
+
return filePaths.map(f => {
|
|
103
|
+
try {
|
|
104
|
+
const content = readFileSync(join(tmpDir, f), 'utf8');
|
|
105
|
+
const windowed = extractConflictWindows(content);
|
|
106
|
+
// No textual conflict markers (binary / modify-delete) — surface the file by name only.
|
|
107
|
+
if (!windowed) {
|
|
108
|
+
return `### ${f}\n(no textual conflict markers — likely a non-text conflict; skip)`;
|
|
109
|
+
}
|
|
110
|
+
return `### ${f}\n\`\`\`\n${windowed}\n\`\`\``;
|
|
111
|
+
}
|
|
112
|
+
catch {
|
|
113
|
+
return `### ${f}\n(could not read file)`;
|
|
114
|
+
}
|
|
115
|
+
}).join('\n\n');
|
|
116
|
+
}
|
|
117
|
+
export async function runConflictResolveStep(tmpDir, prTitle, instructions, model = 'default') {
|
|
118
|
+
const conflictedFiles = findConflictedFiles(tmpDir);
|
|
119
|
+
if (conflictedFiles.length === 0)
|
|
120
|
+
return { appliedCount: 0, resolvedPaths: [] };
|
|
121
|
+
const filesBlock = buildConflictedFilesBlock(tmpDir, conflictedFiles);
|
|
122
|
+
const prompt = PROMPT_TEMPLATE
|
|
123
|
+
.replace('{PR_TITLE}', prTitle)
|
|
124
|
+
.replace('{CONFLICTED_FILES}', filesBlock)
|
|
125
|
+
.replace('{EXTRA_INSTRUCTIONS}', instructions ? `Additional instructions: ${instructions}` : '');
|
|
126
|
+
let output = '';
|
|
127
|
+
let tokensUsed;
|
|
128
|
+
try {
|
|
129
|
+
const modelArgs = model !== 'default' ? ['--model', model] : [];
|
|
130
|
+
const { stdout } = await execa('claude', ['--print', '--output-format', 'json', ...modelArgs], {
|
|
131
|
+
input: prompt,
|
|
132
|
+
timeout: 180_000,
|
|
133
|
+
env: { ...process.env },
|
|
134
|
+
});
|
|
135
|
+
const raw = stdout.trim();
|
|
136
|
+
try {
|
|
137
|
+
const parsed = JSON.parse(raw);
|
|
138
|
+
output = typeof parsed.result === 'string' ? parsed.result : raw;
|
|
139
|
+
const inTok = parsed.usage?.input_tokens;
|
|
140
|
+
const outTok = parsed.usage?.output_tokens;
|
|
141
|
+
tokensUsed = typeof inTok === 'number' && typeof outTok === 'number' ? inTok + outTok : undefined;
|
|
142
|
+
}
|
|
143
|
+
catch {
|
|
144
|
+
output = raw;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
catch (err) {
|
|
148
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
149
|
+
if (/not logged in|auth|credential/i.test(msg)) {
|
|
150
|
+
throw new Error('claude auth failure during conflict-resolve step — run: claude auth login');
|
|
151
|
+
}
|
|
152
|
+
throw err;
|
|
153
|
+
}
|
|
154
|
+
if (!output || output === 'NO_CHANGES')
|
|
155
|
+
return { appliedCount: 0, resolvedPaths: [], tokensUsed };
|
|
156
|
+
const fileEdits = new Map();
|
|
157
|
+
const fileCache = new Map();
|
|
158
|
+
for (const { filePath, oldText, newText } of parseResolverEdits(output, conflictedFiles)) {
|
|
159
|
+
const absPath = join(tmpDir, filePath);
|
|
160
|
+
let current = fileEdits.get(filePath) ?? fileCache.get(filePath);
|
|
161
|
+
if (current === undefined) {
|
|
162
|
+
try {
|
|
163
|
+
current = readFileSync(absPath, 'utf8');
|
|
164
|
+
fileCache.set(filePath, current);
|
|
165
|
+
}
|
|
166
|
+
catch {
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
const updated = applyEdit(current, oldText, newText);
|
|
171
|
+
if (updated === null)
|
|
172
|
+
continue;
|
|
173
|
+
fileEdits.set(filePath, updated);
|
|
174
|
+
}
|
|
175
|
+
const { writeFileSync, mkdirSync } = await import('fs');
|
|
176
|
+
const { dirname } = await import('path');
|
|
177
|
+
let appliedCount = 0;
|
|
178
|
+
const resolvedPaths = [];
|
|
179
|
+
for (const [filePath, content] of fileEdits) {
|
|
180
|
+
const absPath = join(tmpDir, filePath);
|
|
181
|
+
try {
|
|
182
|
+
mkdirSync(dirname(absPath), { recursive: true });
|
|
183
|
+
writeFileSync(absPath, content);
|
|
184
|
+
appliedCount++;
|
|
185
|
+
resolvedPaths.push(filePath);
|
|
186
|
+
}
|
|
187
|
+
catch { /* skip unwritable paths */ }
|
|
188
|
+
}
|
|
189
|
+
return { appliedCount, resolvedPaths, tokensUsed };
|
|
190
|
+
}
|
|
191
|
+
// Parses <edit path="…"><old>…</old><new>…</new></edit> blocks from resolver output.
|
|
192
|
+
// Filters out anything that escapes tmpDir (`..`, absolute paths) or targets a file
|
|
193
|
+
// that wasn't in the original unmerged set — the resolver must only touch the files
|
|
194
|
+
// it was asked about, otherwise a buggy or prompt-injected response could land
|
|
195
|
+
// arbitrary content (including unresolved markers) in unrelated tracked files.
|
|
196
|
+
export function parseResolverEdits(output, conflictedFiles) {
|
|
197
|
+
const conflictedSet = new Set(conflictedFiles);
|
|
198
|
+
const edits = [];
|
|
199
|
+
const editRegex = /<edit path="([^"]+)">([\s\S]*?)<\/edit>/g;
|
|
200
|
+
let match;
|
|
201
|
+
while ((match = editRegex.exec(output)) !== null) {
|
|
202
|
+
const [, filePath, body] = match;
|
|
203
|
+
if (filePath.includes('..') || filePath.startsWith('/'))
|
|
204
|
+
continue;
|
|
205
|
+
if (!conflictedSet.has(filePath))
|
|
206
|
+
continue;
|
|
207
|
+
const oldMatch = body.match(/<old>([\s\S]*?)<\/old>/);
|
|
208
|
+
const newMatch = body.match(/<new>([\s\S]*?)<\/new>/);
|
|
209
|
+
if (!oldMatch || !newMatch)
|
|
210
|
+
continue;
|
|
211
|
+
const oldText = oldMatch[1].replace(/^\n/, '').replace(/\n$/, '');
|
|
212
|
+
const newText = newMatch[1].replace(/^\n/, '').replace(/\n$/, '');
|
|
213
|
+
if (oldText === '')
|
|
214
|
+
continue;
|
|
215
|
+
edits.push({ filePath, oldText, newText });
|
|
216
|
+
}
|
|
217
|
+
return edits;
|
|
218
|
+
}
|
|
219
|
+
//# sourceMappingURL=conflict-resolve.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conflict-resolve.js","sourceRoot":"","sources":["../../src/reviewers/conflict-resolve.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Config } from '../config/schema.js';
|
|
2
|
+
export declare function applyEdit(fileContent: string, oldText: string, newText: string): string | null;
|
|
3
|
+
export declare function runFixStep(tmpDir: string, baseRef: string, prTitle: string, reviewComment: string, instructions: string, config: Config, model?: string): Promise<{
|
|
4
|
+
appliedCount: number;
|
|
5
|
+
tokensUsed?: number;
|
|
6
|
+
}>;
|
|
7
|
+
//# sourceMappingURL=fix.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fix.d.ts","sourceRoot":"","sources":["../../src/reviewers/fix.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AA4DjD,wBAAgB,SAAS,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAO9F;AAED,wBAAsB,UAAU,CAC9B,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,aAAa,EAAE,MAAM,EACrB,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,MAAM,EACd,KAAK,SAAY,GAChB,OAAO,CAAC;IAAE,YAAY,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAkIxD"}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { execSync } from 'child_process';
|
|
2
|
+
import { mkdirSync, readFileSync, writeFileSync } from 'fs';
|
|
3
|
+
import { dirname, join } from 'path';
|
|
4
|
+
import { execa } from 'execa';
|
|
5
|
+
// Minimum ratio of new lines to original lines before we reject a full-file write.
|
|
6
|
+
// Guards against Claude silently truncating large files.
|
|
7
|
+
const MIN_SIZE_RATIO = 0.6;
|
|
8
|
+
const PROMPT_TEMPLATE = `You opened a pull request that received the following code review.
|
|
9
|
+
|
|
10
|
+
PR title: {PR_TITLE}
|
|
11
|
+
|
|
12
|
+
Code review comment:
|
|
13
|
+
---
|
|
14
|
+
{REVIEW_COMMENT}
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
Diff of your changes (base..head):
|
|
18
|
+
---
|
|
19
|
+
{DIFF}
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
{EXTRA_INSTRUCTIONS}
|
|
23
|
+
|
|
24
|
+
Please address the issues raised in the review. Rules:
|
|
25
|
+
- Only fix what the review explicitly calls out
|
|
26
|
+
- Do not refactor unrelated code, rename variables, or add tests unless asked
|
|
27
|
+
- If a comment requires deeper understanding of business logic, skip it
|
|
28
|
+
- If the review has no actionable code changes, output exactly: NO_CHANGES
|
|
29
|
+
|
|
30
|
+
For each file you need to change, output ONLY the edited sections using this format:
|
|
31
|
+
|
|
32
|
+
<edit path="relative/path/to/file.ext">
|
|
33
|
+
<old>
|
|
34
|
+
exact lines from the file that need to be replaced (copy verbatim — must match exactly)
|
|
35
|
+
</old>
|
|
36
|
+
<new>
|
|
37
|
+
replacement lines
|
|
38
|
+
</new>
|
|
39
|
+
</edit>
|
|
40
|
+
|
|
41
|
+
Rules for <edit> blocks:
|
|
42
|
+
- <old> must match the file content EXACTLY (whitespace, indentation, line endings)
|
|
43
|
+
- Include enough surrounding context lines (2–3) so the match is unambiguous
|
|
44
|
+
- One <edit> block per contiguous change; multiple blocks per file are fine
|
|
45
|
+
- Never output the entire file — only the sections that change
|
|
46
|
+
- If a file needs a new section appended, use an <old> that matches the last few lines before the insertion point
|
|
47
|
+
- To create a brand-new file, leave <old> empty and put the complete file content in <new>
|
|
48
|
+
|
|
49
|
+
Output ONLY <edit> blocks or NO_CHANGES. No other text.`;
|
|
50
|
+
function isSafePath(filePath) {
|
|
51
|
+
return !filePath.includes('..') && !filePath.startsWith('/');
|
|
52
|
+
}
|
|
53
|
+
// Apply a single edit: find <old> in fileContent and replace with <new>.
|
|
54
|
+
// Returns null if the old text is not found or appears more than once (ambiguous).
|
|
55
|
+
export function applyEdit(fileContent, oldText, newText) {
|
|
56
|
+
const idx = fileContent.indexOf(oldText);
|
|
57
|
+
if (idx === -1)
|
|
58
|
+
return null;
|
|
59
|
+
// Reject ambiguous matches — if the snippet appears more than once, indexOf and
|
|
60
|
+
// lastIndexOf disagree, so we can't know which occurrence Claude intended to edit.
|
|
61
|
+
if (fileContent.lastIndexOf(oldText) !== idx)
|
|
62
|
+
return null;
|
|
63
|
+
return fileContent.slice(0, idx) + newText + fileContent.slice(idx + oldText.length);
|
|
64
|
+
}
|
|
65
|
+
export async function runFixStep(tmpDir, baseRef, prTitle, reviewComment, instructions, config, model = 'default') {
|
|
66
|
+
let diff = '';
|
|
67
|
+
try {
|
|
68
|
+
diff = execSync(`git diff origin/${baseRef}...HEAD`, { cwd: tmpDir, encoding: 'utf8' });
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
try {
|
|
72
|
+
diff = execSync('git diff HEAD~1', { cwd: tmpDir, encoding: 'utf8' });
|
|
73
|
+
}
|
|
74
|
+
catch { /* proceed with empty diff */ }
|
|
75
|
+
}
|
|
76
|
+
const prompt = PROMPT_TEMPLATE
|
|
77
|
+
.replace('{PR_TITLE}', prTitle)
|
|
78
|
+
.replace('{REVIEW_COMMENT}', reviewComment.slice(0, 8000))
|
|
79
|
+
.replace('{DIFF}', diff.slice(0, 16000))
|
|
80
|
+
.replace('{EXTRA_INSTRUCTIONS}', instructions ? `Additional instructions: ${instructions}` : '');
|
|
81
|
+
let output = '';
|
|
82
|
+
let tokensUsed;
|
|
83
|
+
try {
|
|
84
|
+
const modelArgs = model !== 'default' ? ['--model', model] : [];
|
|
85
|
+
const { stdout } = await execa('claude', ['--print', '--output-format', 'json', ...modelArgs], {
|
|
86
|
+
input: prompt,
|
|
87
|
+
timeout: 180_000,
|
|
88
|
+
env: { ...process.env },
|
|
89
|
+
});
|
|
90
|
+
const raw = stdout.trim();
|
|
91
|
+
try {
|
|
92
|
+
const parsed = JSON.parse(raw);
|
|
93
|
+
output = typeof parsed.result === 'string' ? parsed.result : raw;
|
|
94
|
+
const inTok = parsed.usage?.input_tokens;
|
|
95
|
+
const outTok = parsed.usage?.output_tokens;
|
|
96
|
+
tokensUsed = typeof inTok === 'number' && typeof outTok === 'number' ? inTok + outTok : undefined;
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
output = raw;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
catch (err) {
|
|
103
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
104
|
+
if (/not logged in|auth|credential/i.test(msg)) {
|
|
105
|
+
throw new Error('claude auth failure during fix step — run: claude auth login');
|
|
106
|
+
}
|
|
107
|
+
throw err;
|
|
108
|
+
}
|
|
109
|
+
if (!output || output === 'NO_CHANGES')
|
|
110
|
+
return { appliedCount: 0, tokensUsed };
|
|
111
|
+
let appliedCount = 0;
|
|
112
|
+
// Primary: apply <edit path="..."><old>...</old><new>...</new></edit> blocks.
|
|
113
|
+
// This format only outputs changed sections — structurally prevents truncation.
|
|
114
|
+
const editRegex = /<edit path="([^"]+)">([\s\S]*?)<\/edit>/g;
|
|
115
|
+
const fileEdits = new Map(); // files with ≥1 successful edit
|
|
116
|
+
const fileCache = new Map(); // raw disk reads; never written directly
|
|
117
|
+
let match;
|
|
118
|
+
while ((match = editRegex.exec(output)) !== null) {
|
|
119
|
+
const [, filePath, body] = match;
|
|
120
|
+
if (!isSafePath(filePath))
|
|
121
|
+
continue;
|
|
122
|
+
const oldMatch = body.match(/<old>([\s\S]*?)<\/old>/);
|
|
123
|
+
const newMatch = body.match(/<new>([\s\S]*?)<\/new>/);
|
|
124
|
+
if (!oldMatch || !newMatch)
|
|
125
|
+
continue;
|
|
126
|
+
// Strip exactly one leading/trailing newline added by the XML-style tags
|
|
127
|
+
const oldText = oldMatch[1].replace(/^\n/, '').replace(/\n$/, '');
|
|
128
|
+
const newText = newMatch[1].replace(/^\n/, '').replace(/\n$/, '');
|
|
129
|
+
const absPath = join(tmpDir, filePath);
|
|
130
|
+
// fileCache holds disk reads; fileEdits holds files that have at least one
|
|
131
|
+
// successful edit applied. Keeping them separate prevents a failed <old> match
|
|
132
|
+
// from adding the unchanged file to fileEdits and inflating appliedCount.
|
|
133
|
+
let current = fileEdits.get(filePath) ?? fileCache.get(filePath);
|
|
134
|
+
const alreadyKnown = current !== undefined;
|
|
135
|
+
if (!alreadyKnown) {
|
|
136
|
+
try {
|
|
137
|
+
current = readFileSync(absPath, 'utf8');
|
|
138
|
+
fileCache.set(filePath, current);
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
// File doesn't exist on disk — allow new-file creation only when <old> is empty.
|
|
142
|
+
// Any non-empty <old> is meaningless against a non-existent file.
|
|
143
|
+
if (oldText !== '')
|
|
144
|
+
continue;
|
|
145
|
+
fileEdits.set(filePath, newText);
|
|
146
|
+
continue;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
// Guard: empty <old> on an existing file is ambiguous — indexOf('') = 0 would
|
|
150
|
+
// silently prepend <new> at the top of the file instead of anchoring to content.
|
|
151
|
+
if (oldText === '')
|
|
152
|
+
continue;
|
|
153
|
+
const updated = applyEdit(current, oldText, newText);
|
|
154
|
+
if (updated === null)
|
|
155
|
+
continue; // <old> not found — skip this edit safely
|
|
156
|
+
fileEdits.set(filePath, updated);
|
|
157
|
+
}
|
|
158
|
+
for (const [filePath, content] of fileEdits) {
|
|
159
|
+
const absPath = join(tmpDir, filePath);
|
|
160
|
+
try {
|
|
161
|
+
mkdirSync(dirname(absPath), { recursive: true });
|
|
162
|
+
writeFileSync(absPath, content);
|
|
163
|
+
appliedCount++;
|
|
164
|
+
}
|
|
165
|
+
catch { /* skip unwritable paths */ }
|
|
166
|
+
}
|
|
167
|
+
// Fallback: <file path="...">complete content</file> blocks, with size guard.
|
|
168
|
+
// These are only accepted when the new content is >= MIN_SIZE_RATIO of the original,
|
|
169
|
+
// preventing silent truncation of large files.
|
|
170
|
+
if (appliedCount === 0) {
|
|
171
|
+
const fileRegex = /<file path="([^"]+)">([\s\S]*?)<\/file>/g;
|
|
172
|
+
while ((match = fileRegex.exec(output)) !== null) {
|
|
173
|
+
const [, filePath, rawContent] = match;
|
|
174
|
+
if (!isSafePath(filePath))
|
|
175
|
+
continue;
|
|
176
|
+
const absPath = join(tmpDir, filePath);
|
|
177
|
+
const newContent = rawContent.replace(/^\n/, '');
|
|
178
|
+
try {
|
|
179
|
+
let originalLineCount = 0;
|
|
180
|
+
try {
|
|
181
|
+
originalLineCount = readFileSync(absPath, 'utf8').split('\n').length;
|
|
182
|
+
}
|
|
183
|
+
catch { /* new file — no size guard needed */ }
|
|
184
|
+
if (originalLineCount > 0) {
|
|
185
|
+
const newLineCount = newContent.split('\n').length;
|
|
186
|
+
if (newLineCount < originalLineCount * MIN_SIZE_RATIO)
|
|
187
|
+
continue; // reject — likely truncated
|
|
188
|
+
}
|
|
189
|
+
writeFileSync(absPath, newContent);
|
|
190
|
+
appliedCount++;
|
|
191
|
+
}
|
|
192
|
+
catch { /* skip unwritable paths */ }
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
return { appliedCount, tokensUsed };
|
|
196
|
+
}
|
|
197
|
+
//# sourceMappingURL=fix.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fix.js","sourceRoot":"","sources":["../../src/reviewers/fix.ts"],"names":[],"mappings":"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"}
|