@tienne/gestalt 0.83.2 → 0.84.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/CLAUDE.md +2 -2
- package/README.ko.md +3 -1
- package/README.md +3 -1
- package/dist/package.json +1 -1
- package/dist/plugin/review-agents/harness-reviewer/AGENT.md +211 -0
- package/dist/plugin/role-agents/_shared/references/comment-rules.md +1 -1
- package/dist/plugin/role-agents/suggestion-verifier/AGENT.md +7 -1
- package/dist/plugin/skills/_shared/proactive-routing.md +1 -0
- package/dist/plugin/skills/_shared/rule-sources.md +1 -1
- package/dist/plugin/skills/agent/SKILL.md +2 -0
- package/dist/plugin/skills/review/SKILL.md +343 -7
- package/dist/plugin/skills/review-loop/SKILL.md +124 -2
- package/dist/plugin/skills/ship/SKILL.md +40 -1
- package/dist/schemas/gestalt.schema.json +12 -0
- package/dist/src/cli/commands/approve-gate.d.ts +24 -0
- package/dist/src/cli/commands/approve-gate.d.ts.map +1 -0
- package/dist/src/cli/commands/approve-gate.js +90 -0
- package/dist/src/cli/commands/approve-gate.js.map +1 -0
- package/dist/src/cli/commands/harness-refs-cross-pr.d.ts +218 -0
- package/dist/src/cli/commands/harness-refs-cross-pr.d.ts.map +1 -0
- package/dist/src/cli/commands/harness-refs-cross-pr.js +934 -0
- package/dist/src/cli/commands/harness-refs-cross-pr.js.map +1 -0
- package/dist/src/cli/commands/harness-refs.d.ts +19 -0
- package/dist/src/cli/commands/harness-refs.d.ts.map +1 -0
- package/dist/src/cli/commands/harness-refs.js +51 -0
- package/dist/src/cli/commands/harness-refs.js.map +1 -0
- package/dist/src/cli/index.d.ts.map +1 -1
- package/dist/src/cli/index.js +97 -0
- package/dist/src/cli/index.js.map +1 -1
- package/dist/src/core/config.d.ts +3 -0
- package/dist/src/core/config.d.ts.map +1 -1
- package/dist/src/core/config.js +23 -0
- package/dist/src/core/config.js.map +1 -1
- package/dist/src/core/types.d.ts +2 -0
- package/dist/src/core/types.d.ts.map +1 -1
- package/dist/src/harness-review/approve-gate.d.ts +53 -0
- package/dist/src/harness-review/approve-gate.d.ts.map +1 -0
- package/dist/src/harness-review/approve-gate.js +148 -0
- package/dist/src/harness-review/approve-gate.js.map +1 -0
- package/dist/src/harness-review/backward-search.d.ts +50 -0
- package/dist/src/harness-review/backward-search.d.ts.map +1 -0
- package/dist/src/harness-review/backward-search.js +183 -0
- package/dist/src/harness-review/backward-search.js.map +1 -0
- package/dist/src/harness-review/collect.d.ts +75 -0
- package/dist/src/harness-review/collect.d.ts.map +1 -0
- package/dist/src/harness-review/collect.js +253 -0
- package/dist/src/harness-review/collect.js.map +1 -0
- package/dist/src/harness-review/copy-drift.d.ts +83 -0
- package/dist/src/harness-review/copy-drift.d.ts.map +1 -0
- package/dist/src/harness-review/copy-drift.js +477 -0
- package/dist/src/harness-review/copy-drift.js.map +1 -0
- package/dist/src/harness-review/follow-up-marker.d.ts +29 -0
- package/dist/src/harness-review/follow-up-marker.d.ts.map +1 -0
- package/dist/src/harness-review/follow-up-marker.js +143 -0
- package/dist/src/harness-review/follow-up-marker.js.map +1 -0
- package/dist/src/harness-review/forward-search.d.ts +30 -0
- package/dist/src/harness-review/forward-search.d.ts.map +1 -0
- package/dist/src/harness-review/forward-search.js +381 -0
- package/dist/src/harness-review/forward-search.js.map +1 -0
- package/dist/src/harness-review/github-backend.d.ts +42 -0
- package/dist/src/harness-review/github-backend.d.ts.map +1 -0
- package/dist/src/harness-review/github-backend.js +130 -0
- package/dist/src/harness-review/github-backend.js.map +1 -0
- package/dist/src/harness-review/github-code-search.d.ts +46 -0
- package/dist/src/harness-review/github-code-search.d.ts.map +1 -0
- package/dist/src/harness-review/github-code-search.js +94 -0
- package/dist/src/harness-review/github-code-search.js.map +1 -0
- package/dist/src/harness-review/identifiers.d.ts +75 -0
- package/dist/src/harness-review/identifiers.d.ts.map +1 -0
- package/dist/src/harness-review/identifiers.js +678 -0
- package/dist/src/harness-review/identifiers.js.map +1 -0
- package/dist/src/harness-review/placeholders.d.ts +44 -0
- package/dist/src/harness-review/placeholders.d.ts.map +1 -0
- package/dist/src/harness-review/placeholders.js +138 -0
- package/dist/src/harness-review/placeholders.js.map +1 -0
- package/dist/src/harness-review/related-pr.d.ts +133 -0
- package/dist/src/harness-review/related-pr.d.ts.map +1 -0
- package/dist/src/harness-review/related-pr.js +553 -0
- package/dist/src/harness-review/related-pr.js.map +1 -0
- package/dist/src/harness-review/related-repos.d.ts +69 -0
- package/dist/src/harness-review/related-repos.d.ts.map +1 -0
- package/dist/src/harness-review/related-repos.js +430 -0
- package/dist/src/harness-review/related-repos.js.map +1 -0
- package/dist/src/harness-review/remote-url.d.ts +8 -0
- package/dist/src/harness-review/remote-url.d.ts.map +1 -0
- package/dist/src/harness-review/remote-url.js +35 -0
- package/dist/src/harness-review/remote-url.js.map +1 -0
- package/dist/src/harness-review/replay.d.ts +163 -0
- package/dist/src/harness-review/replay.d.ts.map +1 -0
- package/dist/src/harness-review/replay.js +575 -0
- package/dist/src/harness-review/replay.js.map +1 -0
- package/dist/src/harness-review/rule-id-lists.d.ts +38 -0
- package/dist/src/harness-review/rule-id-lists.d.ts.map +1 -0
- package/dist/src/harness-review/rule-id-lists.js +189 -0
- package/dist/src/harness-review/rule-id-lists.js.map +1 -0
- package/dist/src/harness-review/search-backend.d.ts +59 -0
- package/dist/src/harness-review/search-backend.d.ts.map +1 -0
- package/dist/src/harness-review/search-backend.js +178 -0
- package/dist/src/harness-review/search-backend.js.map +1 -0
- package/dist/src/harness-review/self-contamination.d.ts +83 -0
- package/dist/src/harness-review/self-contamination.d.ts.map +1 -0
- package/dist/src/harness-review/self-contamination.js +560 -0
- package/dist/src/harness-review/self-contamination.js.map +1 -0
- package/dist/src/harness-review/self-references.d.ts +20 -0
- package/dist/src/harness-review/self-references.d.ts.map +1 -0
- package/dist/src/harness-review/self-references.js +173 -0
- package/dist/src/harness-review/self-references.js.map +1 -0
- package/dist/src/harness-review/three-state.d.ts +79 -0
- package/dist/src/harness-review/three-state.d.ts.map +1 -0
- package/dist/src/harness-review/three-state.js +238 -0
- package/dist/src/harness-review/three-state.js.map +1 -0
- package/dist/src/harness-review/types.d.ts +148 -0
- package/dist/src/harness-review/types.d.ts.map +1 -0
- package/dist/src/harness-review/types.js +74 -0
- package/dist/src/harness-review/types.js.map +1 -0
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +1 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/mcp/tools/review-passthrough.js +7 -1
- package/dist/src/mcp/tools/review-passthrough.js.map +1 -1
- package/dist/src/review/agent-matcher.d.ts +16 -1
- package/dist/src/review/agent-matcher.d.ts.map +1 -1
- package/dist/src/review/agent-matcher.js +31 -4
- package/dist/src/review/agent-matcher.js.map +1 -1
- package/dist/src/review/passthrough-engine.d.ts.map +1 -1
- package/dist/src/review/passthrough-engine.js +40 -2
- package/dist/src/review/passthrough-engine.js.map +1 -1
- package/package.json +1 -1
- 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 +211 -0
- package/plugin/role-agents/_shared/references/comment-rules.md +1 -1
- package/plugin/role-agents/suggestion-verifier/AGENT.md +7 -1
- package/plugin/skills/_shared/proactive-routing.md +1 -0
- package/plugin/skills/_shared/rule-sources.md +1 -1
- package/plugin/skills/agent/SKILL.md +2 -0
- package/plugin/skills/review/SKILL.md +343 -7
- package/plugin/skills/review-loop/SKILL.md +124 -2
- package/plugin/skills/ship/SKILL.md +40 -1
- package/schemas/gestalt.schema.json +12 -0
|
@@ -0,0 +1,575 @@
|
|
|
1
|
+
import { COLLECT_BACKENDS } from './collect.js';
|
|
2
|
+
import { REFERENCE_CANDIDATE_KINDS } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* 과거 하네스 PR 재현 스크립트(scripts/local/replay-harness-prs.ts)의 순수 로직.
|
|
5
|
+
*
|
|
6
|
+
* 스크립트는 사내 레포를 다루므로 gitignore 자리에 두고 커밋하지 않는다. 테스트가 그 경로를
|
|
7
|
+
* import하면 CI에서 파일이 없어 깨지니 인자 해석과 리포트 조립만 여기로 뺐다. 이 모듈은
|
|
8
|
+
* 측정값을 표로 옮길 뿐 합격이나 불합격을 가르지 않는다. 기준 수치는 첫 측정을 본 뒤에 정한다.
|
|
9
|
+
*/
|
|
10
|
+
export const DEFAULT_OLD_VERSION = '0.83.2';
|
|
11
|
+
/**
|
|
12
|
+
* 새 버전 칸의 이름. package.json 버전은 배포 전까지 옛 버전과 같은 번호라 커밋으로 가른다.
|
|
13
|
+
* 미커밋 변경이 있으면 그 커밋과도 다른 코드가 돈 것이라 따로 적는다.
|
|
14
|
+
*/
|
|
15
|
+
export function checkoutLabel(shortSha, dirty = false) {
|
|
16
|
+
const parts = [shortSha ?? '커밋 모름', ...(dirty ? ['미커밋 변경 포함'] : [])];
|
|
17
|
+
return `현재 체크아웃(${parts.join(', ')})`;
|
|
18
|
+
}
|
|
19
|
+
export const REPLAY_USAGE = [
|
|
20
|
+
'usage: tsx scripts/local/replay-harness-prs.ts --pr-list <file> [options]',
|
|
21
|
+
' --pr-list <file> 재현할 PR 목록 JSON (로컬 전용)',
|
|
22
|
+
' --repo-dir <path> PR이 있는 레포 체크아웃 (기본: 현재 디렉토리)',
|
|
23
|
+
` --old-version <ver> 비교할 배포 버전 (기본: ${DEFAULT_OLD_VERSION})`,
|
|
24
|
+
' --repeat <n> 버전마다 돌릴 횟수 (기본: 3)',
|
|
25
|
+
' --backend local|github 역방향 검색 백엔드 (기본: local)',
|
|
26
|
+
' --related-dir <spec> collect --repo-dir로 넘길 관련 레포 (여러 번)',
|
|
27
|
+
' --review-cmd <shell> 워크트리에서 돌릴 리뷰 명령. $GESTALT_REPLAY_OUT에 JSON을 쓴다',
|
|
28
|
+
' --code-graph-db <path> 회차마다 워크트리에 복사할 코드 그래프 DB (co-change 경로용)',
|
|
29
|
+
].join('\n');
|
|
30
|
+
function isPositiveInteger(value) {
|
|
31
|
+
return /^[1-9]\d*$/.test(value);
|
|
32
|
+
}
|
|
33
|
+
export function parseReplayArgs(argv, cwd) {
|
|
34
|
+
const args = {
|
|
35
|
+
prList: '',
|
|
36
|
+
repoDir: cwd,
|
|
37
|
+
oldVersion: DEFAULT_OLD_VERSION,
|
|
38
|
+
repeat: 3,
|
|
39
|
+
backend: 'local',
|
|
40
|
+
relatedDirs: [],
|
|
41
|
+
reviewCmd: null,
|
|
42
|
+
codeGraphDb: null,
|
|
43
|
+
};
|
|
44
|
+
for (let i = 0; i < argv.length; i++) {
|
|
45
|
+
const flag = argv[i];
|
|
46
|
+
if (flag === '--help' || flag === '-h')
|
|
47
|
+
return { ok: false, error: REPLAY_USAGE };
|
|
48
|
+
const value = argv[i + 1];
|
|
49
|
+
if (value === undefined || value.startsWith('--')) {
|
|
50
|
+
return { ok: false, error: `${flag} 뒤에 값이 없다` };
|
|
51
|
+
}
|
|
52
|
+
i++;
|
|
53
|
+
switch (flag) {
|
|
54
|
+
case '--pr-list':
|
|
55
|
+
args.prList = value;
|
|
56
|
+
break;
|
|
57
|
+
case '--repo-dir':
|
|
58
|
+
args.repoDir = value;
|
|
59
|
+
break;
|
|
60
|
+
case '--old-version':
|
|
61
|
+
if (!/^\d+\.\d+\.\d+([-.][\w.]+)?$/.test(value)) {
|
|
62
|
+
return { ok: false, error: `--old-version은 x.y.z 꼴이어야 한다: ${value}` };
|
|
63
|
+
}
|
|
64
|
+
args.oldVersion = value;
|
|
65
|
+
break;
|
|
66
|
+
case '--repeat':
|
|
67
|
+
if (!isPositiveInteger(value)) {
|
|
68
|
+
return { ok: false, error: `--repeat는 1 이상의 정수다: ${value}` };
|
|
69
|
+
}
|
|
70
|
+
args.repeat = Number(value);
|
|
71
|
+
break;
|
|
72
|
+
case '--backend':
|
|
73
|
+
if (!COLLECT_BACKENDS.includes(value)) {
|
|
74
|
+
return {
|
|
75
|
+
ok: false,
|
|
76
|
+
error: `--backend는 ${COLLECT_BACKENDS.join('|')} 중 하나다: ${value}`,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
args.backend = value;
|
|
80
|
+
break;
|
|
81
|
+
case '--related-dir':
|
|
82
|
+
args.relatedDirs.push(value);
|
|
83
|
+
break;
|
|
84
|
+
case '--review-cmd':
|
|
85
|
+
args.reviewCmd = value;
|
|
86
|
+
break;
|
|
87
|
+
case '--code-graph-db':
|
|
88
|
+
args.codeGraphDb = value;
|
|
89
|
+
break;
|
|
90
|
+
default:
|
|
91
|
+
return { ok: false, error: `모르는 옵션: ${flag}` };
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
if (!args.prList)
|
|
95
|
+
return { ok: false, error: '--pr-list가 필요하다' };
|
|
96
|
+
return { ok: true, value: args };
|
|
97
|
+
}
|
|
98
|
+
const REPO_PATTERN = /^[\w.-]+\/[\w.-]+$/;
|
|
99
|
+
// git 인자로 들어가므로 옵션처럼 읽히는 값을 막는다
|
|
100
|
+
function isSafeRev(value) {
|
|
101
|
+
return value.length > 0 && !value.startsWith('-') && !/\s/.test(value);
|
|
102
|
+
}
|
|
103
|
+
function asRecord(v) {
|
|
104
|
+
return typeof v === 'object' && v !== null && !Array.isArray(v)
|
|
105
|
+
? v
|
|
106
|
+
: null;
|
|
107
|
+
}
|
|
108
|
+
function optionalString(v) {
|
|
109
|
+
return typeof v === 'string' && v.trim() !== '' ? v.trim() : null;
|
|
110
|
+
}
|
|
111
|
+
function parseExpectation(raw, where) {
|
|
112
|
+
const r = asRecord(raw);
|
|
113
|
+
if (!r)
|
|
114
|
+
return { ok: false, error: `${where}: 객체가 아니다` };
|
|
115
|
+
const id = optionalString(r.id);
|
|
116
|
+
if (!id)
|
|
117
|
+
return { ok: false, error: `${where}: id가 필요하다` };
|
|
118
|
+
const exp = { id, description: optionalString(r.description) ?? id };
|
|
119
|
+
const path = optionalString(r.path);
|
|
120
|
+
if (path)
|
|
121
|
+
exp.path = path;
|
|
122
|
+
const text = optionalString(r.text);
|
|
123
|
+
if (text)
|
|
124
|
+
exp.text = text;
|
|
125
|
+
if (r.line !== undefined) {
|
|
126
|
+
if (!Number.isInteger(r.line) || r.line < 1) {
|
|
127
|
+
return { ok: false, error: `${where}: line은 1 이상의 정수다` };
|
|
128
|
+
}
|
|
129
|
+
exp.line = r.line;
|
|
130
|
+
}
|
|
131
|
+
if (r.lineTolerance !== undefined) {
|
|
132
|
+
if (!Number.isInteger(r.lineTolerance) || r.lineTolerance < 0) {
|
|
133
|
+
return { ok: false, error: `${where}: lineTolerance는 0 이상의 정수다` };
|
|
134
|
+
}
|
|
135
|
+
exp.lineTolerance = r.lineTolerance;
|
|
136
|
+
}
|
|
137
|
+
if (!exp.path && !exp.text) {
|
|
138
|
+
return { ok: false, error: `${where}: path나 text 중 하나는 있어야 맞춰볼 수 있다` };
|
|
139
|
+
}
|
|
140
|
+
return { ok: true, value: exp };
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* PR 목록 파일을 읽는다. 배열이거나 `{ "entries": [...] }`다.
|
|
144
|
+
*
|
|
145
|
+
* 항목마다 `pr`(번호) 또는 `base`와 `head`(커밋)가 있어야 한다. `followedByFix`를 안 적으면
|
|
146
|
+
* `expected`가 있는지로 정한다.
|
|
147
|
+
*/
|
|
148
|
+
export function parseReplayList(text) {
|
|
149
|
+
let json;
|
|
150
|
+
try {
|
|
151
|
+
json = JSON.parse(text);
|
|
152
|
+
}
|
|
153
|
+
catch (e) {
|
|
154
|
+
return { ok: false, error: `PR 목록이 JSON이 아니다: ${e.message}` };
|
|
155
|
+
}
|
|
156
|
+
const list = Array.isArray(json) ? json : asRecord(json)?.entries;
|
|
157
|
+
if (!Array.isArray(list) || list.length === 0) {
|
|
158
|
+
return { ok: false, error: 'PR 목록이 비었다 (배열 또는 { "entries": [...] })' };
|
|
159
|
+
}
|
|
160
|
+
const entries = [];
|
|
161
|
+
const seen = new Set();
|
|
162
|
+
for (const [i, raw] of list.entries()) {
|
|
163
|
+
const where = `entries[${i}]`;
|
|
164
|
+
const r = asRecord(raw);
|
|
165
|
+
if (!r)
|
|
166
|
+
return { ok: false, error: `${where}: 객체가 아니다` };
|
|
167
|
+
let pr = null;
|
|
168
|
+
if (r.pr !== undefined) {
|
|
169
|
+
if (!Number.isInteger(r.pr) || r.pr < 1) {
|
|
170
|
+
return { ok: false, error: `${where}: pr은 1 이상의 정수다` };
|
|
171
|
+
}
|
|
172
|
+
pr = r.pr;
|
|
173
|
+
}
|
|
174
|
+
const repo = optionalString(r.repo);
|
|
175
|
+
if (repo && !REPO_PATTERN.test(repo)) {
|
|
176
|
+
return { ok: false, error: `${where}: repo는 owner/name 꼴이다: ${repo}` };
|
|
177
|
+
}
|
|
178
|
+
const base = optionalString(r.base);
|
|
179
|
+
const head = optionalString(r.head);
|
|
180
|
+
for (const [name, rev] of [
|
|
181
|
+
['base', base],
|
|
182
|
+
['head', head],
|
|
183
|
+
]) {
|
|
184
|
+
if (rev !== null && !isSafeRev(rev)) {
|
|
185
|
+
return { ok: false, error: `${where}: ${name}에 쓸 수 없는 값: ${rev}` };
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
if (pr === null && (base === null || head === null)) {
|
|
189
|
+
return { ok: false, error: `${where}: pr이 없으면 base와 head가 둘 다 필요하다` };
|
|
190
|
+
}
|
|
191
|
+
const expected = [];
|
|
192
|
+
if (r.expected !== undefined) {
|
|
193
|
+
if (!Array.isArray(r.expected))
|
|
194
|
+
return { ok: false, error: `${where}: expected는 배열이다` };
|
|
195
|
+
for (const [j, e] of r.expected.entries()) {
|
|
196
|
+
const parsed = parseExpectation(e, `${where}.expected[${j}]`);
|
|
197
|
+
if (!parsed.ok)
|
|
198
|
+
return parsed;
|
|
199
|
+
expected.push(parsed.value);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
let followedByFix = expected.length > 0;
|
|
203
|
+
if (r.followedByFix !== undefined) {
|
|
204
|
+
if (typeof r.followedByFix !== 'boolean') {
|
|
205
|
+
return { ok: false, error: `${where}: followedByFix는 true나 false다` };
|
|
206
|
+
}
|
|
207
|
+
followedByFix = r.followedByFix;
|
|
208
|
+
}
|
|
209
|
+
const id = optionalString(r.id) ??
|
|
210
|
+
(pr !== null ? `pr-${pr}` : `${base.slice(0, 7)}..${head.slice(0, 7)}`);
|
|
211
|
+
if (seen.has(id))
|
|
212
|
+
return { ok: false, error: `${where}: id가 겹친다: ${id}` };
|
|
213
|
+
seen.add(id);
|
|
214
|
+
entries.push({
|
|
215
|
+
id,
|
|
216
|
+
pr,
|
|
217
|
+
repo,
|
|
218
|
+
base,
|
|
219
|
+
head,
|
|
220
|
+
followedByFix,
|
|
221
|
+
expected,
|
|
222
|
+
note: optionalString(r.note),
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
return { ok: true, value: entries };
|
|
226
|
+
}
|
|
227
|
+
function lineOf(v) {
|
|
228
|
+
return typeof v === 'number' && Number.isInteger(v) && v > 0 ? v : null;
|
|
229
|
+
}
|
|
230
|
+
/** `gestalt harness-refs collect --json` 출력에서 후보를 꺼낸다. 모양이 다르면 빈 배열이다 */
|
|
231
|
+
export function commentsFromCollect(json) {
|
|
232
|
+
const candidates = asRecord(asRecord(json)?.candidates);
|
|
233
|
+
if (!candidates)
|
|
234
|
+
return [];
|
|
235
|
+
const out = [];
|
|
236
|
+
for (const kind of REFERENCE_CANDIDATE_KINDS) {
|
|
237
|
+
const list = candidates[kind];
|
|
238
|
+
if (!Array.isArray(list))
|
|
239
|
+
continue;
|
|
240
|
+
for (const raw of list) {
|
|
241
|
+
const c = asRecord(raw);
|
|
242
|
+
if (!c)
|
|
243
|
+
continue;
|
|
244
|
+
const targetRepo = optionalString(c.targetRepo);
|
|
245
|
+
const targetPath = optionalString(c.targetPath);
|
|
246
|
+
const target = [targetRepo, targetPath].filter(Boolean).join(':');
|
|
247
|
+
out.push({
|
|
248
|
+
source: 'collect',
|
|
249
|
+
kind,
|
|
250
|
+
path: optionalString(c.sourceFile) ?? '',
|
|
251
|
+
line: lineOf(c.sourceLine),
|
|
252
|
+
relatedPath: targetPath,
|
|
253
|
+
relatedLine: lineOf(c.targetLine),
|
|
254
|
+
// 역방향 후보는 matchedText가 식별자라 걸린 줄 내용은 contextLines에만 있다
|
|
255
|
+
body: [
|
|
256
|
+
target,
|
|
257
|
+
optionalString(c.matchedText),
|
|
258
|
+
...(Array.isArray(c.contextLines)
|
|
259
|
+
? c.contextLines.filter((l) => typeof l === 'string')
|
|
260
|
+
: []),
|
|
261
|
+
]
|
|
262
|
+
.filter(Boolean)
|
|
263
|
+
.join(' — '),
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
return out;
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* 리뷰 명령이 쓴 JSON에서 코멘트를 꺼낸다.
|
|
271
|
+
*
|
|
272
|
+
* ReviewIssue 배열, `{ issues }`나 `{ comments }`, ReviewResult 배열 중 무엇이든 받는다.
|
|
273
|
+
* 이 텍스트는 세어서 표에 옮길 뿐 재현 절차에 영향을 주지 않는다.
|
|
274
|
+
*/
|
|
275
|
+
export function commentsFromReview(json) {
|
|
276
|
+
const items = [];
|
|
277
|
+
const visit = (v) => {
|
|
278
|
+
if (Array.isArray(v)) {
|
|
279
|
+
for (const x of v)
|
|
280
|
+
visit(x);
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
const r = asRecord(v);
|
|
284
|
+
if (!r)
|
|
285
|
+
return;
|
|
286
|
+
const nested = r.issues ?? r.comments ?? r.findings;
|
|
287
|
+
if (Array.isArray(nested)) {
|
|
288
|
+
visit(nested);
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
items.push(r);
|
|
292
|
+
};
|
|
293
|
+
visit(json);
|
|
294
|
+
const out = [];
|
|
295
|
+
for (const raw of items) {
|
|
296
|
+
const r = raw;
|
|
297
|
+
const body = optionalString(r.message) ??
|
|
298
|
+
optionalString(r.body) ??
|
|
299
|
+
optionalString(r.comment) ??
|
|
300
|
+
optionalString(r.description);
|
|
301
|
+
if (!body)
|
|
302
|
+
continue;
|
|
303
|
+
out.push({
|
|
304
|
+
source: 'review',
|
|
305
|
+
kind: optionalString(r.category) ??
|
|
306
|
+
optionalString(r.kind) ??
|
|
307
|
+
optionalString(r.reportedBy) ??
|
|
308
|
+
'review',
|
|
309
|
+
path: optionalString(r.file) ?? optionalString(r.path) ?? '',
|
|
310
|
+
line: lineOf(r.line) ?? lineOf(r.startLine),
|
|
311
|
+
relatedPath: null,
|
|
312
|
+
relatedLine: null,
|
|
313
|
+
body,
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
return out;
|
|
317
|
+
}
|
|
318
|
+
/** 회차를 넘어 같은 코멘트로 묶을 때 쓰는 키. 본문 공백 차이는 무시한다 */
|
|
319
|
+
export function commentFingerprint(c) {
|
|
320
|
+
return [c.source, c.kind, c.path, c.line ?? '', c.body.replace(/\s+/g, ' ').trim()].join('|');
|
|
321
|
+
}
|
|
322
|
+
// 옛 버전에도 있던 코멘트인지 볼 때 쓴다. LLM 리뷰는 회차마다 문장이 달라지니 본문은 뺀다
|
|
323
|
+
function commentPlace(c) {
|
|
324
|
+
return [c.source, c.kind, c.path, c.line ?? ''].join('|');
|
|
325
|
+
}
|
|
326
|
+
// 자기오염 후보는 룰 자리(path)와 오염된 자리(relatedPath)를 함께 든다.
|
|
327
|
+
// 기대 항목은 대개 오염된 자리를 적으므로 줄 번호도 그 자리의 줄과 맞춰 본다
|
|
328
|
+
export function matchesExpectation(c, e) {
|
|
329
|
+
const places = [{ path: c.path, line: c.line }];
|
|
330
|
+
if (c.relatedPath)
|
|
331
|
+
places.push({ path: c.relatedPath, line: c.relatedLine });
|
|
332
|
+
const placed = places.some((p) => (e.path === undefined || p.path === e.path) &&
|
|
333
|
+
(e.line === undefined ||
|
|
334
|
+
(p.line !== null && Math.abs(p.line - e.line) <= (e.lineTolerance ?? 0))));
|
|
335
|
+
if (!placed)
|
|
336
|
+
return false;
|
|
337
|
+
// 기대 항목의 text는 그 줄에 적힌 문자열이다. collect 후보 본문은 그 줄을 옮겨 오지만 리뷰 코멘트는
|
|
338
|
+
// 리뷰어 말로 쓰므로 자리만 맞으면 잡은 것으로 본다
|
|
339
|
+
if (e.text !== undefined && c.source === 'collect' && !c.body.includes(e.text))
|
|
340
|
+
return false;
|
|
341
|
+
return true;
|
|
342
|
+
}
|
|
343
|
+
export const STEP_STATUSES = ['ok', 'unsupported', 'failed', 'skipped'];
|
|
344
|
+
function mean(values) {
|
|
345
|
+
return values.length === 0 ? null : values.reduce((a, b) => a + b, 0) / values.length;
|
|
346
|
+
}
|
|
347
|
+
function stepNote(label, runs, pick) {
|
|
348
|
+
const notes = [];
|
|
349
|
+
for (const status of ['unsupported', 'failed', 'skipped']) {
|
|
350
|
+
const hit = runs.filter((r) => pick(r).status === status);
|
|
351
|
+
if (hit.length === 0)
|
|
352
|
+
continue;
|
|
353
|
+
const word = { unsupported: '명령 없음', failed: '실패', skipped: '안 돌림' }[status];
|
|
354
|
+
notes.push(`${label} ${word} ${hit.length}/${runs.length}회`);
|
|
355
|
+
}
|
|
356
|
+
return notes;
|
|
357
|
+
}
|
|
358
|
+
export function summarizeVersion(runs, version) {
|
|
359
|
+
const mine = runs.filter((r) => r.version === version).sort((a, b) => a.iteration - b.iteration);
|
|
360
|
+
const counts = mine.map((r) => r.comments.length);
|
|
361
|
+
const notes = [
|
|
362
|
+
...stepNote('collect', mine, (r) => r.collect),
|
|
363
|
+
...stepNote('리뷰', mine, (r) => r.review),
|
|
364
|
+
];
|
|
365
|
+
const skippedRefs = mine.filter((r) => r.collect.referenceCheckSkipped).length;
|
|
366
|
+
if (skippedRefs > 0)
|
|
367
|
+
notes.push(`참조 검사 일부 못 봄 ${skippedRefs}/${mine.length}회`);
|
|
368
|
+
return { counts, mean: mean(counts), notes };
|
|
369
|
+
}
|
|
370
|
+
function formatMean(v) {
|
|
371
|
+
return v === null ? '-' : v.toFixed(1);
|
|
372
|
+
}
|
|
373
|
+
function formatDiff(oldMean, newMean) {
|
|
374
|
+
if (oldMean === null || newMean === null)
|
|
375
|
+
return '-';
|
|
376
|
+
const d = newMean - oldMean;
|
|
377
|
+
return `${d > 0 ? '+' : ''}${d.toFixed(1)}`;
|
|
378
|
+
}
|
|
379
|
+
function cell(text) {
|
|
380
|
+
return text.replace(/\|/g, '\\|').replace(/\r?\n/g, ' ');
|
|
381
|
+
}
|
|
382
|
+
function rangeLabel(r) {
|
|
383
|
+
if (!r.base || !r.head)
|
|
384
|
+
return '-';
|
|
385
|
+
return `\`${r.base.slice(0, 7)}..${r.head.slice(0, 7)}\``;
|
|
386
|
+
}
|
|
387
|
+
function countsCell(s) {
|
|
388
|
+
if (s.counts.length === 0)
|
|
389
|
+
return '-';
|
|
390
|
+
return `${s.counts.join(', ')} (평균 ${formatMean(s.mean)})`;
|
|
391
|
+
}
|
|
392
|
+
export function expectationHits(result) {
|
|
393
|
+
return result.entry.expected.map((expectation) => {
|
|
394
|
+
const hits = {};
|
|
395
|
+
for (const version of ['old', 'new']) {
|
|
396
|
+
const mine = result.runs.filter((r) => r.version === version);
|
|
397
|
+
hits[version] = {
|
|
398
|
+
runs: mine.filter((r) => r.comments.some((c) => matchesExpectation(c, expectation))).length,
|
|
399
|
+
total: mine.length,
|
|
400
|
+
};
|
|
401
|
+
}
|
|
402
|
+
return { expectation, hits };
|
|
403
|
+
});
|
|
404
|
+
}
|
|
405
|
+
/** 측정 리포트 본문. 숫자와 회차별 상태만 적고 통과 여부는 적지 않는다 */
|
|
406
|
+
export function buildReplayReport(input) {
|
|
407
|
+
const { versions } = input;
|
|
408
|
+
const lines = [
|
|
409
|
+
`# 하네스 PR 재현 리포트 (${input.runId})`,
|
|
410
|
+
'',
|
|
411
|
+
`- 레포: ${input.repoLabel}`,
|
|
412
|
+
`- 만든 시각: ${input.createdAt}`,
|
|
413
|
+
`- 비교: ${versions.old} (옛 버전) / ${versions.new}`,
|
|
414
|
+
`- 버전마다 ${input.repeat}회, 역방향 검색 백엔드 ${input.backend}`,
|
|
415
|
+
`- 리뷰 명령: ${input.reviewCmdGiven ? '돌림' : '안 줌. collect 후보만 셌다'}`,
|
|
416
|
+
'- GitHub에는 아무것도 게시하지 않았다. 판정 기준 수치는 아직 정하지 않았으므로 측정값만 싣는다.',
|
|
417
|
+
'',
|
|
418
|
+
];
|
|
419
|
+
const failed = input.results.filter((r) => r.error);
|
|
420
|
+
const clean = input.results.filter((r) => !r.error && !r.entry.followedByFix);
|
|
421
|
+
const fixed = input.results.filter((r) => !r.error && r.entry.followedByFix);
|
|
422
|
+
lines.push('## fix가 안 따라온 PR', '');
|
|
423
|
+
if (clean.length === 0) {
|
|
424
|
+
lines.push('없음', '');
|
|
425
|
+
}
|
|
426
|
+
else {
|
|
427
|
+
lines.push(`| 항목 | 범위 | ${versions.old} 코멘트 수 | ${versions.new} 코멘트 수 | 평균 차이 | 비고 |`, '|---|---|---|---|---|---|');
|
|
428
|
+
for (const r of clean) {
|
|
429
|
+
const o = summarizeVersion(r.runs, 'old');
|
|
430
|
+
const n = summarizeVersion(r.runs, 'new');
|
|
431
|
+
const notes = [
|
|
432
|
+
...o.notes.map((x) => `${versions.old} ${x}`),
|
|
433
|
+
...n.notes.map((x) => `${versions.new} ${x}`),
|
|
434
|
+
];
|
|
435
|
+
lines.push(`| ${cell(r.entry.id)} | ${rangeLabel(r)} | ${countsCell(o)} | ${countsCell(n)} | ${formatDiff(o.mean, n.mean)} | ${cell(notes.join('; ') || '-')} |`);
|
|
436
|
+
}
|
|
437
|
+
lines.push('');
|
|
438
|
+
}
|
|
439
|
+
lines.push('## fix가 따라온 PR', '');
|
|
440
|
+
if (fixed.length === 0) {
|
|
441
|
+
lines.push('없음', '');
|
|
442
|
+
}
|
|
443
|
+
for (const r of fixed) {
|
|
444
|
+
const o = summarizeVersion(r.runs, 'old');
|
|
445
|
+
const n = summarizeVersion(r.runs, 'new');
|
|
446
|
+
const hits = expectationHits(r);
|
|
447
|
+
lines.push(`### ${r.entry.id} ${rangeLabel(r)}`, '');
|
|
448
|
+
if (r.entry.note)
|
|
449
|
+
lines.push(`${r.entry.note}`, '');
|
|
450
|
+
lines.push(`- 코멘트 수: ${versions.old} ${countsCell(o)} / ${versions.new} ${countsCell(n)} / 평균 차이 ${formatDiff(o.mean, n.mean)}`);
|
|
451
|
+
for (const x of [
|
|
452
|
+
...o.notes.map((y) => `${versions.old} ${y}`),
|
|
453
|
+
...n.notes.map((y) => `${versions.new} ${y}`),
|
|
454
|
+
]) {
|
|
455
|
+
lines.push(`- ${x}`);
|
|
456
|
+
}
|
|
457
|
+
for (const version of ['old', 'new']) {
|
|
458
|
+
const caught = hits.filter((h) => h.hits[version].runs > 0).length;
|
|
459
|
+
lines.push(`- ${versions[version]}: 한 번이라도 잡은 항목 ${caught}개, 한 번도 못 잡은 항목 ${hits.length - caught}개`);
|
|
460
|
+
}
|
|
461
|
+
lines.push('');
|
|
462
|
+
if (hits.length > 0) {
|
|
463
|
+
lines.push(`| 기대 항목 | 설명 | 자리 | ${versions.old} 잡은 회차 | ${versions.new} 잡은 회차 |`, '|---|---|---|---|---|');
|
|
464
|
+
for (const h of hits) {
|
|
465
|
+
const e = h.expectation;
|
|
466
|
+
const place = [
|
|
467
|
+
e.path,
|
|
468
|
+
e.line !== undefined ? `:${e.line}` : '',
|
|
469
|
+
e.text ? ` "${e.text}"` : '',
|
|
470
|
+
]
|
|
471
|
+
.join('')
|
|
472
|
+
.trim();
|
|
473
|
+
lines.push(`| ${cell(e.id)} | ${cell(e.description)} | ${cell(place || '-')} | ${h.hits.old.runs}/${h.hits.old.total} | ${h.hits.new.runs}/${h.hits.new.total} |`);
|
|
474
|
+
}
|
|
475
|
+
lines.push('');
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
if (failed.length > 0) {
|
|
479
|
+
lines.push('## 재현하지 못한 항목', '');
|
|
480
|
+
for (const r of failed)
|
|
481
|
+
lines.push(`- ${r.entry.id}: ${r.error}`);
|
|
482
|
+
lines.push('');
|
|
483
|
+
}
|
|
484
|
+
return lines.join('\n');
|
|
485
|
+
}
|
|
486
|
+
/** 새 버전이 낸 코멘트를 회차를 넘어 중복 없이 모은다 */
|
|
487
|
+
export function collectLabelItems(results) {
|
|
488
|
+
const items = [];
|
|
489
|
+
for (const r of results) {
|
|
490
|
+
const newRuns = r.runs.filter((x) => x.version === 'new');
|
|
491
|
+
const oldPlaces = new Set(r.runs.filter((x) => x.version === 'old').flatMap((x) => x.comments.map(commentPlace)));
|
|
492
|
+
const byFp = new Map();
|
|
493
|
+
for (const run of newRuns) {
|
|
494
|
+
const seenThisRun = new Set();
|
|
495
|
+
for (const c of run.comments) {
|
|
496
|
+
const fp = commentFingerprint(c);
|
|
497
|
+
if (seenThisRun.has(fp))
|
|
498
|
+
continue;
|
|
499
|
+
seenThisRun.add(fp);
|
|
500
|
+
const found = byFp.get(fp);
|
|
501
|
+
if (found) {
|
|
502
|
+
found.seenRuns++;
|
|
503
|
+
continue;
|
|
504
|
+
}
|
|
505
|
+
byFp.set(fp, {
|
|
506
|
+
entryId: r.entry.id,
|
|
507
|
+
comment: c,
|
|
508
|
+
seenRuns: 1,
|
|
509
|
+
totalRuns: newRuns.length,
|
|
510
|
+
inOldVersion: oldPlaces.has(commentPlace(c)),
|
|
511
|
+
});
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
items.push(...byFp.values());
|
|
515
|
+
}
|
|
516
|
+
return items;
|
|
517
|
+
}
|
|
518
|
+
export const LABEL_PREFIX = 'label:';
|
|
519
|
+
/** 사용자가 코멘트마다 correct나 incorrect를 적는 시트 */
|
|
520
|
+
export function buildLabelSheet(input) {
|
|
521
|
+
const items = collectLabelItems(input.results.filter((r) => !r.error));
|
|
522
|
+
const lines = [
|
|
523
|
+
`# 새 버전 코멘트 라벨 (${input.runId})`,
|
|
524
|
+
'',
|
|
525
|
+
`각 코멘트의 \`${LABEL_PREFIX}\` 뒤에 \`correct\`나 \`incorrect\`를 적는다. 모르면 비워둔다.`,
|
|
526
|
+
`${input.versions.new}가 낸 코멘트를 회차를 넘어 하나로 묶었다. 모두 ${items.length}개.`,
|
|
527
|
+
'',
|
|
528
|
+
];
|
|
529
|
+
items.forEach((item, i) => {
|
|
530
|
+
const c = item.comment;
|
|
531
|
+
const place = `${c.path || '(파일 없음)'}${c.line !== null ? `:${c.line}` : ''}`;
|
|
532
|
+
lines.push(`## ${i + 1}. ${item.entryId} \`${place}\``, '', `- 종류: ${c.source} / ${c.kind}`, `- 나온 회차: ${item.seenRuns}/${item.totalRuns}`, `- ${input.versions.old}에도 같은 자리: ${item.inOldVersion ? '예' : '아니오'}`, '', ...c.body.split(/\r?\n/).map((l) => `> ${l}`), '', `${LABEL_PREFIX} `, '');
|
|
533
|
+
});
|
|
534
|
+
return lines.join('\n');
|
|
535
|
+
}
|
|
536
|
+
const GH_READ_ONLY = {
|
|
537
|
+
auth: ['status'],
|
|
538
|
+
search: null,
|
|
539
|
+
pr: ['view', 'list', 'diff', 'checks', 'status'],
|
|
540
|
+
repo: ['view', 'list'],
|
|
541
|
+
issue: ['view', 'list'],
|
|
542
|
+
api: null,
|
|
543
|
+
};
|
|
544
|
+
const GH_API_WRITE_FLAGS = ['-f', '-F', '--field', '--raw-field', '--input'];
|
|
545
|
+
/**
|
|
546
|
+
* 재현 중 자식 프로세스가 부르는 gh가 읽기만 하는지 본다.
|
|
547
|
+
*
|
|
548
|
+
* 리뷰 명령이 review 스킬을 돌리면 PR 대상일 때 코멘트를 게시하려 한다. 재현은 게시 없이
|
|
549
|
+
* 리포트만 내야 하므로 스크립트가 PATH 앞에 둔 gh 가림막이 이 함수로 쓰기 호출을 끊는다.
|
|
550
|
+
*/
|
|
551
|
+
export function isReadOnlyGhCall(args) {
|
|
552
|
+
const [group, sub] = args;
|
|
553
|
+
if (group === undefined || !(group in GH_READ_ONLY))
|
|
554
|
+
return false;
|
|
555
|
+
const allowed = GH_READ_ONLY[group];
|
|
556
|
+
if (allowed && (sub === undefined || !allowed.includes(sub)))
|
|
557
|
+
return false;
|
|
558
|
+
if (group !== 'api')
|
|
559
|
+
return true;
|
|
560
|
+
for (let i = 1; i < args.length; i++) {
|
|
561
|
+
const a = args[i];
|
|
562
|
+
if (GH_API_WRITE_FLAGS.some((f) => a === f || a.startsWith(`${f}=`)))
|
|
563
|
+
return false;
|
|
564
|
+
if (a === '-X' || a === '--method') {
|
|
565
|
+
if ((args[i + 1] ?? '').toUpperCase() !== 'GET')
|
|
566
|
+
return false;
|
|
567
|
+
}
|
|
568
|
+
else if (/^(-X|--method=)/.test(a) &&
|
|
569
|
+
a.replace(/^(-X|--method=)/, '').toUpperCase() !== 'GET') {
|
|
570
|
+
return false;
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
return true;
|
|
574
|
+
}
|
|
575
|
+
//# sourceMappingURL=replay.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"replay.js","sourceRoot":"","sources":["../../../src/harness-review/replay.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { ReferenceCandidate } from './types.js';
|
|
2
|
+
export interface RuleIdListGapInput {
|
|
3
|
+
diff: string;
|
|
4
|
+
/** head 트리의 파일 경로 */
|
|
5
|
+
files: string[];
|
|
6
|
+
readFile: (path: string) => string | undefined;
|
|
7
|
+
/** 후보의 targetRepo에 싣는 자기 레포 표기. 기본값 '.' */
|
|
8
|
+
repoName?: string;
|
|
9
|
+
}
|
|
10
|
+
/** 이보다 적게 나열한 자리는 목록이 아니라 설명 속 언급으로 본다 */
|
|
11
|
+
export declare const MIN_LIST_IDS = 3;
|
|
12
|
+
/** 룰 ID 사이가 이 줄 수보다 벌어지면 다른 목록으로 나눈다 */
|
|
13
|
+
export declare const MAX_LIST_GAP_LINES = 2;
|
|
14
|
+
export declare const MAX_LIST_CONTEXT_LINES = 8;
|
|
15
|
+
export interface RuleIdList {
|
|
16
|
+
file: string;
|
|
17
|
+
startLine: number;
|
|
18
|
+
endLine: number;
|
|
19
|
+
ids: Set<string>;
|
|
20
|
+
/** 나온 차례대로. 같은 ID가 두 번 나오면 둘 다 있다 */
|
|
21
|
+
entries: Array<{
|
|
22
|
+
id: string;
|
|
23
|
+
line: number;
|
|
24
|
+
}>;
|
|
25
|
+
}
|
|
26
|
+
/** diff의 추가 줄에서 정의된 룰 ID를 룰북 경로별로 모은다 */
|
|
27
|
+
export declare function changedRuleIds(diff: string): Map<string, Set<string>>;
|
|
28
|
+
/** 따옴표로 감싼 룰 ID가 줄 간격 MAX_LIST_GAP_LINES 안에서 이어지는 구간을 목록 하나로 묶는다 */
|
|
29
|
+
export declare function findRuleIdLists(file: string, content: string): RuleIdList[];
|
|
30
|
+
/**
|
|
31
|
+
* 빠진 ID가 들어갈 줄. ID 순으로 정렬된 목록이면 순서상 자리를, 아니면 목록 끝 다음 줄을 준다.
|
|
32
|
+
* 리뷰어가 코멘트를 달 자리이고 목록 첫 줄을 주면 긴 목록에서 어디를 보라는 건지 흐려진다.
|
|
33
|
+
*/
|
|
34
|
+
export declare function insertionLine(list: RuleIdList, id: string): number;
|
|
35
|
+
export declare function findRuleIdListGaps(input: RuleIdListGapInput): ReferenceCandidate[];
|
|
36
|
+
/** base와 head 사이 diff로 검사한다. 파일은 head 트리에서 읽는다 */
|
|
37
|
+
export declare function findRuleIdListGapsFromGit(repoRoot: string, base: string, head: string, repoName?: string): ReferenceCandidate[];
|
|
38
|
+
//# sourceMappingURL=rule-id-lists.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rule-id-lists.d.ts","sourceRoot":"","sources":["../../../src/harness-review/rule-id-lists.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAErD,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,qBAAqB;IACrB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IAC/C,2CAA2C;IAC3C,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,0CAA0C;AAC1C,eAAO,MAAM,YAAY,IAAI,CAAC;AAC9B,wCAAwC;AACxC,eAAO,MAAM,kBAAkB,IAAI,CAAC;AACpC,eAAO,MAAM,sBAAsB,IAAI,CAAC;AAOxC,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACjB,qCAAqC;IACrC,OAAO,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC9C;AAMD,yCAAyC;AACzC,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAgBrE;AAiBD,oEAAoE;AACpE,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,UAAU,EAAE,CAmB3E;AAQD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAMlE;AAQD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,kBAAkB,GAAG,kBAAkB,EAAE,CAsClF;AAED,kDAAkD;AAClD,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,QAAQ,CAAC,EAAE,MAAM,GAChB,kBAAkB,EAAE,CAkCtB"}
|