@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.
- package/assets/agents/oat-reviewer.md +54 -10
- package/assets/docs/workflows/projects/reviews.md +21 -2
- package/assets/docs/workflows/skills/index.md +2 -0
- package/assets/public-package-versions.json +4 -4
- package/assets/skills/oat-project-review-provide-remote/SKILL.md +354 -0
- package/assets/skills/oat-project-review-receive/SKILL.md +7 -10
- package/assets/skills/oat-project-review-receive-remote/SKILL.md +4 -4
- package/assets/skills/oat-review-provide-remote/SKILL.md +273 -0
- package/assets/skills/oat-review-receive/SKILL.md +6 -6
- package/assets/skills/oat-review-receive-remote/SKILL.md +5 -5
- package/dist/commands/init/tools/shared/skill-manifest.d.ts +2 -2
- package/dist/commands/init/tools/shared/skill-manifest.d.ts.map +1 -1
- package/dist/commands/init/tools/shared/skill-manifest.js +2 -0
- package/dist/config/json.d.ts +2 -0
- package/dist/config/json.d.ts.map +1 -0
- package/dist/config/json.js +29 -0
- package/dist/config/oat-config.d.ts.map +1 -1
- package/dist/config/oat-config.js +4 -3
- package/dist/config/sync-config.d.ts.map +1 -1
- package/dist/config/sync-config.js +2 -1
- package/dist/review-remote/body-builder.d.ts +79 -0
- package/dist/review-remote/body-builder.d.ts.map +1 -0
- package/dist/review-remote/body-builder.js +103 -0
- package/dist/review-remote/capability-probe.d.ts +61 -0
- package/dist/review-remote/capability-probe.d.ts.map +1 -0
- package/dist/review-remote/capability-probe.js +87 -0
- package/dist/review-remote/line-mapper.d.ts +81 -0
- package/dist/review-remote/line-mapper.d.ts.map +1 -0
- package/dist/review-remote/line-mapper.js +165 -0
- package/dist/review-remote/marker-parser.d.ts +44 -0
- package/dist/review-remote/marker-parser.d.ts.map +1 -0
- package/dist/review-remote/marker-parser.js +97 -0
- package/dist/review-remote/narrowing.d.ts +81 -0
- package/dist/review-remote/narrowing.d.ts.map +1 -0
- package/dist/review-remote/narrowing.js +90 -0
- package/dist/review-remote/project-resolver.d.ts +46 -0
- package/dist/review-remote/project-resolver.d.ts.map +1 -0
- package/dist/review-remote/project-resolver.js +60 -0
- package/dist/review-remote/reviewer-dispatch.d.ts +108 -0
- package/dist/review-remote/reviewer-dispatch.d.ts.map +1 -0
- package/dist/review-remote/reviewer-dispatch.js +153 -0
- package/dist/review-remote/worktree.d.ts +62 -0
- package/dist/review-remote/worktree.d.ts.map +1 -0
- package/dist/review-remote/worktree.js +117 -0
- package/package.json +3 -2
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: oat-project-review-receive-remote
|
|
3
|
-
version: 1.
|
|
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`
|
|
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
|
+
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
|
|
45
|
-
-
|
|
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`
|
|
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
|
|
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.
|
|
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`
|
|
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
|
|
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,
|
|
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 @@
|
|
|
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":"
|
|
1
|
+
{"version":3,"file":"oat-config.d.ts","sourceRoot":"","sources":["../../src/config/oat-config.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,sBAAsB;IACrC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2BAA2B,CAAC,EAAE,OAAO,CAAC;CACvC;AAED,MAAM,WAAW,YAAY;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,MAAM,6BAA6B,GAAG,OAAO,GAAG,OAAO,CAAC;AAC9D,MAAM,MAAM,6BAA6B,GACrC,MAAM,GACN,SAAS,GACT,IAAI,GACJ,SAAS,CAAC;AACd,MAAM,MAAM,4BAA4B,GACpC,UAAU,GACV,QAAQ,GACR,eAAe,CAAC;AACpB,MAAM,MAAM,kBAAkB,GAAG,eAAe,GAAG,WAAW,GAAG,OAAO,CAAC;AACzE,MAAM,MAAM,4BAA4B,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;AAC/E,MAAM,MAAM,6BAA6B,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;AACxE,MAAM,MAAM,6BAA6B,GACrC,UAAU,GACV,SAAS,GACT,gBAAgB,CAAC;AAErB,MAAM,WAAW,uBAAuB;IACtC,MAAM,CAAC,EAAE,6BAA6B,CAAC;IACvC,SAAS,CAAC,EAAE;QACV,KAAK,CAAC,EAAE,4BAA4B,CAAC;QACrC,MAAM,CAAC,EAAE,6BAA6B,CAAC;KACxC,CAAC;CACH;AAED,MAAM,WAAW,iBAAiB;IAChC,qBAAqB,CAAC,EAAE,6BAA6B,CAAC;IACtD,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,qBAAqB,CAAC,EAAE,6BAA6B,CAAC;IACtD,oBAAoB,CAAC,EAAE,4BAA4B,CAAC;IACpD,2BAA2B,CAAC,EAAE,OAAO,CAAC;IACtC,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,UAAU,CAAC,EAAE,kBAAkB,CAAC;IAChC,eAAe,CAAC,EAAE,uBAAuB,CAAC;CAC3C;AAgBD,eAAO,MAAM,6BAA6B,EAAE,SAAS,4BAA4B,EAC7C,CAAC;AACrC,eAAO,MAAM,8BAA8B,EAAE,SAAS,6BAA6B,EACtD,CAAC;AAC9B,eAAO,MAAM,8BAA8B,EAAE,SAAS,6BAA6B,EACxC,CAAC;AA8G5C,MAAM,MAAM,cAAc,GAAG,OAAO,CAClC,MAAM,CACF,MAAM,GACN,OAAO,GACP,MAAM,GACN,WAAW,GACX,SAAS,GACT,oBAAoB,GACpB,UAAU,GACV,YAAY,EACd,OAAO,CACR,CACF,CAAC;AAEF,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7B,QAAQ,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5B,GAAG,CAAC,EAAE,YAAY,CAAC;IACnB,OAAO,CAAC,EAAE,gBAAgB,CAAC;IAC3B,KAAK,CAAC,EAAE,cAAc,CAAC;IACvB,aAAa,CAAC,EAAE,sBAAsB,CAAC;IACvC,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,QAAQ,CAAC,EAAE,iBAAiB,CAAC;CAC9B;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,QAAQ,CAAC,EAAE,iBAAiB,CAAC;CAC9B;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,QAAQ,CAAC,EAAE,iBAAiB,CAAC;CAC9B;AAED,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,MAAM,EAAE,QAAQ,GAAG,SAAS,GAAG,OAAO,CAAC;CACxC;AAkRD,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,EAAE,CAE7D;AAED,wBAAsB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAaxE;AAED,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,cAAc,CAAC,CAazB;AAED,wBAAsB,cAAc,CAClC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,SAAS,GAChB,OAAO,CAAC,IAAI,CAAC,CAIf;AAED,wBAAsB,mBAAmB,CACvC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,cAAc,GACrB,OAAO,CAAC,IAAI,CAAC,CAIf;AAED,wBAAsB,oBAAoB,CACxC,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,uBAAuB,CAAC,CAkBlC;AAED,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,MAAM,EAChB,mBAAmB,EAAE,MAAM,GAC1B,OAAO,CAAC,IAAI,CAAC,CAaf;AAED,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,GAChC,OAAO,CAAC,IAAI,CAAC,CAYf;AA2BD,wBAAsB,cAAc,CAClC,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,UAAU,CAAC,CAarB;AAED,wBAAsB,eAAe,CACnC,aAAa,EAAE,MAAM,EACrB,MAAM,EAAE,UAAU,GACjB,OAAO,CAAC,IAAI,CAAC,CAIf;AAED,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAQxB;AAED,wBAAsB,aAAa,CACjC,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAMf;AAED,wBAAsB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAMrE;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CA6B5D"}
|
|
@@ -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(
|
|
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,
|
|
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(
|
|
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;
|
|
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 =
|
|
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"}
|