@open-agent-toolkit/cli 0.1.12 → 0.1.14

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.
Files changed (45) hide show
  1. package/assets/agents/oat-reviewer.md +54 -10
  2. package/assets/docs/workflows/projects/reviews.md +21 -2
  3. package/assets/docs/workflows/skills/index.md +2 -0
  4. package/assets/public-package-versions.json +4 -4
  5. package/assets/skills/oat-project-review-provide-remote/SKILL.md +354 -0
  6. package/assets/skills/oat-project-review-receive/SKILL.md +7 -10
  7. package/assets/skills/oat-project-review-receive-remote/SKILL.md +4 -4
  8. package/assets/skills/oat-review-provide-remote/SKILL.md +273 -0
  9. package/assets/skills/oat-review-receive/SKILL.md +6 -6
  10. package/assets/skills/oat-review-receive-remote/SKILL.md +5 -5
  11. package/dist/commands/init/tools/shared/skill-manifest.d.ts +2 -2
  12. package/dist/commands/init/tools/shared/skill-manifest.d.ts.map +1 -1
  13. package/dist/commands/init/tools/shared/skill-manifest.js +2 -0
  14. package/dist/config/json.d.ts +2 -0
  15. package/dist/config/json.d.ts.map +1 -0
  16. package/dist/config/json.js +29 -0
  17. package/dist/config/oat-config.d.ts.map +1 -1
  18. package/dist/config/oat-config.js +4 -3
  19. package/dist/config/sync-config.d.ts.map +1 -1
  20. package/dist/config/sync-config.js +2 -1
  21. package/dist/review-remote/body-builder.d.ts +79 -0
  22. package/dist/review-remote/body-builder.d.ts.map +1 -0
  23. package/dist/review-remote/body-builder.js +103 -0
  24. package/dist/review-remote/capability-probe.d.ts +61 -0
  25. package/dist/review-remote/capability-probe.d.ts.map +1 -0
  26. package/dist/review-remote/capability-probe.js +87 -0
  27. package/dist/review-remote/line-mapper.d.ts +81 -0
  28. package/dist/review-remote/line-mapper.d.ts.map +1 -0
  29. package/dist/review-remote/line-mapper.js +165 -0
  30. package/dist/review-remote/marker-parser.d.ts +44 -0
  31. package/dist/review-remote/marker-parser.d.ts.map +1 -0
  32. package/dist/review-remote/marker-parser.js +97 -0
  33. package/dist/review-remote/narrowing.d.ts +81 -0
  34. package/dist/review-remote/narrowing.d.ts.map +1 -0
  35. package/dist/review-remote/narrowing.js +90 -0
  36. package/dist/review-remote/project-resolver.d.ts +46 -0
  37. package/dist/review-remote/project-resolver.d.ts.map +1 -0
  38. package/dist/review-remote/project-resolver.js +60 -0
  39. package/dist/review-remote/reviewer-dispatch.d.ts +108 -0
  40. package/dist/review-remote/reviewer-dispatch.d.ts.map +1 -0
  41. package/dist/review-remote/reviewer-dispatch.js +153 -0
  42. package/dist/review-remote/worktree.d.ts +62 -0
  43. package/dist/review-remote/worktree.d.ts.map +1 -0
  44. package/dist/review-remote/worktree.js +117 -0
  45. package/package.json +3 -2
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: oat-project-review-receive-remote
3
- version: 1.3.0
3
+ version: 1.4.0
4
4
  description: Use when processing GitHub PR review comments within project context. Fetches PR comments, creates plan tasks, and updates project artifacts.
5
5
  disable-model-invocation: true
6
6
  user-invocable: true
@@ -139,11 +139,11 @@ Before prompting dispositions, print:
139
139
 
140
140
  Disposition options:
141
141
 
142
- - `convert` (default for critical/important/medium)
143
- - `defer` (default for minor)
142
+ - `convert` (default for critical/important/medium/minor)
143
+ - `defer`
144
144
  - `dismiss`
145
145
 
146
- Require rationale for `defer`/`dismiss`.
146
+ Require concrete rationale for `defer`/`dismiss` at any severity, including minor. Small findings are usually cheaper to fix inline than to track as backlog items, so a minor `defer` must be justified just like any other deferral.
147
147
 
148
148
  ### Step 5: Convert Findings to Plan Tasks
149
149
 
@@ -0,0 +1,273 @@
1
+ ---
2
+ name: oat-review-provide-remote
3
+ version: 1.0.3
4
+ description: Use when reviewing a GitHub PR opened on another machine and posting findings back as a single PR review, outside any OAT project context. Fetches the PR via gh, reviews it, and posts via gh api.
5
+ disable-model-invocation: true
6
+ user-invocable: true
7
+ allowed-tools: Read, Write, Bash, Glob, Grep, AskUserQuestion
8
+ ---
9
+
10
+ # Remote Review Provide (Ad-hoc GitHub PR)
11
+
12
+ Review a GitHub PR opened by an agent on another machine and post the findings back as a single GitHub PR review — without requiring an active OAT project. GitHub is the source of truth: no local artifact is written and no lifecycle bookkeeping happens here. The posted review carries metadata markers so `oat-review-receive-remote` can round-trip the findings into tasks on the originating machine.
13
+
14
+ ## Prerequisites
15
+
16
+ - `gh` CLI is installed and authenticated (`gh auth status`).
17
+ - The PR to review exists on GitHub and is reachable from the current repo's remote.
18
+ - Optionally `npx agent-reviews` for posting symmetry (capability-probed at startup; `gh api` is the fallback).
19
+ - User wants an ad-hoc remote review outside the OAT project lifecycle.
20
+
21
+ ## Mode Assertion
22
+
23
+ **OAT MODE: Remote Review Provide**
24
+
25
+ **Purpose:** Fetch a GitHub PR, review it inline against the ad-hoc review checklist + severity model, and post a single PR review (summary + severity counts + inline comments + metadata markers) back to GitHub.
26
+
27
+ **BLOCKED Activities:**
28
+
29
+ - No `plan.md`, `state.md`, or `implementation.md` lifecycle mutations.
30
+ - No local review artifact written on this machine (GitHub is the source of truth).
31
+ - No mutation of the caller's working tree — all checkout happens in an ephemeral worktree.
32
+ - No implementing fixes, commits, or pushes (this skill reviews; it does not fix).
33
+ - No posting a review to GitHub without explicit user confirmation.
34
+
35
+ **ALLOWED Activities:**
36
+
37
+ - Resolve the PR number.
38
+ - Acquire PR content via ephemeral worktree + `gh pr checkout` (or `gh pr diff` fallback).
39
+ - Detect prior provide-remote reviews and narrow re-review scope (with the stale-SHA guard).
40
+ - Run the ad-hoc review inline (no tier model).
41
+ - Build the posted-review body + inline-comment array.
42
+ - Post a single PR review via `agent-reviews` (if probed supported) else `gh api` (with user confirmation).
43
+
44
+ **Self-Correction Protocol:**
45
+ If you catch yourself:
46
+
47
+ - Running `gh pr checkout` in the caller's working tree instead of an ephemeral worktree -> STOP, acquire the worktree first, and check out inside it.
48
+ - Writing a review artifact file on this machine -> STOP; the posted PR review is the only output.
49
+ - Editing project lifecycle artifacts (`plan.md`, `state.md`, `implementation.md`) -> STOP and revert to review-and-post only.
50
+ - Posting the review to GitHub without explicit user confirmation -> STOP and present the body + verdict for approval first.
51
+ - Narrowing against a prior review SHA without running the existence + ancestry guard -> STOP and run the guard first.
52
+ - Forgetting to remove the ephemeral worktree after posting (or on failure) -> STOP and release it in a `finally`.
53
+
54
+ ## Progress Indicators (User-Facing)
55
+
56
+ Print this banner once at start:
57
+
58
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
59
+ OAT ▸ REMOTE REVIEW PROVIDE
60
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
61
+
62
+ Use step indicators:
63
+
64
+ - `[1/7] Resolving PR...`
65
+ - `[2/7] Checking out PR (ephemeral worktree)...`
66
+ - `[3/7] Detecting prior reviews + narrowing scope...`
67
+ - `[4/7] Running review...`
68
+ - `[5/7] Mapping inline comments to the diff...`
69
+ - `[6/7] Building review body + verdict...`
70
+ - `[7/7] Posting review + cleanup...`
71
+
72
+ ## Arguments
73
+
74
+ ```
75
+ oat-review-provide-remote [--pr <N>] [--no-checkout] [--narrow|--no-narrow]
76
+ ```
77
+
78
+ - `--pr <N>`: target PR number. When omitted, auto-detect from the current branch.
79
+ - `--no-checkout`: skip the ephemeral worktree and review from `gh pr diff` only (degraded context).
80
+ - `--narrow` / `--no-narrow`: force or forbid re-review narrowing against a prior provide-remote review. When neither is passed, honor `workflow.autoNarrowReReviewScope` (no prompt when `true`; confirm prompt otherwise).
81
+
82
+ Inputs are CLI-style args parsed from `$ARGUMENTS`. No file inputs. No file outputs on this machine.
83
+
84
+ ## Findings Model
85
+
86
+ Normalize every finding to this shape (matches the ad-hoc review checklist and the `oat-review-receive-remote` model):
87
+
88
+ ```yaml
89
+ finding:
90
+ id: "C1" | "I1" | "M1" | "m1"
91
+ severity: critical | important | medium | minor
92
+ title: string
93
+ file: string | null
94
+ line: number | null
95
+ body: string
96
+ fix_guidance: string | null
97
+ ```
98
+
99
+ Severity conventions:
100
+
101
+ - `critical`: Broken behavior, security risk, or missing P0 requirement.
102
+ - `important`: Missing P1 requirement, major robustness issue.
103
+ - `medium`: Meaningful but non-blocking quality/maintainability issue.
104
+ - `minor`: Cosmetic/style/documentation issue.
105
+
106
+ Checklist + severity model source of truth: `.agents/skills/oat-review-provide/references/review-artifact-template.md`.
107
+
108
+ ## Process
109
+
110
+ ### Step 1: Resolve PR Number
111
+
112
+ PR resolution order:
113
+
114
+ 1. `--pr <N>` from `$ARGUMENTS`.
115
+ 2. Auto-detect from the current branch: `gh pr view --json number -q .number`.
116
+
117
+ Confirm `gh auth status` succeeds. Ask the user to confirm the resolved PR number before checkout. Capture the PR HEAD SHA (full 40-char) for the marker block and the narrowing guard:
118
+
119
+ ```bash
120
+ PR_HEAD_SHA=$(gh pr view "$PR" --json headRefOid -q .headRefOid)
121
+ ```
122
+
123
+ ### Step 2: Check Out the PR (Hybrid Read)
124
+
125
+ Acquire an ephemeral worktree FIRST, then run `gh pr checkout` inside it so the caller's working tree is never mutated. Use repo-scoped git commands so the skill works regardless of the caller's CWD (design.md → Data Flow step 2). This shell flow parallels the tested TypeScript helper at `packages/cli/src/review-remote/worktree.ts` (`acquireWorktree` / `runInWorktree` / `releaseWorktree`) — keep the two in sync if you change either:
126
+
127
+ ```bash
128
+ REPO_ROOT=$(git rev-parse --show-toplevel)
129
+ EPHEMERAL_PATH=$(mktemp -d)
130
+ rmdir "$EPHEMERAL_PATH" # git worktree add requires a non-existent target
131
+ git -C "$REPO_ROOT" worktree add --detach "$EPHEMERAL_PATH" HEAD
132
+ ( cd "$EPHEMERAL_PATH" && gh pr checkout "$PR" )
133
+ ```
134
+
135
+ The `-C "$REPO_ROOT"` flag is load-bearing — it lets the command run even when the caller's CWD is not inside the repository.
136
+
137
+ Fallback to diff-only mode when `--no-checkout` is set, or when worktree creation / `gh pr checkout` fails (capture exit code + stderr; distinguish auth from network from branch-state failures). On checkout failure, clean up the partial worktree (`git -C "$REPO_ROOT" worktree remove --force "$EPHEMERAL_PATH"`), then warn the user that context is degraded and continue with:
138
+
139
+ ```bash
140
+ gh pr diff "$PR" > "$DIFF_FILE"
141
+ gh pr view "$PR" --json title,body,headRefOid,baseRefName,state
142
+ ```
143
+
144
+ ### Step 3: Detect Prior Reviews + Narrow Scope
145
+
146
+ List prior PR reviews and parse each body's marker block. Filter to reviews where `oat_provide_remote: true` AND `oat_review_scope == "ad-hoc"` AND no `oat_project` key — project-rail markers are ignored by the ad-hoc filter.
147
+
148
+ ```bash
149
+ gh api "/repos/{owner}/{repo}/pulls/$PR/reviews"
150
+ ```
151
+
152
+ Take the most recent matching review (by submitted timestamp). Before narrowing to `<prior_sha>..<HEAD>`, run the stale-SHA guard (design.md → Error Handling → Stale prior-review SHA):
153
+
154
+ Run the guard in the available git context `$GIT_CTX` — `$EPHEMERAL_PATH` in rich-context (checkout) mode, or `$REPO_ROOT` in diff-only mode (where no worktree exists):
155
+
156
+ 1. **Existence:** `git -C "$GIT_CTX" cat-file -e <prior_sha>` (diff-only mode: `git -C "$REPO_ROOT" fetch origin <prior_sha>:refs/oat-prior-review` first, then re-check; if that fetch fails, fall back to full PR scope).
157
+ 2. **Ancestry:** `git -C "$GIT_CTX" merge-base --is-ancestor <prior_sha> "$PR_HEAD_SHA"`.
158
+
159
+ Guard outcomes:
160
+
161
+ - Both pass -> narrow to `<prior_sha>..<HEAD>`.
162
+ - Either fails -> fall back to full PR scope and warn that the prior SHA is unreachable (likely rebase/force-push).
163
+ - `--narrow` set AND guard fails -> hard error; surface unreachability and stop.
164
+ - `workflow.autoNarrowReReviewScope == true` -> never prompt; guard failure auto-falls back to full scope with the warning as the auto-fallback notice.
165
+ - No matching prior review -> use full PR diff.
166
+
167
+ ### Step 4: Run the Review (Inline)
168
+
169
+ Review inline (no tier model — matches local `oat-review-provide`) using the ad-hoc review checklist + severity model. Scope to the narrowing range when one was chosen; otherwise the full PR diff. Assign finding IDs per severity bucket (`C1`, `I1`, `M1`, `m1`).
170
+
171
+ ### Step 5: Map Inline Comments to the Diff
172
+
173
+ For each finding with non-null `file` + `line`, classify it against the PR diff BEFORE adding it to the inline `comments[]` payload (design.md → Error Handling → Inline-comment line mapping):
174
+
175
+ - Rich-context mode: parse hunk ranges from `gh api /repos/{owner}/{repo}/pulls/$PR/files` (per-file `patch` field).
176
+ - Diff-only mode: parse hunk headers (`@@ -a,b +c,d @@`) from the `gh pr diff` output.
177
+ - `side: RIGHT` for additions/context; `side: LEFT` only when the finding is explicitly about removed code.
178
+ - **Renamed files:** a `gh api .../files` entry carries the pre-rename path in a sibling `previous_filename` field (not in `patch`). When a finding references the pre-rename path, remap it to the entry's post-rename `filename` before classifying, or it will be treated as out-of-diff.
179
+ - If `line` falls outside the diff: downgrade the finding to a top-level "Findings outside the PR diff" subsection with its `file:line` reference. NEVER silently drop it and NEVER shift the line to the nearest in-diff line.
180
+
181
+ > **Reference implementation:** the canonical, tested logic for this step lives in `packages/cli/src/review-remote/line-mapper.ts` (`parsePullFilesPatch` / `parseUnifiedDiff` / `classifyFinding`). The bash/`jq` flow here mirrors it — keep the two in sync. See `packages/cli/src/review-remote/README.md`; `bl-a7cd` tracks wiring this skill to call the helpers directly. The same applies to the marker block (`marker-parser.ts`), body/verdict (`body-builder.ts`), and re-review narrowing (`narrowing.ts`) used in the steps below.
182
+
183
+ ### Step 6: Build the Review Body + Verdict
184
+
185
+ Build the posted-review body (design.md → Data Models → Posted-review-body): a leading HTML-comment marker block, then summary, severity counts, the minor-fix "Notes" nudge (only when minor findings are present), and optional verification commands.
186
+
187
+ Markers (ad-hoc rail):
188
+
189
+ ```
190
+ <!-- oat-review-metadata
191
+ oat_provide_remote: true
192
+ oat_review_head_sha: <PR_HEAD_SHA>
193
+ oat_review_scope: ad-hoc
194
+ oat_review_invocation: manual
195
+ -->
196
+ ```
197
+
198
+ `oat_project` is omitted entirely on the ad-hoc rail. Verdict: `REQUEST_CHANGES` when any critical or important finding exists; `COMMENT` otherwise (including a clean, zero-findings review — never auto-`APPROVE`).
199
+
200
+ ### Step 7: Post the Review + Clean Up
201
+
202
+ Probe `agent-reviews` for a posting flow with a non-mutating check (`npx agent-reviews --help`), cached for the run:
203
+
204
+ - If a posting flow is supported -> prefer `agent-reviews` for tooling symmetry.
205
+ - Otherwise (or if the probe is inconclusive) -> post via `gh api`. As of the current `agent-reviews` release there is no review-posting flow, so `gh api` is the expected path.
206
+
207
+ Present the body + verdict + inline-comment count to the user and get explicit confirmation, then post a single review.
208
+
209
+ `gh api --field`/`-f`/`-F` only set top-level scalar values; they CANNOT build the nested `comments[]` array of objects the reviews endpoint requires for inline comments. Construct the complete review payload as JSON and pipe it through `--input -` instead (a heredoc or a temp JSON file both work). Each in-diff finding (from Step 5) becomes one `comments[]` entry `{ path, line, side, body }`; out-of-diff findings are NOT added here — they were already downgraded into `$REVIEW_BODY` in Step 5. `event` is the Step 6 verdict (`REQUEST_CHANGES` when any critical/important finding exists, else `COMMENT`). A body-only review (zero in-diff findings) uses an empty `comments` array or omits the key:
210
+
211
+ ```bash
212
+ # Build the payload as JSON. `comments` is the in-diff findings array; jq
213
+ # assembles it safely (escaping body text, numbers as numbers). For a
214
+ # body-only review, COMMENTS_JSON is `[]`.
215
+ jq -n \
216
+ --arg event "$VERDICT" \
217
+ --arg body "$REVIEW_BODY" \
218
+ --argjson comments "$COMMENTS_JSON" \
219
+ '{event: $event, body: $body, comments: $comments}' \
220
+ | gh api --method POST "/repos/{owner}/{repo}/pulls/$PR/reviews" --input -
221
+
222
+ # COMMENTS_JSON is a JSON array, one object per in-diff finding, e.g.:
223
+ # [
224
+ # { "path": "src/foo.ts", "line": 42, "side": "RIGHT", "body": "..." },
225
+ # { "path": "src/bar.ts", "line": 17, "side": "LEFT", "body": "..." }
226
+ # ]
227
+ # `side` is RIGHT for additions/context, LEFT only for explicit removed-code
228
+ # findings (Step 5). Use `[]` when there are no in-diff findings.
229
+ ```
230
+
231
+ Posting failure handling (design.md → Error Handling → Posting failures): on auth failure, surface `gh auth status` and stop (findings kept in memory). On PR closed/merged, surface a clear message and present findings inline. On inline-comment rejection, re-map against the current file list and retry once; if still rejected, downgrade the offending finding(s) and retry. On rate limit, surface the window and stop. NEVER silently drop a finding.
232
+
233
+ Always release the ephemeral worktree in a `finally`, even when review or posting fails:
234
+
235
+ ```bash
236
+ git -C "$REPO_ROOT" worktree remove --force "$EPHEMERAL_PATH" || git -C "$REPO_ROOT" worktree prune
237
+ rm -rf "$EPHEMERAL_PATH"
238
+ ```
239
+
240
+ ## Troubleshooting
241
+
242
+ - Auth failure: run `gh auth status`; re-authenticate, then retry.
243
+ - No PR detected: pass explicit `--pr <N>`.
244
+ - Checkout fails: the skill auto-falls back to diff-only mode with a degraded-context warning; pass `--no-checkout` to force it.
245
+ - Prior-review SHA unreachable: re-invoke without `--narrow` to review full scope.
246
+ - Inline comment rejected at a file:line: the finding is downgraded to the top-level body, not dropped.
247
+ - Network / rate-limit errors: retry after backoff; report blocked state if persistent.
248
+
249
+ ## Output Contract
250
+
251
+ At completion, report:
252
+
253
+ - PR number and HEAD SHA reviewed.
254
+ - Read mode (worktree checkout vs diff-only).
255
+ - Narrowing decision (full scope vs `<prior_sha>..<HEAD>`, and why).
256
+ - Severity counts and total findings.
257
+ - Inline-comment count posted vs findings downgraded to the body (out-of-diff).
258
+ - Verdict (`REQUEST_CHANGES` or `COMMENT`).
259
+ - Posting mechanism (`agent-reviews` or `gh api`) and whether the review was posted.
260
+ - Confirmation that the ephemeral worktree was removed.
261
+
262
+ ## Success Criteria
263
+
264
+ - PR scope resolved and confirmed.
265
+ - PR content acquired via ephemeral worktree (or diff-only fallback) without mutating the caller's working tree.
266
+ - Prior provide-remote reviews detected; re-review narrowing applied only after the stale-SHA guard passes.
267
+ - Findings produced with consistent 4-tier severities and file:line references.
268
+ - Inline comments mapped to in-diff positions; out-of-diff findings downgraded to the body, never dropped.
269
+ - Posted-review body carries the marker block first, correct severity counts, and the minor-fix nudge when minors are present.
270
+ - Verdict matches the C/I rule (`REQUEST_CHANGES` vs `COMMENT`; never auto-`APPROVE`).
271
+ - Single PR review posted (with user confirmation) via `agent-reviews` if supported, else `gh api`.
272
+ - Ephemeral worktree removed on success and on failure.
273
+ - No local artifact, no lifecycle bookkeeping, no fixes/commits/pushes on this machine.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: oat-review-receive
3
- version: 1.3.0
3
+ version: 1.4.0
4
4
  description: Use when processing review findings outside project context. Converts local review artifacts into actionable task lists.
5
5
  disable-model-invocation: true
6
6
  user-invocable: true
@@ -41,8 +41,8 @@ If you catch yourself:
41
41
 
42
42
  - Editing project lifecycle docs in ad-hoc mode -> STOP and revert to task-list output only.
43
43
  - Triaging without presenting a findings overview first -> STOP and show overview before disposition prompts.
44
- - Skipping Medium finding rationale when proposing deferral -> STOP and collect explicit rationale.
45
- - Auto-deferring Minor findings without checking future cleanup likelihood or fix cost -> STOP and re-evaluate the recommendation.
44
+ - Skipping rationale when proposing deferral at any severity (including Minor) -> STOP and collect explicit rationale.
45
+ - Defaulting a Minor finding to `defer` instead of `convert` -> STOP; the Minor default is `convert` (fix inline), and `defer` requires concrete rationale.
46
46
 
47
47
  **Recovery:**
48
48
 
@@ -182,12 +182,12 @@ Default suggestions:
182
182
  - Critical -> `convert`
183
183
  - Important -> `convert`
184
184
  - Medium -> `convert` (propose `defer` only with concrete rationale)
185
- - Minor -> `convert` when future cleanup is likely or the fix is trivial; otherwise `defer` with concrete rationale
185
+ - Minor -> `convert` (propose `defer` only with concrete rationale)
186
186
 
187
187
  Rules:
188
188
 
189
- - Require explicit rationale for `defer` or `dismiss`.
190
- - Do not recommend `defer` for a Minor finding solely because it does not impact current functionality. If there is a better-than-even chance the team will need to clean it up later, or the fix is `Negligible`/`Minor`, recommend `convert`.
189
+ - Require explicit rationale for `defer` or `dismiss` at any severity, including Minor. Small findings are cheap to fix inline, so deferring a Minor into a backlog item must be justified just like any other deferral.
190
+ - Do not recommend `defer` for a Minor finding solely because it does not impact current functionality fixing inline is usually cheaper than tracking it. Reserve `defer` for the genuine cases (low-probability cleanup, blocked dependency, duplicated elsewhere, explicitly out of scope, or disproportionate churn now).
191
191
  - Do not silently skip findings.
192
192
 
193
193
  ### Step 5: Generate Task List Output
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: oat-review-receive-remote
3
- version: 1.2.0
3
+ version: 1.3.0
4
4
  description: Use when processing GitHub PR review comments outside project context. Fetches PR comments via agent-reviews and converts them into actionable task lists.
5
5
  disable-model-invocation: true
6
6
  user-invocable: true
@@ -145,14 +145,14 @@ Before triage prompts, output:
145
145
 
146
146
  Disposition options per finding:
147
147
 
148
- - `convert` (default for critical/important/medium)
149
- - `defer` (default for minor)
148
+ - `convert` (default for critical/important/medium/minor)
149
+ - `defer`
150
150
  - `dismiss`
151
151
 
152
152
  Rules:
153
153
 
154
- - Require rationale for `defer`/`dismiss`.
155
- - For medium deferral, require concrete rationale (duplicate, dependency, explicit out-of-scope follow-up, risky churn).
154
+ - Require concrete rationale for `defer`/`dismiss` at any severity, including minor. Small findings are usually cheaper to fix inline than to track as backlog items, so a minor `defer` must be justified just like any other deferral.
155
+ - For any deferral (minor included), require a concrete reason (duplicate, dependency, explicit out-of-scope follow-up, risky churn).
156
156
 
157
157
  ### Step 5: Generate Standalone Task List
158
158
 
@@ -11,7 +11,7 @@ export interface PackMetadata {
11
11
  }
12
12
  export declare const PACK_METADATA: Record<string, PackMetadata>;
13
13
  export declare function resolvePackDefaultScope(packName: string): 'user' | 'project';
14
- export declare const WORKFLOW_SKILLS: readonly ["oat-project-capture", "oat-project-clear-active", "oat-project-complete", "oat-project-design", "oat-project-discover", "oat-project-document", "oat-project-implement", "oat-project-import-plan", "oat-project-new", "oat-project-next", "oat-project-open", "oat-project-plan", "oat-project-plan-writing", "oat-project-pr-final", "oat-project-pr-progress", "oat-project-progress", "oat-project-promote-spec-driven", "oat-project-quick-start", "oat-project-reconcile", "oat-project-revise", "oat-project-review-provide", "oat-project-review-receive", "oat-project-review-receive-remote", "oat-project-spec", "oat-project-split", "oat-project-summary", "oat-repo-knowledge-index", "oat-worktree-bootstrap", "oat-worktree-bootstrap-auto", "oat-wrap-up"];
14
+ export declare const WORKFLOW_SKILLS: readonly ["oat-project-capture", "oat-project-clear-active", "oat-project-complete", "oat-project-design", "oat-project-discover", "oat-project-document", "oat-project-implement", "oat-project-import-plan", "oat-project-new", "oat-project-next", "oat-project-open", "oat-project-plan", "oat-project-plan-writing", "oat-project-pr-final", "oat-project-pr-progress", "oat-project-progress", "oat-project-promote-spec-driven", "oat-project-quick-start", "oat-project-reconcile", "oat-project-revise", "oat-project-review-provide", "oat-project-review-provide-remote", "oat-project-review-receive", "oat-project-review-receive-remote", "oat-project-spec", "oat-project-split", "oat-project-summary", "oat-repo-knowledge-index", "oat-worktree-bootstrap", "oat-worktree-bootstrap-auto", "oat-wrap-up"];
15
15
  export declare const WORKFLOW_AGENTS: readonly ["oat-codebase-mapper.md", "oat-phase-implementer.md", "oat-reviewer.md"];
16
16
  export declare const WORKFLOW_TEMPLATES: readonly ["state.md", "discovery.md", "spec.md", "design.md", "plan.md", "implementation.md", "summary.md"];
17
17
  export declare const WORKFLOW_SCRIPTS: readonly ["generate-oat-state.sh", "generate-thin-index.sh", "resolve-tracking.sh"];
@@ -19,7 +19,7 @@ export declare const IDEA_SKILLS: readonly ["oat-idea-new", "oat-idea-ideate", "
19
19
  export declare const CORE_SKILLS: readonly ["oat-docs", "oat-doctor"];
20
20
  export declare const DOCS_SKILLS: readonly ["oat-agent-instructions-analyze", "oat-agent-instructions-apply", "oat-docs-analyze", "oat-docs-apply", "oat-docs-bootstrap"];
21
21
  export declare const DOCS_SCRIPTS: readonly ["resolve-tracking.sh"];
22
- export declare const UTILITY_SKILLS: readonly ["create-agnostic-skill", "oat-repo-maintainability-review", "oat-review-provide", "oat-review-receive", "oat-review-receive-remote"];
22
+ export declare const UTILITY_SKILLS: readonly ["create-agnostic-skill", "oat-repo-maintainability-review", "oat-review-provide", "oat-review-provide-remote", "oat-review-receive", "oat-review-receive-remote"];
23
23
  export declare const PROJECT_MANAGEMENT_SKILLS: readonly ["oat-pjm-add-backlog-item", "oat-pjm-update-repo-reference", "oat-pjm-review-backlog"];
24
24
  export declare const PROJECT_MANAGEMENT_TEMPLATES: readonly ["backlog-item.md", "roadmap.md"];
25
25
  export declare const PROJECT_MANAGEMENT_SCRIPTS: readonly [];
@@ -1 +1 @@
1
- {"version":3,"file":"skill-manifest.d.ts","sourceRoot":"","sources":["../../../../../src/commands/init/tools/shared/skill-manifest.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAgBH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;CAClC;AAED,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAKtD,CAAC;AAEF,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAE5E;AAID,eAAO,MAAM,eAAe,wvBA+BlB,CAAC;AAEX,eAAO,MAAM,eAAe,oFAIlB,CAAC;AAEX,eAAO,MAAM,kBAAkB,6GAQrB,CAAC;AAEX,eAAO,MAAM,gBAAgB,qFAInB,CAAC;AAIX,eAAO,MAAM,WAAW,2FAKd,CAAC;AAIX,eAAO,MAAM,WAAW,qCAAsC,CAAC;AAI/D,eAAO,MAAM,WAAW,yIAMd,CAAC;AAEX,eAAO,MAAM,YAAY,kCAAmC,CAAC;AAI7D,eAAO,MAAM,cAAc,gJAMjB,CAAC;AAIX,eAAO,MAAM,yBAAyB,kGAI5B,CAAC;AAEX,eAAO,MAAM,4BAA4B,4CAG/B,CAAC;AAEX,eAAO,MAAM,0BAA0B,aAAc,CAAC;AAItD,eAAO,MAAM,iBAAiB,6BAA8B,CAAC;AAI7D,eAAO,MAAM,eAAe,2EAMlB,CAAC;AAEX,eAAO,MAAM,eAAe,qCAAsC,CAAC"}
1
+ {"version":3,"file":"skill-manifest.d.ts","sourceRoot":"","sources":["../../../../../src/commands/init/tools/shared/skill-manifest.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAgBH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;CAClC;AAED,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAKtD,CAAC;AAEF,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAE5E;AAID,eAAO,MAAM,eAAe,6xBAgClB,CAAC;AAEX,eAAO,MAAM,eAAe,oFAIlB,CAAC;AAEX,eAAO,MAAM,kBAAkB,6GAQrB,CAAC;AAEX,eAAO,MAAM,gBAAgB,qFAInB,CAAC;AAIX,eAAO,MAAM,WAAW,2FAKd,CAAC;AAIX,eAAO,MAAM,WAAW,qCAAsC,CAAC;AAI/D,eAAO,MAAM,WAAW,yIAMd,CAAC;AAEX,eAAO,MAAM,YAAY,kCAAmC,CAAC;AAI7D,eAAO,MAAM,cAAc,6KAOjB,CAAC;AAIX,eAAO,MAAM,yBAAyB,kGAI5B,CAAC;AAEX,eAAO,MAAM,4BAA4B,4CAG/B,CAAC;AAEX,eAAO,MAAM,0BAA0B,aAAc,CAAC;AAItD,eAAO,MAAM,iBAAiB,6BAA8B,CAAC;AAI7D,eAAO,MAAM,eAAe,2EAMlB,CAAC;AAEX,eAAO,MAAM,eAAe,qCAAsC,CAAC"}
@@ -37,6 +37,7 @@ export const WORKFLOW_SKILLS = [
37
37
  'oat-project-reconcile',
38
38
  'oat-project-revise',
39
39
  'oat-project-review-provide',
40
+ 'oat-project-review-provide-remote',
40
41
  'oat-project-review-receive',
41
42
  'oat-project-review-receive-remote',
42
43
  'oat-project-spec',
@@ -89,6 +90,7 @@ export const UTILITY_SKILLS = [
89
90
  'create-agnostic-skill',
90
91
  'oat-repo-maintainability-review',
91
92
  'oat-review-provide',
93
+ 'oat-review-provide-remote',
92
94
  'oat-review-receive',
93
95
  'oat-review-receive-remote',
94
96
  ];
@@ -0,0 +1,2 @@
1
+ export declare function parseJsonConfig(raw: string, configPath: string): unknown;
2
+ //# sourceMappingURL=json.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json.d.ts","sourceRoot":"","sources":["../../src/config/json.ts"],"names":[],"mappings":"AAYA,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAcxE"}
@@ -0,0 +1,29 @@
1
+ import { parse as parseJsonc, printParseErrorCode, } from 'jsonc-parser';
2
+ const JSON_CONFIG_PARSE_OPTIONS = {
3
+ allowTrailingComma: true,
4
+ disallowComments: true,
5
+ };
6
+ export function parseJsonConfig(raw, configPath) {
7
+ const errors = [];
8
+ const parsed = parseJsonc(raw, errors, JSON_CONFIG_PARSE_OPTIONS);
9
+ if (errors.length > 0) {
10
+ const details = errors
11
+ .map((error) => formatParseError(raw, error))
12
+ .join('; ');
13
+ throw new SyntaxError(`Config at ${configPath} is not valid JSON: ${details}`);
14
+ }
15
+ return parsed;
16
+ }
17
+ function formatParseError(raw, error) {
18
+ const location = offsetToLineColumn(raw, error.offset);
19
+ return `${printParseErrorCode(error.error)} at ${location.line}:${location.column}`;
20
+ }
21
+ function offsetToLineColumn(raw, offset) {
22
+ const prefix = raw.slice(0, offset);
23
+ const lines = prefix.split('\n');
24
+ const lastLine = lines[lines.length - 1] ?? '';
25
+ return {
26
+ line: lines.length,
27
+ column: lastLine.length + 1,
28
+ };
29
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"oat-config.d.ts","sourceRoot":"","sources":["../../src/config/oat-config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"oat-config.d.ts","sourceRoot":"","sources":["../../src/config/oat-config.ts"],"names":[],"mappings":"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"}
@@ -3,6 +3,7 @@ import { readFile } from 'node:fs/promises';
3
3
  import { basename, isAbsolute, join, relative, resolve, sep } from 'node:path';
4
4
  import { atomicWriteJson, dirExists, fileExists } from '../fs/io.js';
5
5
  import { normalizeToPosixPath } from '../fs/paths.js';
6
+ import { parseJsonConfig } from './json.js';
6
7
  const VALID_HILL_CHECKPOINT_DEFAULTS = ['every', 'final'];
7
8
  const VALID_POST_IMPLEMENT_SEQUENCES = ['wait', 'summary', 'pr', 'docs-pr'];
8
9
  const VALID_REVIEW_EXECUTION_MODELS = [
@@ -291,7 +292,7 @@ export async function readOatConfig(repoRoot) {
291
292
  const configPath = getConfigPath(repoRoot);
292
293
  try {
293
294
  const raw = await readFile(configPath, 'utf8');
294
- return normalizeOatConfig(JSON.parse(raw));
295
+ return normalizeOatConfig(parseJsonConfig(raw, configPath));
295
296
  }
296
297
  catch (error) {
297
298
  if (isMissingFileError(error)) {
@@ -304,7 +305,7 @@ export async function readOatLocalConfig(repoRoot) {
304
305
  const configPath = getLocalConfigPath(repoRoot);
305
306
  try {
306
307
  const raw = await readFile(configPath, 'utf8');
307
- return normalizeOatLocalConfig(repoRoot, JSON.parse(raw));
308
+ return normalizeOatLocalConfig(repoRoot, parseJsonConfig(raw, configPath));
308
309
  }
309
310
  catch (error) {
310
311
  if (isMissingFileError(error)) {
@@ -384,7 +385,7 @@ export async function readUserConfig(userConfigDir) {
384
385
  const configPath = getUserConfigPath(userConfigDir);
385
386
  try {
386
387
  const raw = await readFile(configPath, 'utf8');
387
- return normalizeUserConfig(JSON.parse(raw));
388
+ return normalizeUserConfig(parseJsonConfig(raw, configPath));
388
389
  }
389
390
  catch (error) {
390
391
  if (isMissingFileError(error)) {
@@ -1 +1 @@
1
- {"version":3,"file":"sync-config.d.ts","sourceRoot":"","sources":["../../src/config/sync-config.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,QAAA,MAAM,oBAAoB;;;;;;;;;EAGxB,CAAC;AAEH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;EAI3B,CAAC;AAEH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAEtE,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,GAAG;IAC1D,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;CAC/C,CAAC;AAEF,eAAO,MAAM,mBAAmB,EAAE,UAIjC,CAAC;AAoDF,wBAAsB,cAAc,CAClC,UAAU,EAAE,MAAM,EAClB,QAAQ,GAAE,UAAgC,GACzC,OAAO,CAAC,UAAU,CAAC,CA4BrB;AAED,wBAAsB,cAAc,CAClC,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,UAAU,GACjB,OAAO,CAAC,UAAU,CAAC,CAWrB;AAED,wBAAsB,kBAAkB,CACtC,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,OAAO,GACf,OAAO,CAAC,UAAU,CAAC,CAcrB"}
1
+ {"version":3,"file":"sync-config.d.ts","sourceRoot":"","sources":["../../src/config/sync-config.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,QAAA,MAAM,oBAAoB;;;;;;;;;EAGxB,CAAC;AAEH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;EAI3B,CAAC;AAEH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAEtE,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,GAAG;IAC1D,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;CAC/C,CAAC;AAEF,eAAO,MAAM,mBAAmB,EAAE,UAIjC,CAAC;AAoDF,wBAAsB,cAAc,CAClC,UAAU,EAAE,MAAM,EAClB,QAAQ,GAAE,UAAgC,GACzC,OAAO,CAAC,UAAU,CAAC,CA4BrB;AAED,wBAAsB,cAAc,CAClC,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,UAAU,GACjB,OAAO,CAAC,UAAU,CAAC,CAWrB;AAED,wBAAsB,kBAAkB,CACtC,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,OAAO,GACf,OAAO,CAAC,UAAU,CAAC,CAcrB"}
@@ -3,6 +3,7 @@ import { CliError } from '../errors/index.js';
3
3
  import { atomicWriteJson } from '../fs/io.js';
4
4
  import { SyncStrategySchema } from '../shared/types.js';
5
5
  import { z } from 'zod';
6
+ import { parseJsonConfig } from './json.js';
6
7
  const ProviderConfigSchema = z.object({
7
8
  strategy: SyncStrategySchema.optional(),
8
9
  enabled: z.boolean().optional(),
@@ -37,7 +38,7 @@ function normalizeConfig(config, defaults) {
37
38
  function parseSyncConfig(raw, configPath) {
38
39
  let parsed;
39
40
  try {
40
- parsed = JSON.parse(raw);
41
+ parsed = parseJsonConfig(raw, configPath);
41
42
  }
42
43
  catch {
43
44
  throw new CliError(`Sync config at ${configPath} is not valid JSON. Fix the file and retry.`);
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Builder for the posted-review-body (see design.md → Data Models →
3
+ * Posted-review-body) and the verdict mapper that decides the GitHub review
4
+ * `event`.
5
+ *
6
+ * The body is the durable handoff to `*-receive-remote`: a leading
7
+ * HTML-comment marker block (parsed back by {@link parseMarkerBlock}) followed
8
+ * by human-readable prose (summary, severity counts, optional minor-fix nudge,
9
+ * optional verification commands).
10
+ */
11
+ import { type ReviewInvocation } from './marker-parser.js';
12
+ export type ReviewVerdict = 'REQUEST_CHANGES' | 'COMMENT';
13
+ export type FindingSeverity = 'critical' | 'important' | 'medium' | 'minor';
14
+ /** Minimal finding shape the builder needs — only severity is required. */
15
+ export interface BuilderFinding {
16
+ severity: FindingSeverity;
17
+ }
18
+ /**
19
+ * A finding whose `file:line` is NOT present in the PR diff and therefore
20
+ * cannot be posted as a GitHub inline comment (see design.md → Error Handling →
21
+ * Inline-comment line mapping). Such findings must NOT be dropped — they are
22
+ * downgraded into the top-level body via a "Findings outside the PR diff"
23
+ * subsection carrying the original `file:line` reference and finding body.
24
+ *
25
+ * Field names mirror the `StructuredFindings` finding shape (design.md → Data
26
+ * Models → StructuredFindings) so callers can pass entries through unchanged;
27
+ * `line` is `number | null` because a reviewer-level finding may be file-scoped
28
+ * with no specific line.
29
+ */
30
+ export interface OutOfDiffFinding {
31
+ /** Repo-relative path the original finding referenced. */
32
+ file: string;
33
+ /** 1-based line the original finding referenced, or `null` if file-scoped. */
34
+ line: number | null;
35
+ severity: FindingSeverity;
36
+ /** Optional short title carried from the structured finding. */
37
+ title?: string;
38
+ /** Finding description / rationale — preserved verbatim, never dropped. */
39
+ body: string;
40
+ }
41
+ export interface BuildInput {
42
+ /** Full 40-char hex SHA of the reviewed PR HEAD. */
43
+ headSha: string;
44
+ /** Scope token (`pNN`, `final`, …) or the `ad-hoc` sentinel. */
45
+ scope: string;
46
+ /** Project path — set only on the project rail; omitted on ad-hoc. */
47
+ project?: string;
48
+ /** How the review was invoked. */
49
+ invocation: ReviewInvocation;
50
+ /** 2-3 sentence human-readable summary. */
51
+ summary: string;
52
+ findings: BuilderFinding[];
53
+ /**
54
+ * Findings whose `file:line` is not in the PR diff, downgraded into the body
55
+ * instead of posted inline. Omitted/empty renders no subsection (the body is
56
+ * byte-identical to a build without the field).
57
+ *
58
+ * Count contract: these findings MUST also appear in {@link BuildInput.findings}
59
+ * so the severity counts stay complete. This field only drives body rendering
60
+ * — the builder never re-derives severity counts from it.
61
+ */
62
+ outOfDiffFindings?: OutOfDiffFinding[];
63
+ /** Commands the user can run to verify fixes; omitted when absent/empty. */
64
+ verificationCommands?: string[];
65
+ }
66
+ /**
67
+ * Map a finding set to the GitHub review verdict: `REQUEST_CHANGES` when any
68
+ * critical or important finding is present, otherwise `COMMENT` (including the
69
+ * zero-findings clean-review case). Never auto-`APPROVE`.
70
+ */
71
+ export declare function mapVerdict(findings: BuilderFinding[]): ReviewVerdict;
72
+ /**
73
+ * Build the posted-review body and compute its verdict.
74
+ */
75
+ export declare function buildReviewBody(input: BuildInput): {
76
+ body: string;
77
+ verdict: ReviewVerdict;
78
+ };
79
+ //# sourceMappingURL=body-builder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"body-builder.d.ts","sourceRoot":"","sources":["../../src/review-remote/body-builder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAqB,KAAK,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAE3E,MAAM,MAAM,aAAa,GAAG,iBAAiB,GAAG,SAAS,CAAC;AAE1D,MAAM,MAAM,eAAe,GAAG,UAAU,GAAG,WAAW,GAAG,QAAQ,GAAG,OAAO,CAAC;AAE5E,2EAA2E;AAC3E,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,eAAe,CAAC;CAC3B;AAED;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,gBAAgB;IAC/B,0DAA0D;IAC1D,IAAI,EAAE,MAAM,CAAC;IACb,8EAA8E;IAC9E,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,QAAQ,EAAE,eAAe,CAAC;IAC1B,gEAAgE;IAChE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2EAA2E;IAC3E,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,UAAU;IACzB,oDAAoD;IACpD,OAAO,EAAE,MAAM,CAAC;IAChB,gEAAgE;IAChE,KAAK,EAAE,MAAM,CAAC;IACd,sEAAsE;IACtE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,kCAAkC;IAClC,UAAU,EAAE,gBAAgB,CAAC;IAC7B,2CAA2C;IAC3C,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,cAAc,EAAE,CAAC;IAC3B;;;;;;;;OAQG;IACH,iBAAiB,CAAC,EAAE,gBAAgB,EAAE,CAAC;IACvC,4EAA4E;IAC5E,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;CACjC;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,QAAQ,EAAE,cAAc,EAAE,GAAG,aAAa,CAKpE;AAkED;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,UAAU,GAAG;IAClD,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,aAAa,CAAC;CACxB,CAkCA"}