@tienne/gestalt 0.85.0 → 0.87.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/dist/package.json +4 -3
- package/dist/plugin/review-agents/harness-reviewer/AGENT.md +21 -1
- package/dist/plugin/role-agents/_shared/references/ai-tell-quick-rules.md +2 -2
- package/dist/plugin/skills/review/SKILL.md +9 -2
- package/dist/src/cli/commands/harness-refs.d.ts +10 -0
- package/dist/src/cli/commands/harness-refs.d.ts.map +1 -1
- package/dist/src/cli/commands/harness-refs.js +40 -0
- package/dist/src/cli/commands/harness-refs.js.map +1 -1
- package/dist/src/cli/index.d.ts.map +1 -1
- package/dist/src/cli/index.js +10 -1
- package/dist/src/cli/index.js.map +1 -1
- package/dist/src/harness-review/backward-search.d.ts +15 -2
- package/dist/src/harness-review/backward-search.d.ts.map +1 -1
- package/dist/src/harness-review/backward-search.js +101 -43
- package/dist/src/harness-review/backward-search.js.map +1 -1
- package/dist/src/harness-review/collect.d.ts +11 -2
- package/dist/src/harness-review/collect.d.ts.map +1 -1
- package/dist/src/harness-review/collect.js +72 -7
- package/dist/src/harness-review/collect.js.map +1 -1
- package/dist/src/harness-review/github-code-search.d.ts +32 -1
- package/dist/src/harness-review/github-code-search.d.ts.map +1 -1
- package/dist/src/harness-review/github-code-search.js +86 -2
- package/dist/src/harness-review/github-code-search.js.map +1 -1
- package/dist/src/harness-review/hybrid-search.d.ts +35 -0
- package/dist/src/harness-review/hybrid-search.d.ts.map +1 -0
- package/dist/src/harness-review/hybrid-search.js +63 -0
- package/dist/src/harness-review/hybrid-search.js.map +1 -0
- package/dist/src/harness-review/related-clones.d.ts +66 -0
- package/dist/src/harness-review/related-clones.d.ts.map +1 -0
- package/dist/src/harness-review/related-clones.js +309 -0
- package/dist/src/harness-review/related-clones.js.map +1 -0
- package/dist/src/harness-review/rule-overlap.d.ts +3 -0
- package/dist/src/harness-review/rule-overlap.d.ts.map +1 -0
- package/dist/src/harness-review/rule-overlap.js +78 -0
- package/dist/src/harness-review/rule-overlap.js.map +1 -0
- package/dist/src/harness-review/search-backend.d.ts +23 -1
- package/dist/src/harness-review/search-backend.d.ts.map +1 -1
- package/dist/src/harness-review/search-backend.js +13 -1
- package/dist/src/harness-review/search-backend.js.map +1 -1
- package/dist/src/harness-review/types.d.ts +1 -1
- package/dist/src/harness-review/types.d.ts.map +1 -1
- package/dist/src/harness-review/types.js +1 -0
- package/dist/src/harness-review/types.js.map +1 -1
- package/dist/src/humanize/detectors.js +1 -1
- package/dist/src/humanize/detectors.js.map +1 -1
- package/dist/src/humanize/overlap.d.ts +116 -0
- package/dist/src/humanize/overlap.d.ts.map +1 -0
- package/dist/src/humanize/overlap.js +680 -0
- package/dist/src/humanize/overlap.js.map +1 -0
- package/package.json +4 -3
- package/plugin/.codex-plugin/plugin.json +1 -1
- package/plugin/.mcp.json +1 -1
- package/plugin/mcp.json +1 -1
- package/plugin/review-agents/harness-reviewer/AGENT.md +21 -1
- package/plugin/role-agents/_shared/references/ai-tell-quick-rules.md +2 -2
- package/plugin/skills/review/SKILL.md +9 -2
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { type GhRunner } from '../review-loop/fetch.js';
|
|
2
|
+
import type { LocalRepoSource } from './search-backend.js';
|
|
3
|
+
export interface CloneTarget {
|
|
4
|
+
/** owner/name */
|
|
5
|
+
repo: string;
|
|
6
|
+
/** 관련 레포 탐지가 알아낸 기본 브랜치. 없으면 클론의 origin/HEAD를 본다 */
|
|
7
|
+
defaultBranch?: string;
|
|
8
|
+
/** `--repo-dir`로 받은 클론. 있으면 관리 클론을 만들지 않는다 */
|
|
9
|
+
userDir?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface CloneGitRunner {
|
|
12
|
+
(dir: string, args: readonly string[]): string;
|
|
13
|
+
}
|
|
14
|
+
export interface PrepareClonesOptions {
|
|
15
|
+
targets: CloneTarget[];
|
|
16
|
+
/** 관리 클론을 두는 자리. 부르는 쪽이 `worktreeCloneRoot`로 워크트리마다 나눠 넘긴다 */
|
|
17
|
+
cloneRoot?: string;
|
|
18
|
+
gh?: GhRunner;
|
|
19
|
+
git?: CloneGitRunner;
|
|
20
|
+
now?: Date;
|
|
21
|
+
/** fetch가 잠금에 걸렸을 때 다시 시도하기 전 기다리는 함수. 테스트가 실제로 자지 않게 주입한다 */
|
|
22
|
+
wait?: (ms: number) => void;
|
|
23
|
+
}
|
|
24
|
+
export interface CloneFailure {
|
|
25
|
+
repo: string;
|
|
26
|
+
reason: string;
|
|
27
|
+
}
|
|
28
|
+
export interface PreparedClones {
|
|
29
|
+
sources: LocalRepoSource[];
|
|
30
|
+
/** 클론을 못 얻은 레포. 부르는 쪽이 GitHub 검색으로 넘긴다 */
|
|
31
|
+
failed: CloneFailure[];
|
|
32
|
+
limitations: string[];
|
|
33
|
+
}
|
|
34
|
+
export declare function defaultCloneRoot(): string;
|
|
35
|
+
/**
|
|
36
|
+
* 워크트리 하나가 쓸 클론 루트를 돌려준다. 이름은 사람이 알아보게 디렉토리 이름을 앞에 두고
|
|
37
|
+
* 같은 이름의 워크트리끼리 겹치지 않게 경로 해시를 붙인다.
|
|
38
|
+
*/
|
|
39
|
+
export declare function worktreeCloneRoot(base: string, worktree: string): string;
|
|
40
|
+
/** 이 기간 넘게 어느 수집도 안 쓴 클론 루트는 워크트리가 살아 있어도 치운다 */
|
|
41
|
+
export declare const DEFAULT_CLONE_MAX_IDLE_MS: number;
|
|
42
|
+
export type PruneReason = 'worktreeGone' | 'idle' | 'all';
|
|
43
|
+
export interface PrunedClone {
|
|
44
|
+
root: string;
|
|
45
|
+
/** 표시 파일에 적힌 워크트리 경로. 표시가 없으면 null */
|
|
46
|
+
worktree: string | null;
|
|
47
|
+
reason: PruneReason;
|
|
48
|
+
}
|
|
49
|
+
export interface PruneClonesOptions {
|
|
50
|
+
now?: Date;
|
|
51
|
+
maxIdleMs?: number;
|
|
52
|
+
/** 표시 없는 디렉토리까지 전부 지운다. 사람이 명령으로 부를 때만 쓴다 */
|
|
53
|
+
all?: boolean;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* 원래 워크트리가 지워졌거나 오래 안 쓴 클론 루트를 치운다. 쓴 시각은 수집마다
|
|
57
|
+
* `worktreeCloneRoot`가 표시 파일을 다시 쓰며 갱신한다. 표시 파일이 없는 디렉토리는 누가 만든
|
|
58
|
+
* 건지 몰라 `all`이 아니면 건드리지 않는다. 예외를 던지지 않는다.
|
|
59
|
+
*/
|
|
60
|
+
export declare function pruneWorktreeClones(base: string, opts?: PruneClonesOptions): PrunedClone[];
|
|
61
|
+
/**
|
|
62
|
+
* 대상마다 클론을 확보하고 origin 기본 브랜치를 받아 온다. 예외를 던지지 않는다 — 실패는 failed와
|
|
63
|
+
* limitations로 돌려준다.
|
|
64
|
+
*/
|
|
65
|
+
export declare function prepareRelatedClones(opts: PrepareClonesOptions): PreparedClones;
|
|
66
|
+
//# sourceMappingURL=related-clones.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"related-clones.d.ts","sourceRoot":"","sources":["../../../src/harness-review/related-clones.ts"],"names":[],"mappings":"AA4BA,OAAO,EAAS,KAAK,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAE3D,MAAM,WAAW,WAAW;IAC1B,iBAAiB;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,oDAAoD;IACpD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,8CAA8C;IAC9C,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAAC;CAChD;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,8DAA8D;IAC9D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,EAAE,CAAC,EAAE,QAAQ,CAAC;IACd,GAAG,CAAC,EAAE,cAAc,CAAC;IACrB,GAAG,CAAC,EAAE,IAAI,CAAC;IACX,8DAA8D;IAC9D,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7B;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,0CAA0C;IAC1C,MAAM,EAAE,YAAY,EAAE,CAAC;IACvB,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAYD,wBAAgB,gBAAgB,IAAI,MAAM,CAEzC;AAaD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAYxE;AAED,iDAAiD;AACjD,eAAO,MAAM,yBAAyB,QAAa,CAAC;AAEpD,MAAM,MAAM,WAAW,GAAG,cAAc,GAAG,MAAM,GAAG,KAAK,CAAC;AAE1D,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,sCAAsC;IACtC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,WAAW,CAAC;CACrB;AAED,MAAM,WAAW,kBAAkB;IACjC,GAAG,CAAC,EAAE,IAAI,CAAC;IACX,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6CAA6C;IAC7C,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAYD;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,kBAAuB,GAAG,WAAW,EAAE,CA2B9F;AAwHD;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,oBAAoB,GAAG,cAAc,CAgG/E"}
|
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 역방향 검색에 쓸 관련 레포 클론을 준비한다.
|
|
3
|
+
*
|
|
4
|
+
* GitHub 코드 검색은 분당 10회라 식별자가 수십 개인 PR은 한 번에 못 끝낸다. 관련 레포를 로컬에
|
|
5
|
+
* 받아 두면 같은 질의를 git grep으로 한도 없이 돌린다. 사람이 `--repo-dir`로 준 클론을 먼저 쓰고
|
|
6
|
+
* 없으면 `~/.gestalt/repos/<워크트리 키>/<owner>/<name>`에 기본 브랜치만 얕게 받는다.
|
|
7
|
+
*
|
|
8
|
+
* 클론은 워크트리마다 따로 둔다. 여러 워크트리에서 리뷰를 동시에 돌리면 한 클론을 두고 fetch가
|
|
9
|
+
* 부딪히고 한쪽이 검색하는 사이 다른 쪽이 ref를 옮긴다.
|
|
10
|
+
*
|
|
11
|
+
* 어느 쪽이든 워킹트리가 아니라 origin 기본 브랜치 ref를 읽는다. GitHub 검색이 기본 브랜치만 보므로
|
|
12
|
+
* 기준을 맞추고 체크아웃된 작업 브랜치나 커밋 안 한 변경이 결과에 섞이지 않게 한다.
|
|
13
|
+
*/
|
|
14
|
+
import { execFileSync } from 'node:child_process';
|
|
15
|
+
import { createHash, randomUUID } from 'node:crypto';
|
|
16
|
+
import { existsSync, mkdirSync, readFileSync, readdirSync, realpathSync, renameSync, rmSync, statSync, writeFileSync, } from 'node:fs';
|
|
17
|
+
import { basename, dirname, join, resolve, sep } from 'node:path';
|
|
18
|
+
import { gestaltPath } from '../core/home.js';
|
|
19
|
+
import { runGh } from '../review-loop/fetch.js';
|
|
20
|
+
const DAY_MS = 24 * 60 * 60 * 1000;
|
|
21
|
+
const TMP_PREFIX = '.clone-tmp-';
|
|
22
|
+
// 받다가 죽은 프로세스가 남긴 임시 클론만 치운다. 다른 수집이 지금 받고 있는 자리는 건드리면 안 된다
|
|
23
|
+
const STALE_TMP_MS = 60 * 60 * 1000;
|
|
24
|
+
// 다른 워크트리의 수집이 같은 클론을 fetch하는 중이면 git이 잠금 파일로 막는다. 끝나길 잠깐 기다린다
|
|
25
|
+
const LOCK_RETRY_DELAYS_MS = [1_000, 2_000, 4_000];
|
|
26
|
+
const LOCK_ERROR_RE = /\.lock'?:? File exists|Unable to create '[^']*\.lock'/;
|
|
27
|
+
// 경로 조각으로 쓰므로 `..` 같은 값이 들어오면 cloneRoot 밖을 가리킨다
|
|
28
|
+
const SLUG_PART_RE = /^(?!\.{1,2}$)[A-Za-z0-9_.-]+$/;
|
|
29
|
+
export function defaultCloneRoot() {
|
|
30
|
+
return gestaltPath('repos');
|
|
31
|
+
}
|
|
32
|
+
// 워크트리 루트에 이 파일로 원래 경로를 적어 둔다. 그 경로가 사라졌으면 클론을 치워도 된다
|
|
33
|
+
const WORKTREE_MARKER = '.worktree';
|
|
34
|
+
function canonicalPath(path) {
|
|
35
|
+
try {
|
|
36
|
+
return realpathSync(path);
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return resolve(path);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* 워크트리 하나가 쓸 클론 루트를 돌려준다. 이름은 사람이 알아보게 디렉토리 이름을 앞에 두고
|
|
44
|
+
* 같은 이름의 워크트리끼리 겹치지 않게 경로 해시를 붙인다.
|
|
45
|
+
*/
|
|
46
|
+
export function worktreeCloneRoot(base, worktree) {
|
|
47
|
+
const path = canonicalPath(worktree);
|
|
48
|
+
const name = basename(path).replace(/[^A-Za-z0-9_.-]/g, '_') || 'root';
|
|
49
|
+
const hash = createHash('sha256').update(path).digest('hex').slice(0, 8);
|
|
50
|
+
const root = join(resolve(base), `${name}-${hash}`);
|
|
51
|
+
try {
|
|
52
|
+
mkdirSync(root, { recursive: true });
|
|
53
|
+
writeFileSync(join(root, WORKTREE_MARKER), `${path}\n`);
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
// 표시를 못 남겨도 클론은 받는다. 못 남긴 루트는 정리 대상에서 빠질 뿐이다
|
|
57
|
+
}
|
|
58
|
+
return root;
|
|
59
|
+
}
|
|
60
|
+
/** 이 기간 넘게 어느 수집도 안 쓴 클론 루트는 워크트리가 살아 있어도 치운다 */
|
|
61
|
+
export const DEFAULT_CLONE_MAX_IDLE_MS = 7 * DAY_MS;
|
|
62
|
+
function readMarker(root) {
|
|
63
|
+
try {
|
|
64
|
+
const marker = join(root, WORKTREE_MARKER);
|
|
65
|
+
const worktree = readFileSync(marker, 'utf-8').trim();
|
|
66
|
+
return worktree === '' ? null : { worktree, usedAt: statSync(marker).mtimeMs };
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* 원래 워크트리가 지워졌거나 오래 안 쓴 클론 루트를 치운다. 쓴 시각은 수집마다
|
|
74
|
+
* `worktreeCloneRoot`가 표시 파일을 다시 쓰며 갱신한다. 표시 파일이 없는 디렉토리는 누가 만든
|
|
75
|
+
* 건지 몰라 `all`이 아니면 건드리지 않는다. 예외를 던지지 않는다.
|
|
76
|
+
*/
|
|
77
|
+
export function pruneWorktreeClones(base, opts = {}) {
|
|
78
|
+
const now = (opts.now ?? new Date()).getTime();
|
|
79
|
+
const maxIdleMs = opts.maxIdleMs ?? DEFAULT_CLONE_MAX_IDLE_MS;
|
|
80
|
+
const pruned = [];
|
|
81
|
+
let entries;
|
|
82
|
+
try {
|
|
83
|
+
entries = readdirSync(base);
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
return pruned;
|
|
87
|
+
}
|
|
88
|
+
for (const entry of entries) {
|
|
89
|
+
const root = join(base, entry);
|
|
90
|
+
const marker = readMarker(root);
|
|
91
|
+
let reason = null;
|
|
92
|
+
if (opts.all)
|
|
93
|
+
reason = 'all';
|
|
94
|
+
else if (marker === null)
|
|
95
|
+
continue;
|
|
96
|
+
else if (!existsSync(marker.worktree))
|
|
97
|
+
reason = 'worktreeGone';
|
|
98
|
+
else if (now - marker.usedAt > maxIdleMs)
|
|
99
|
+
reason = 'idle';
|
|
100
|
+
if (reason === null)
|
|
101
|
+
continue;
|
|
102
|
+
try {
|
|
103
|
+
rmSync(root, { recursive: true, force: true });
|
|
104
|
+
pruned.push({ root, worktree: marker?.worktree ?? null, reason });
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
// 다른 수집이 먼저 치웠다
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return pruned;
|
|
111
|
+
}
|
|
112
|
+
function sleepSync(ms) {
|
|
113
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
|
|
114
|
+
}
|
|
115
|
+
const defaultGit = (dir, args) => execFileSync('git', ['-C', dir, ...args], {
|
|
116
|
+
encoding: 'utf-8',
|
|
117
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
118
|
+
// 인증이 필요한 원격이면 프롬프트를 띄우지 말고 실패하게 한다. 수집이 입력을 기다리며 멈춘다
|
|
119
|
+
env: { ...process.env, GIT_TERMINAL_PROMPT: '0' },
|
|
120
|
+
timeout: 120_000,
|
|
121
|
+
});
|
|
122
|
+
function errText(e) {
|
|
123
|
+
if (typeof e === 'object' && e !== null) {
|
|
124
|
+
const stderr = e.stderr;
|
|
125
|
+
if (stderr !== undefined && stderr !== null && String(stderr).trim() !== '') {
|
|
126
|
+
return String(stderr).trim();
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return e instanceof Error ? e.message : String(e);
|
|
130
|
+
}
|
|
131
|
+
// git은 원인을 fatal 줄에 쓰고 그 뒤에 안내 문단을 붙인다. 마지막 줄만 보면 원인이 빠진다
|
|
132
|
+
function errMessage(e) {
|
|
133
|
+
const lines = errText(e).split('\n');
|
|
134
|
+
return lines.find((l) => /^(fatal|error):/.test(l)) ?? lines.at(-1);
|
|
135
|
+
}
|
|
136
|
+
function originHeadBranch(git, dir) {
|
|
137
|
+
try {
|
|
138
|
+
const out = git(dir, ['symbolic-ref', '--short', 'refs/remotes/origin/HEAD']).trim();
|
|
139
|
+
return out.startsWith('origin/') ? out.slice('origin/'.length) : null;
|
|
140
|
+
}
|
|
141
|
+
catch {
|
|
142
|
+
return null;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
function resolveCommit(git, dir, ref) {
|
|
146
|
+
try {
|
|
147
|
+
const sha = git(dir, ['rev-parse', '--verify', '--quiet', `${ref}^{commit}`]).trim();
|
|
148
|
+
return sha === '' ? null : sha;
|
|
149
|
+
}
|
|
150
|
+
catch {
|
|
151
|
+
return null;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
function sweepStaleTmp(parent, now) {
|
|
155
|
+
let entries;
|
|
156
|
+
try {
|
|
157
|
+
entries = readdirSync(parent);
|
|
158
|
+
}
|
|
159
|
+
catch {
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
for (const entry of entries) {
|
|
163
|
+
if (!entry.startsWith(TMP_PREFIX))
|
|
164
|
+
continue;
|
|
165
|
+
const path = join(parent, entry);
|
|
166
|
+
try {
|
|
167
|
+
if (now.getTime() - statSync(path).mtimeMs > STALE_TMP_MS)
|
|
168
|
+
rmSync(path, { recursive: true, force: true });
|
|
169
|
+
}
|
|
170
|
+
catch {
|
|
171
|
+
// 다른 수집이 먼저 치웠다
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* 임시 자리에 받은 뒤 rename으로 옮긴다. 같은 자리에 바로 받으면 동시에 도는 다른 수집이 받다 만
|
|
177
|
+
* 디렉토리를 끊긴 클론으로 보고 지울 수 있다. rename이 이미 있다고 실패하면 다른 수집이 먼저 받은
|
|
178
|
+
* 것이라 그 클론을 쓴다.
|
|
179
|
+
*/
|
|
180
|
+
function cloneInto(gh, repo, dir, now) {
|
|
181
|
+
const parent = dirname(dir);
|
|
182
|
+
mkdirSync(parent, { recursive: true });
|
|
183
|
+
sweepStaleTmp(parent, now);
|
|
184
|
+
const tmp = join(parent, `${TMP_PREFIX}${repo.split('/')[1]}-${randomUUID()}`);
|
|
185
|
+
try {
|
|
186
|
+
gh(['repo', 'clone', repo, tmp, '--', '--depth', '1', '--single-branch']);
|
|
187
|
+
try {
|
|
188
|
+
renameSync(tmp, dir);
|
|
189
|
+
}
|
|
190
|
+
catch (e) {
|
|
191
|
+
if (!existsSync(join(dir, '.git')))
|
|
192
|
+
throw e;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
finally {
|
|
196
|
+
rmSync(tmp, { recursive: true, force: true });
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
function fetchWithRetry(git, dir, args, wait) {
|
|
200
|
+
for (let attempt = 0;; attempt++) {
|
|
201
|
+
try {
|
|
202
|
+
git(dir, args);
|
|
203
|
+
return { error: null, locked: false };
|
|
204
|
+
}
|
|
205
|
+
catch (e) {
|
|
206
|
+
const error = errMessage(e);
|
|
207
|
+
const locked = LOCK_ERROR_RE.test(errText(e));
|
|
208
|
+
const delay = LOCK_RETRY_DELAYS_MS[attempt];
|
|
209
|
+
if (!locked || delay === undefined)
|
|
210
|
+
return { error, locked };
|
|
211
|
+
wait(delay);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
function ageInDays(git, dir, ref, now) {
|
|
216
|
+
try {
|
|
217
|
+
const seconds = Number(git(dir, ['log', '-1', '--format=%ct', ref]).trim());
|
|
218
|
+
if (!Number.isFinite(seconds))
|
|
219
|
+
return null;
|
|
220
|
+
return Math.max(0, Math.floor((now.getTime() - seconds * 1000) / DAY_MS));
|
|
221
|
+
}
|
|
222
|
+
catch {
|
|
223
|
+
return null;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* 대상마다 클론을 확보하고 origin 기본 브랜치를 받아 온다. 예외를 던지지 않는다 — 실패는 failed와
|
|
228
|
+
* limitations로 돌려준다.
|
|
229
|
+
*/
|
|
230
|
+
export function prepareRelatedClones(opts) {
|
|
231
|
+
const gh = opts.gh ?? runGh;
|
|
232
|
+
const git = opts.git ?? defaultGit;
|
|
233
|
+
const now = opts.now ?? new Date();
|
|
234
|
+
const wait = opts.wait ?? sleepSync;
|
|
235
|
+
const cloneRoot = resolve(opts.cloneRoot ?? defaultCloneRoot());
|
|
236
|
+
const result = { sources: [], failed: [], limitations: [] };
|
|
237
|
+
const seen = new Set();
|
|
238
|
+
const fail = (repo, reason) => {
|
|
239
|
+
result.failed.push({ repo, reason });
|
|
240
|
+
result.limitations.push(`${repo}: 로컬 클론을 못 얻어 GitHub 검색으로 넘겼다 (${reason})`);
|
|
241
|
+
};
|
|
242
|
+
for (const target of opts.targets) {
|
|
243
|
+
const key = target.repo.toLowerCase();
|
|
244
|
+
if (seen.has(key))
|
|
245
|
+
continue;
|
|
246
|
+
seen.add(key);
|
|
247
|
+
const [owner, name, ...rest] = target.repo.split('/');
|
|
248
|
+
if (!owner ||
|
|
249
|
+
!name ||
|
|
250
|
+
rest.length > 0 ||
|
|
251
|
+
!SLUG_PART_RE.test(owner) ||
|
|
252
|
+
!SLUG_PART_RE.test(name)) {
|
|
253
|
+
fail(target.repo, 'owner/name 꼴이 아니다');
|
|
254
|
+
continue;
|
|
255
|
+
}
|
|
256
|
+
const managed = target.userDir === undefined;
|
|
257
|
+
const dir = managed ? join(cloneRoot, owner, name) : resolve(target.userDir);
|
|
258
|
+
let fresh = false;
|
|
259
|
+
if (!managed && !existsSync(dir)) {
|
|
260
|
+
fail(target.repo, `--repo-dir 경로가 없다: ${dir}`);
|
|
261
|
+
continue;
|
|
262
|
+
}
|
|
263
|
+
if (managed && !existsSync(join(dir, '.git'))) {
|
|
264
|
+
// 클론은 rename으로만 이 자리에 오므로 .git 없는 디렉토리는 이전 버전이 남긴 끊긴 클론이다
|
|
265
|
+
if (existsSync(dir) && dir.startsWith(cloneRoot + sep))
|
|
266
|
+
rmSync(dir, { recursive: true, force: true });
|
|
267
|
+
try {
|
|
268
|
+
cloneInto(gh, target.repo, dir, now);
|
|
269
|
+
fresh = true;
|
|
270
|
+
}
|
|
271
|
+
catch (e) {
|
|
272
|
+
fail(target.repo, `클론 실패: ${errMessage(e)}`);
|
|
273
|
+
continue;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
const branch = target.defaultBranch ?? originHeadBranch(git, dir) ?? 'main';
|
|
277
|
+
const ref = `refs/remotes/origin/${branch}`;
|
|
278
|
+
let fetchError = null;
|
|
279
|
+
let fetchLocked = false;
|
|
280
|
+
// 방금 받은 클론은 기본 브랜치가 이미 있다. 탐지한 기본 브랜치가 원격 HEAD와 다를 때만 더 받는다
|
|
281
|
+
if (!(fresh && resolveCommit(git, dir, ref) !== null)) {
|
|
282
|
+
// 사람이 준 클론은 이력을 잘라 얕게 만들면 안 된다. depth는 관리 클론에만 건다
|
|
283
|
+
const depth = managed ? ['--depth', '1'] : [];
|
|
284
|
+
const fetched = fetchWithRetry(git, dir, ['fetch', '--quiet', ...depth, 'origin', `+refs/heads/${branch}:${ref}`], wait);
|
|
285
|
+
fetchError = fetched.error;
|
|
286
|
+
fetchLocked = fetched.locked;
|
|
287
|
+
}
|
|
288
|
+
// ref 이름이 아니라 커밋으로 고정한다. 검색 도중 다른 수집이 같은 클론을 fetch해 ref를 옮기면
|
|
289
|
+
// 질의마다 다른 커밋을 보게 된다
|
|
290
|
+
const commit = resolveCommit(git, dir, ref);
|
|
291
|
+
if (commit === null) {
|
|
292
|
+
fail(target.repo, fetchError
|
|
293
|
+
? `origin/${branch}가 없고 fetch도 실패했다: ${fetchError}`
|
|
294
|
+
: `origin/${branch}가 없다`);
|
|
295
|
+
continue;
|
|
296
|
+
}
|
|
297
|
+
if (fetchError) {
|
|
298
|
+
const days = ageInDays(git, dir, commit, now);
|
|
299
|
+
const age = days === null ? '언제인지 모르는' : `${days}일 전`;
|
|
300
|
+
const cause = fetchLocked
|
|
301
|
+
? '다른 수집이 같은 클론을 받는 중이라 fetch를 못 해'
|
|
302
|
+
: 'fetch가 실패해';
|
|
303
|
+
result.limitations.push(`${target.repo}: ${cause} origin/${branch}를 ${age} 커밋 기준으로 봤다 (${fetchError})`);
|
|
304
|
+
}
|
|
305
|
+
result.sources.push({ repo: target.repo, dir, ref: commit });
|
|
306
|
+
}
|
|
307
|
+
return result;
|
|
308
|
+
}
|
|
309
|
+
//# sourceMappingURL=related-clones.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"related-clones.js","sourceRoot":"","sources":["../../../src/harness-review/related-clones.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rule-overlap.d.ts","sourceRoot":"","sources":["../../../src/harness-review/rule-overlap.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AA4BrD,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,GACf,kBAAkB,EAAE,CA6CtB"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 룰북 PR에서 룰끼리 겹치는 자리를 harness-reviewer 후보로 싣는다.
|
|
3
|
+
*
|
|
4
|
+
* 판정은 `src/humanize/overlap.ts`가 한다. 여기서는 base와 head의 룰북을 git에서 읽어
|
|
5
|
+
* 이번 변경에서 새로 생긴 문장이 낀 것만 후보로 바꾼다. 룰북 전체를 늘 걸면 오래된
|
|
6
|
+
* 겹침이 PR마다 다시 올라와서 리뷰어가 후보를 안 읽게 된다.
|
|
7
|
+
*/
|
|
8
|
+
import { execFileSync } from 'node:child_process';
|
|
9
|
+
import { dirname } from 'node:path';
|
|
10
|
+
import { changedSentences, checkOverlap, hasRuleTable, parseRuleEntries, RULE_DETECTORS, } from '../humanize/overlap.js';
|
|
11
|
+
/** 룰북이 사는 자리. 플러그인 공유 레퍼런스뿐이다 */
|
|
12
|
+
const RULEBOOK_DIR = /(?:^|\/)_shared\/references\/[^/]+\.md$/;
|
|
13
|
+
function rulebooksAt(git, ref, dirs) {
|
|
14
|
+
const entries = [];
|
|
15
|
+
for (const dir of dirs) {
|
|
16
|
+
let names;
|
|
17
|
+
try {
|
|
18
|
+
names = git('ls-tree', '--name-only', `${ref}:${dir}`).split('\n').filter(Boolean);
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
// base에 없던 디렉토리면 그쪽 문장이 전부 새것이다
|
|
22
|
+
continue;
|
|
23
|
+
}
|
|
24
|
+
for (const name of names.filter((n) => n.endsWith('.md'))) {
|
|
25
|
+
const path = `${dir}/${name}`;
|
|
26
|
+
const text = git('show', `${ref}:${path}`);
|
|
27
|
+
if (hasRuleTable(text))
|
|
28
|
+
entries.push(...parseRuleEntries(text, path));
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return entries;
|
|
32
|
+
}
|
|
33
|
+
export function findRuleOverlapFromGit(repoRoot, base, head, repoName) {
|
|
34
|
+
const git = (...args) => execFileSync('git', ['-c', 'core.quotepath=false', ...args], {
|
|
35
|
+
cwd: repoRoot,
|
|
36
|
+
encoding: 'utf-8',
|
|
37
|
+
maxBuffer: 64 * 1024 * 1024,
|
|
38
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
39
|
+
});
|
|
40
|
+
const changedFiles = git('diff', '--name-only', base, head)
|
|
41
|
+
.split('\n')
|
|
42
|
+
.filter((p) => RULEBOOK_DIR.test(p));
|
|
43
|
+
if (changedFiles.length === 0)
|
|
44
|
+
return [];
|
|
45
|
+
// 겹침은 파일을 넘나든다. 바뀐 룰북과 같은 디렉토리의 룰북을 함께 읽는다
|
|
46
|
+
const dirs = new Set(changedFiles.map((p) => dirname(p)));
|
|
47
|
+
const headEntries = rulebooksAt(git, head, dirs);
|
|
48
|
+
if (headEntries.length === 0)
|
|
49
|
+
return [];
|
|
50
|
+
const changed = changedSentences(rulebooksAt(git, base, dirs), headEntries);
|
|
51
|
+
if (changed.size === 0)
|
|
52
|
+
return [];
|
|
53
|
+
const report = checkOverlap(headEntries, RULE_DETECTORS, { changed });
|
|
54
|
+
const fromMatrix = report.findings
|
|
55
|
+
.filter((f) => f.level === 'error' && changed.has(f.example.sentence))
|
|
56
|
+
.map((f) => ({
|
|
57
|
+
kind: 'ruleOverlap',
|
|
58
|
+
sourceFile: headEntries.find((e) => e.id === f.ruleId)?.file ?? '',
|
|
59
|
+
sourceLine: f.example.line,
|
|
60
|
+
targetRepo: repoName,
|
|
61
|
+
targetPath: headEntries.find((e) => e.id === f.hitBy)?.file ?? '',
|
|
62
|
+
matchedText: `[${f.code}] ${f.message}`,
|
|
63
|
+
contextLines: [f.example.sentence],
|
|
64
|
+
needsLlmJudgment: false,
|
|
65
|
+
}));
|
|
66
|
+
const fromText = report.candidates.map((c) => ({
|
|
67
|
+
kind: 'ruleOverlap',
|
|
68
|
+
sourceFile: c.file,
|
|
69
|
+
sourceLine: c.line,
|
|
70
|
+
targetRepo: repoName,
|
|
71
|
+
targetPath: headEntries.find((e) => e.id === c.rules[1])?.file ?? c.file,
|
|
72
|
+
matchedText: `[${c.code}] ${c.question}`,
|
|
73
|
+
contextLines: c.evidence,
|
|
74
|
+
needsLlmJudgment: true,
|
|
75
|
+
}));
|
|
76
|
+
return [...fromMatrix, ...fromText];
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=rule-overlap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rule-overlap.js","sourceRoot":"","sources":["../../../src/harness-review/rule-overlap.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { SearchBackend } from './types.js';
|
|
1
|
+
import type { SearchBackend, SearchBackendKind } from './types.js';
|
|
2
2
|
export interface SearchHit {
|
|
3
3
|
/** owner/name 표기 */
|
|
4
4
|
repo: string;
|
|
@@ -21,6 +21,17 @@ export interface SearchResult {
|
|
|
21
21
|
export interface SearchOptions {
|
|
22
22
|
/** 레포당 상한. 넘으면 앞쪽만 남긴다 */
|
|
23
23
|
maxHitsPerRepo?: number;
|
|
24
|
+
/**
|
|
25
|
+
* 이 문자열도 함께 있는 결과만 쓸 질의. GitHub 백엔드는 질의에 AND로 붙여 서버가 거르게 하고
|
|
26
|
+
* 로컬 백엔드는 무시한다. 부르는 쪽이 어차피 결과를 다시 거르므로 로컬에서 더 찾아도 틀리지 않는다
|
|
27
|
+
*/
|
|
28
|
+
requireAlso?: string;
|
|
29
|
+
}
|
|
30
|
+
export interface BackendCounts {
|
|
31
|
+
/** 실제로 찾은 질의 수 */
|
|
32
|
+
searched: number;
|
|
33
|
+
/** 한도나 막힘 때문에 보내지 않은 질의 수 */
|
|
34
|
+
skipped: number;
|
|
24
35
|
}
|
|
25
36
|
/** 식별자 문자열을 관련 레포에서 찾는 역방향 검색. 구현체를 바꿔 끼워도 호출부는 그대로다 */
|
|
26
37
|
export interface CodeSearchBackend extends SearchBackend {
|
|
@@ -31,6 +42,13 @@ export interface CodeSearchBackend extends SearchBackend {
|
|
|
31
42
|
* 모르면 undefined다. 파일 목록을 싸게 못 얻는 백엔드는 구현하지 않는다
|
|
32
43
|
*/
|
|
33
44
|
hasFile?(repo: string, path: string): boolean | undefined;
|
|
45
|
+
/**
|
|
46
|
+
* 앞으로 보낼 질의마다 넘길 레포 목록을 미리 알린다. 한도가 있는 백엔드가 남은 질의로
|
|
47
|
+
* 기다릴지 정하는 데 쓴다
|
|
48
|
+
*/
|
|
49
|
+
plan?(queryRepos: string[][]): void;
|
|
50
|
+
/** 백엔드별 범위. refs.json에 그대로 싣는다 */
|
|
51
|
+
counts?(): Partial<Record<SearchBackendKind, BackendCounts>>;
|
|
34
52
|
}
|
|
35
53
|
export declare const DEFAULT_MAX_HITS_PER_REPO = 100;
|
|
36
54
|
export declare const MAX_HIT_TEXT_LENGTH = 300;
|
|
@@ -50,10 +68,14 @@ export declare class LocalCloneBackend implements CodeSearchBackend {
|
|
|
50
68
|
rateLimited: boolean;
|
|
51
69
|
};
|
|
52
70
|
private readonly sources;
|
|
71
|
+
private searchedCount;
|
|
72
|
+
private skippedCount;
|
|
53
73
|
private readonly fileLists;
|
|
54
74
|
constructor(sources: LocalRepoSource[]);
|
|
55
75
|
hasFile(repo: string, path: string): boolean | undefined;
|
|
56
76
|
private fileList;
|
|
57
77
|
search(identifier: string, repos: string[], opts?: SearchOptions): Promise<SearchResult>;
|
|
78
|
+
counts(): Partial<Record<SearchBackendKind, BackendCounts>>;
|
|
79
|
+
private searchRepos;
|
|
58
80
|
}
|
|
59
81
|
//# sourceMappingURL=search-backend.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search-backend.d.ts","sourceRoot":"","sources":["../../../src/harness-review/search-backend.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"search-backend.d.ts","sourceRoot":"","sources":["../../../src/harness-review/search-backend.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEnE,MAAM,WAAW,SAAS;IACxB,oBAAoB;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,2BAA2B;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,aAAa;IACb,IAAI,EAAE,MAAM,CAAC;IACb,0CAA0C;IAC1C,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,SAAS,EAAE,CAAC;IAClB,kDAAkD;IAClD,OAAO,EAAE,WAAW,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,aAAa;IAC5B,0BAA0B;IAC1B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,aAAa;IAC5B,kBAAkB;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,6BAA6B;IAC7B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wDAAwD;AACxD,MAAM,WAAW,iBAAkB,SAAQ,aAAa;IACtD,4DAA4D;IAC5D,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,IAAI,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IACzF;;;OAGG;IACH,OAAO,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;IAC1D;;;OAGG;IACH,IAAI,CAAC,CAAC,UAAU,EAAE,MAAM,EAAE,EAAE,GAAG,IAAI,CAAC;IACpC,kCAAkC;IAClC,MAAM,CAAC,IAAI,OAAO,CAAC,MAAM,CAAC,iBAAiB,EAAE,aAAa,CAAC,CAAC,CAAC;CAC9D;AAED,eAAO,MAAM,yBAAyB,MAAM,CAAC;AAC7C,eAAO,MAAM,mBAAmB,MAAM,CAAC;AAKvC,MAAM,WAAW,eAAe;IAC9B,iBAAiB;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,wBAAwB;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,2CAA2C;IAC3C,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,qBAAa,iBAAkB,YAAW,iBAAiB;IACzD,QAAQ,CAAC,IAAI,EAAG,YAAY,CAAU;IACtC,QAAQ,CAAC,YAAY;;;;MAInB;IAEF,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAsC;IAE9D,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,YAAY,CAAK;IAEzB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAwE;gBAEtF,OAAO,EAAE,eAAe,EAAE;IAItC,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS;IAYxD,OAAO,CAAC,QAAQ;IAqBV,MAAM,CACV,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,MAAM,EAAE,EACf,IAAI,GAAE,aAAkB,GACvB,OAAO,CAAC,YAAY,CAAC;IAUxB,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC,iBAAiB,EAAE,aAAa,CAAC,CAAC;IAI3D,OAAO,CAAC,WAAW;CAsBpB"}
|
|
@@ -13,6 +13,8 @@ export class LocalCloneBackend {
|
|
|
13
13
|
rateLimited: false,
|
|
14
14
|
};
|
|
15
15
|
sources = new Map();
|
|
16
|
+
searchedCount = 0;
|
|
17
|
+
skippedCount = 0;
|
|
16
18
|
fileLists = new Map();
|
|
17
19
|
constructor(sources) {
|
|
18
20
|
for (const s of sources)
|
|
@@ -55,6 +57,17 @@ export class LocalCloneBackend {
|
|
|
55
57
|
const result = { hits: [], skipped: [] };
|
|
56
58
|
if (identifier === '')
|
|
57
59
|
return result;
|
|
60
|
+
this.searchRepos(identifier, repos, max, result);
|
|
61
|
+
if (result.skipped.length > 0)
|
|
62
|
+
this.skippedCount++;
|
|
63
|
+
else
|
|
64
|
+
this.searchedCount++;
|
|
65
|
+
return result;
|
|
66
|
+
}
|
|
67
|
+
counts() {
|
|
68
|
+
return { localClone: { searched: this.searchedCount, skipped: this.skippedCount } };
|
|
69
|
+
}
|
|
70
|
+
searchRepos(identifier, repos, max, result) {
|
|
58
71
|
for (const repo of repos) {
|
|
59
72
|
const source = this.sources.get(repo);
|
|
60
73
|
if (!source) {
|
|
@@ -71,7 +84,6 @@ export class LocalCloneBackend {
|
|
|
71
84
|
result.skipped.push({ repo, reason: e instanceof Error ? e.message : String(e) });
|
|
72
85
|
}
|
|
73
86
|
}
|
|
74
|
-
return result;
|
|
75
87
|
}
|
|
76
88
|
}
|
|
77
89
|
function toHit(repo, path, line, text) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search-backend.js","sourceRoot":"","sources":["../../../src/harness-review/search-backend.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAClE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"search-backend.js","sourceRoot":"","sources":["../../../src/harness-review/search-backend.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const REFERENCE_CANDIDATE_KINDS: readonly ["selfContamination", "copyDrift", "forwardRef", "backwardRef", "knowledgeDoc", "ruleIdListGap"];
|
|
1
|
+
export declare const REFERENCE_CANDIDATE_KINDS: readonly ["selfContamination", "copyDrift", "forwardRef", "backwardRef", "knowledgeDoc", "ruleIdListGap", "ruleOverlap"];
|
|
2
2
|
export type ReferenceCandidateKind = (typeof REFERENCE_CANDIDATE_KINDS)[number];
|
|
3
3
|
export interface ReferenceCandidate {
|
|
4
4
|
kind: ReferenceCandidateKind;
|