mandrel 2.8.0 → 2.10.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/.agents/agents/.markdownlint.json +4 -0
- package/.agents/agents/acceptance-critic.md +30 -5
- package/.agents/agents/auditor.md +36 -19
- package/.agents/agents/plan-critic.md +31 -5
- package/.agents/agents/story-worker.md +91 -100
- package/.agents/docs/configuration.md +39 -1
- package/.agents/docs/execution-reference.md +13 -0
- package/.agents/docs/workflows.md +1 -1
- package/.agents/instructions.md +131 -265
- package/.agents/rules/git-conventions.md +47 -83
- package/.agents/rules/orchestration-error-handling.md +28 -0
- package/.agents/schemas/agentrc.schema.json +44 -1
- package/.agents/schemas/validation-evidence.schema.json +3 -1
- package/.agents/scripts/acceptance-eval.js +1 -1
- package/.agents/scripts/apply-quality-bootstrap.js +1 -1
- package/.agents/scripts/audit-to-stories.js +51 -0
- package/.agents/scripts/check-test-temp-hygiene.js +438 -0
- package/.agents/scripts/deliver-recover.js +23 -6
- package/.agents/scripts/lib/audit-suite/index.js +5 -0
- package/.agents/scripts/lib/audit-suite/lens-diff-floor.js +179 -0
- package/.agents/scripts/lib/audit-suite/selector.js +1 -1
- package/.agents/scripts/lib/audit-to-stories/dedupe-against-github.js +120 -55
- package/.agents/scripts/lib/config/temp-paths.js +121 -1
- package/.agents/scripts/lib/config-settings-schema-delivery.js +30 -0
- package/.agents/scripts/lib/config-settings-schema.js +32 -0
- package/.agents/scripts/lib/findings/semantic-issue-search.js +43 -5
- package/.agents/scripts/lib/observability/metrics-ledger.js +217 -0
- package/.agents/scripts/lib/observability/runtime-friction.js +7 -0
- package/.agents/scripts/lib/observability/terse-result.js +114 -0
- package/.agents/scripts/lib/orchestration/complexity-gate.js +318 -0
- package/.agents/scripts/lib/orchestration/deliver-recover.js +137 -10
- package/.agents/scripts/lib/orchestration/merge-block-class.js +36 -15
- package/.agents/scripts/lib/orchestration/merge-poll.js +213 -0
- package/.agents/scripts/lib/orchestration/plan-context.js +60 -0
- package/.agents/scripts/lib/orchestration/plan-critic-conditions.js +182 -9
- package/.agents/scripts/lib/orchestration/plan-critics-evaluate.js +29 -2
- package/.agents/scripts/lib/orchestration/plan-metrics.js +31 -82
- package/.agents/scripts/lib/orchestration/plan-persist/run-plan-persist.js +102 -2
- package/.agents/scripts/lib/orchestration/plan-persist/story-ops.js +215 -14
- package/.agents/scripts/lib/orchestration/resolve-stories.js +7 -0
- package/.agents/scripts/lib/orchestration/review-providers/native.js +34 -16
- package/.agents/scripts/lib/orchestration/single-story-close/phases/auto-merge.js +221 -8
- package/.agents/scripts/lib/orchestration/single-story-close/phases/code-review.js +8 -3
- package/.agents/scripts/lib/orchestration/single-story-close/phases/confirm-merge.js +230 -79
- package/.agents/scripts/lib/orchestration/single-story-close/runner.js +55 -14
- package/.agents/scripts/lib/orchestration/story-close/emit-blocked.js +9 -3
- package/.agents/scripts/lib/orchestration/story-close/phases/local-lens-review.js +89 -1
- package/.agents/scripts/lib/orchestration/story-close/phases/review-core.js +73 -0
- package/.agents/scripts/lib/orchestration/story-deliver-terminal.js +4 -1
- package/.agents/scripts/lib/orchestration/task-body-validator.js +13 -40
- package/.agents/scripts/lib/story-body/body-format-lints.js +215 -0
- package/.agents/scripts/lib/story-body/story-body.js +18 -2
- package/.agents/scripts/lib/templates/decomposer-prompts.js +29 -6
- package/.agents/scripts/lib/test-env.js +65 -0
- package/.agents/scripts/plan-context.js +66 -9
- package/.agents/scripts/plan-critics.js +115 -3
- package/.agents/scripts/plan-persist.js +11 -1
- package/.agents/scripts/plan-run-epilogue.js +1 -1
- package/.agents/scripts/providers/github/issues.js +54 -7
- package/.agents/scripts/providers/github/search-budget.js +124 -0
- package/.agents/scripts/providers/github/search-query.js +71 -0
- package/.agents/scripts/single-story-confirm-merge.js +79 -10
- package/.agents/scripts/single-story-init.js +19 -3
- package/.agents/scripts/stories-wave-tick.js +1 -1
- package/.agents/scripts/sync-branch-from-base.js +9 -3
- package/.agents/workflows/deliver.md +86 -230
- package/.agents/workflows/helpers/deliver-reference.md +167 -0
- package/.agents/workflows/helpers/deliver-story-reference.md +203 -0
- package/.agents/workflows/helpers/deliver-story.md +114 -422
- package/.agents/workflows/helpers/plan-reference.md +211 -0
- package/.agents/workflows/plan.md +107 -279
- package/docs/CHANGELOG.md +47 -0
- package/package.json +1 -1
|
@@ -23,6 +23,42 @@
|
|
|
23
23
|
* no-op. `--delete-branch` is preserved verbatim, so the PR head branch is
|
|
24
24
|
* still deleted on merge without depending on the repo's auto-delete
|
|
25
25
|
* setting. Resolution is non-fatal — it degrades to the original cwd.
|
|
26
|
+
*
|
|
27
|
+
* Story #4681 made the arm survive a LOCAL-ONLY cleanup failure. Against an
|
|
28
|
+
* already-mergeable PR, `gh pr merge --auto --squash --delete-branch` merges
|
|
29
|
+
* immediately and then shells out to local `git` to drop the head branch.
|
|
30
|
+
* When the per-Story worktree still holds `story-<id>`, that local delete
|
|
31
|
+
* fails (`Cannot delete branch 'story-<id>' used by worktree at …`) and `gh`
|
|
32
|
+
* exits non-zero — even though the REMOTE merge already landed. Reporting
|
|
33
|
+
* that as an arm failure sent close's confirm phase straight to
|
|
34
|
+
* `blockOnUnlanded`, flipping a merged Story to a stale `agent::blocked` that
|
|
35
|
+
* only a hand-run `single-story-confirm-merge.js` could undo. The failure is
|
|
36
|
+
* now classified: a local-cleanup-only signature reports the arm as ENABLED
|
|
37
|
+
* with `localCleanupDeferred: true`, so the confirm phase polls the PR
|
|
38
|
+
* (observes MERGED) and the post-land tail reaps the local ref. Every other
|
|
39
|
+
* non-zero exit — a genuinely refused REMOTE merge — keeps the pre-existing
|
|
40
|
+
* `enabled: false` → blocked behaviour verbatim.
|
|
41
|
+
*
|
|
42
|
+
* Story #4682 restored the direct-merge fallback the v2.0.0 Story-only cutover
|
|
43
|
+
* dropped (originally PR #4480 / Story #4472, in the retired `AutomergeArmer`).
|
|
44
|
+
* GitHub native auto-merge (`gh pr merge --auto`) can only be QUEUED on a repo
|
|
45
|
+
* that has the "Allow auto-merge" setting enabled — which in practice requires
|
|
46
|
+
* branch protection. A repo with NO required checks and NO branch protection
|
|
47
|
+
* (every mandrel-bench sandbox, many real consumer repos) refuses the `--auto`
|
|
48
|
+
* arm: either "auto-merge is not allowed for this repository", or — once the
|
|
49
|
+
* PR has settled to an immediately-mergeable state, which the SECOND delivery
|
|
50
|
+
* into a warm repo reaches faster than the first into a cold one — the
|
|
51
|
+
* `enablePullRequestAutoMerge` "Pull request is in clean status" refusal. The
|
|
52
|
+
* close gates and Story-scope review have already cleared the merge by the
|
|
53
|
+
* time the arm runs, so the safe, must-land-satisfying response is a direct
|
|
54
|
+
* immediate squash-merge (no `--auto`). When the `--auto` failure matches the
|
|
55
|
+
* narrow {@link isAutoMergeUnavailable} signature, `enableAutoMergeWith`
|
|
56
|
+
* retries `gh pr merge --squash --delete-branch` and reports
|
|
57
|
+
* `{ enabled: true, directMerged: true }` on success — so the confirm phase
|
|
58
|
+
* polls the PR, observes MERGED, and lands it instead of blocking a PR that
|
|
59
|
+
* would never merge on its own. Every OTHER `--auto` failure — a genuine
|
|
60
|
+
* conflict, a red required check, an auth fault — matches neither the
|
|
61
|
+
* local-cleanup nor the unavailable signature and keeps blocking verbatim.
|
|
26
62
|
*/
|
|
27
63
|
|
|
28
64
|
import { gh as defaultGh } from '../../../gh-exec.js';
|
|
@@ -52,6 +88,123 @@ export function isOperatorMergeReason(reason) {
|
|
|
52
88
|
return OPERATOR_MERGE_ARM_REASONS.includes(reason);
|
|
53
89
|
}
|
|
54
90
|
|
|
91
|
+
/**
|
|
92
|
+
* Signatures of a `gh pr merge --delete-branch` failure whose ONLY casualty
|
|
93
|
+
* is the LOCAL head-branch cleanup that runs *after* the remote merge has
|
|
94
|
+
* already been performed (or auto-merge already armed).
|
|
95
|
+
*
|
|
96
|
+
* Each pattern is emitted by local `git` (or `gh`'s wrapper around it) and
|
|
97
|
+
* names branch DELETION specifically:
|
|
98
|
+
* - `Cannot delete branch '<name>' used by worktree at …` — `git branch -D`
|
|
99
|
+
* refusing a ref another worktree has checked out (the Story #4681 report).
|
|
100
|
+
* - `failed to delete local branch …` — `gh`'s own wrapper wording.
|
|
101
|
+
*
|
|
102
|
+
* Deliberately narrow on two fronts. A genuinely refused REMOTE merge ("Pull
|
|
103
|
+
* request is not mergeable", a required status check, branch protection)
|
|
104
|
+
* matches neither pattern and keeps the existing blocked path. Nor does the
|
|
105
|
+
* bare `fatal: '<base>' is already used by worktree` checkout collision Story
|
|
106
|
+
* #4282 defends against: that one aborts `gh` *before* the branch delete and
|
|
107
|
+
* carries no evidence the merge stands, so it must keep failing the arm.
|
|
108
|
+
*/
|
|
109
|
+
const LOCAL_CLEANUP_FAILURE =
|
|
110
|
+
/cannot delete branch[^\n]*used by worktree|failed to delete (?:the )?local branch/i;
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Whether a non-zero `gh pr merge` exit is attributable solely to local
|
|
114
|
+
* branch cleanup, leaving the remote merge/arm itself intact.
|
|
115
|
+
*
|
|
116
|
+
* Module-private on purpose: `enableAutoMergeWith` is the only caller and the
|
|
117
|
+
* only surface worth pinning, so the classification is asserted through it
|
|
118
|
+
* rather than through a test-only export.
|
|
119
|
+
*
|
|
120
|
+
* @param {string|undefined|null} stderr
|
|
121
|
+
* @returns {boolean}
|
|
122
|
+
*/
|
|
123
|
+
function isLocalCleanupOnlyFailure(stderr) {
|
|
124
|
+
return LOCAL_CLEANUP_FAILURE.test(String(stderr ?? ''));
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Pure: does a `gh pr merge --auto` stderr indicate that GitHub native
|
|
129
|
+
* auto-merge is UNAVAILABLE on this repository / PR — as opposed to a genuine
|
|
130
|
+
* arm failure (a merge conflict, a red required check, an auth fault)?
|
|
131
|
+
*
|
|
132
|
+
* Two distinct refusals both mean "there is no queued auto-merge for this repo,
|
|
133
|
+
* merge it directly instead", and both are safe to retry as an immediate
|
|
134
|
+
* squash-merge:
|
|
135
|
+
*
|
|
136
|
+
* - **"auto-merge is not allowed for this repository"** — the repo has no
|
|
137
|
+
* "Allow auto-merge" setting (no branch protection). Constant per repo.
|
|
138
|
+
* - **"Pull request is in clean status"** — the `enablePullRequestAutoMerge`
|
|
139
|
+
* GraphQL mutation refuses to queue a merge on a PR that is ALREADY
|
|
140
|
+
* immediately mergeable with nothing to wait for (no required checks
|
|
141
|
+
* pending). This is the second-delivery wedge (Story #4682): the first
|
|
142
|
+
* delivery into a cold sandbox arms while GitHub is still computing the
|
|
143
|
+
* fresh PR's mergeability (the arm queues, then merges); the second
|
|
144
|
+
* delivery into the now-warm repo hits an instantly-clean PR, so the arm
|
|
145
|
+
* is refused here.
|
|
146
|
+
*
|
|
147
|
+
* Only these classes fall through to the direct-merge fallback; everything
|
|
148
|
+
* else (an unmatched non-zero exit) keeps the `enabled: false` → blocked path.
|
|
149
|
+
* Matched case-insensitively.
|
|
150
|
+
*
|
|
151
|
+
* Module-private on purpose (mirroring {@link isLocalCleanupOnlyFailure}):
|
|
152
|
+
* `enableAutoMergeWith` is the only caller, so the marker set is asserted
|
|
153
|
+
* through it rather than through a test-only export the production dead-export
|
|
154
|
+
* ratchet would then flag.
|
|
155
|
+
*
|
|
156
|
+
* @param {string|undefined|null} stderr
|
|
157
|
+
* @returns {boolean}
|
|
158
|
+
*/
|
|
159
|
+
function isAutoMergeUnavailable(stderr) {
|
|
160
|
+
const text = String(stderr ?? '').toLowerCase();
|
|
161
|
+
return (
|
|
162
|
+
text.includes('auto merge is not allowed') ||
|
|
163
|
+
text.includes('auto-merge is not allowed') ||
|
|
164
|
+
text.includes('enablepullrequestautomerge') ||
|
|
165
|
+
text.includes('clean status') ||
|
|
166
|
+
(text.includes('auto') && text.includes('not enabled'))
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Direct (non-`--auto`) squash-merge fallback (Story #4682, restoring PR
|
|
172
|
+
* #4480 / Story #4472). Reached only when the `--auto` arm was refused with
|
|
173
|
+
* the {@link isAutoMergeUnavailable} signature — a repo with no native
|
|
174
|
+
* auto-merge, or an already-clean PR with nothing to queue behind. Omitting
|
|
175
|
+
* `--auto` makes `gh` merge synchronously; the same `--squash --delete-branch`
|
|
176
|
+
* shape and the same `armCwd` re-point are preserved so the trailing local
|
|
177
|
+
* `--delete-branch` housekeeping runs from the primary worktree (Story #4282).
|
|
178
|
+
*
|
|
179
|
+
* A local-cleanup-only grumble on the direct merge (Story #4681) still means
|
|
180
|
+
* the REMOTE merge landed, so it reports `directMerged` with
|
|
181
|
+
* `localCleanupDeferred`. Any other non-zero exit is a genuine failure the
|
|
182
|
+
* caller escalates.
|
|
183
|
+
*
|
|
184
|
+
* @returns {Promise<{ enabled: boolean, directMerged?: boolean, localCleanupDeferred?: boolean, reason?: string }>}
|
|
185
|
+
*/
|
|
186
|
+
async function directMergeFallback({ exec, prNumber, armCwd, autoReason }) {
|
|
187
|
+
const direct = await exec(
|
|
188
|
+
['pr', 'merge', String(prNumber), '--squash', '--delete-branch'],
|
|
189
|
+
{ cwd: armCwd },
|
|
190
|
+
);
|
|
191
|
+
if (direct.status === 0) {
|
|
192
|
+
return { enabled: true, directMerged: true, reason: autoReason };
|
|
193
|
+
}
|
|
194
|
+
if (isLocalCleanupOnlyFailure(direct.stderr)) {
|
|
195
|
+
return {
|
|
196
|
+
enabled: true,
|
|
197
|
+
directMerged: true,
|
|
198
|
+
localCleanupDeferred: true,
|
|
199
|
+
reason: autoReason,
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
return {
|
|
203
|
+
enabled: false,
|
|
204
|
+
reason: `direct-merge fallback failed after auto-merge unavailable (${autoReason}); gh-exit-${direct.status}: ${(direct.stderr ?? '').trim().slice(0, 160)}`,
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
|
|
55
208
|
/**
|
|
56
209
|
* Enable GitHub native auto-merge on the PR. Non-fatal.
|
|
57
210
|
*
|
|
@@ -62,7 +215,7 @@ export function isOperatorMergeReason(reason) {
|
|
|
62
215
|
* runner?: (args: string[], opts: object) => ({ status: number, stdout?: string, stderr?: string } | Promise<{ status: number, stdout?: string, stderr?: string }>),
|
|
63
216
|
* resolveArmCwd?: (cwd: string) => string,
|
|
64
217
|
* }} opts
|
|
65
|
-
* @returns {Promise<{ enabled: boolean, reason?: string }>}
|
|
218
|
+
* @returns {Promise<{ enabled: boolean, reason?: string, localCleanupDeferred?: boolean, directMerged?: boolean }>}
|
|
66
219
|
*/
|
|
67
220
|
export async function enableAutoMergeWith({
|
|
68
221
|
cwd,
|
|
@@ -89,10 +242,25 @@ export async function enableAutoMergeWith({
|
|
|
89
242
|
{ cwd: armCwd },
|
|
90
243
|
);
|
|
91
244
|
if (result.status === 0) return { enabled: true };
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
245
|
+
const detail = `gh-exit-${result.status}: ${(result.stderr ?? '').trim().slice(0, 200)}`;
|
|
246
|
+
if (isLocalCleanupOnlyFailure(result.stderr)) {
|
|
247
|
+
// The remote side stands; only the local head-branch cleanup failed.
|
|
248
|
+
// Report ENABLED so the confirm phase polls the real PR state instead
|
|
249
|
+
// of blocking a merge that already landed, and flag the deferred
|
|
250
|
+
// cleanup for the land tail's `git branch -D` to finish.
|
|
251
|
+
return { enabled: true, localCleanupDeferred: true, reason: detail };
|
|
252
|
+
}
|
|
253
|
+
if (isAutoMergeUnavailable(result.stderr)) {
|
|
254
|
+
// No native auto-merge on this repo (or nothing to queue behind an
|
|
255
|
+
// already-clean PR): merge directly so the PR still lands (Story #4682).
|
|
256
|
+
return directMergeFallback({
|
|
257
|
+
exec,
|
|
258
|
+
prNumber,
|
|
259
|
+
armCwd,
|
|
260
|
+
autoReason: detail,
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
return { enabled: false, reason: detail };
|
|
96
264
|
} catch (err) {
|
|
97
265
|
return { enabled: false, reason: `gh-spawn-error: ${err?.message ?? err}` };
|
|
98
266
|
}
|
|
@@ -167,7 +335,11 @@ function makeDefaultGhAutoMergeRunner(gh) {
|
|
|
167
335
|
* gh?: ReturnType<typeof import('../../../gh-exec.js').createGh>,
|
|
168
336
|
* progress: (tag: string, msg: string) => void,
|
|
169
337
|
* }} args
|
|
170
|
-
* @returns {Promise<{ autoMergeEnabled: boolean, autoMergeReason: string|null }>}
|
|
338
|
+
* @returns {Promise<{ autoMergeEnabled: boolean, autoMergeReason: string|null, localCleanupDeferred?: boolean, directMerged?: boolean }>}
|
|
339
|
+
* `localCleanupDeferred` is true when the arm stands but `gh`'s local
|
|
340
|
+
* head-branch delete failed (Story #4681) — the land tail owns the reap.
|
|
341
|
+
* `directMerged` is true when native auto-merge was unavailable and the PR
|
|
342
|
+
* was landed by a direct squash-merge instead (Story #4682).
|
|
171
343
|
*/
|
|
172
344
|
export async function runAutoMergePhase({
|
|
173
345
|
cwd,
|
|
@@ -211,15 +383,56 @@ export async function runAutoMergePhase({
|
|
|
211
383
|
}
|
|
212
384
|
const result = await enableAutoMergeWith({ cwd, prNumber, gh });
|
|
213
385
|
if (result.enabled) {
|
|
386
|
+
if (result.directMerged) {
|
|
387
|
+
// No native auto-merge on this repo — the PR was merged directly
|
|
388
|
+
// instead of queued (Story #4682). The confirm phase polls the PR,
|
|
389
|
+
// observes MERGED, and runs the land tail; `localCleanupDeferred`
|
|
390
|
+
// still defers a local-ref reap when gh's `--delete-branch` grumbled.
|
|
391
|
+
progress(
|
|
392
|
+
'PR',
|
|
393
|
+
`✅ Native auto-merge unavailable on PR #${prNumber} — direct squash-merge landed it` +
|
|
394
|
+
(result.localCleanupDeferred
|
|
395
|
+
? " (gh's LOCAL branch cleanup deferred to the land tail; the merge stands)."
|
|
396
|
+
: '.'),
|
|
397
|
+
);
|
|
398
|
+
return {
|
|
399
|
+
autoMergeEnabled: true,
|
|
400
|
+
autoMergeReason: null,
|
|
401
|
+
directMerged: true,
|
|
402
|
+
localCleanupDeferred: Boolean(result.localCleanupDeferred),
|
|
403
|
+
};
|
|
404
|
+
}
|
|
405
|
+
if (result.localCleanupDeferred) {
|
|
406
|
+
// Warning, never a block (Story #4681): the merge/arm stands and the
|
|
407
|
+
// land tail reaps the local ref once the worktree releases it.
|
|
408
|
+
progress(
|
|
409
|
+
'PR',
|
|
410
|
+
`⚠️ Auto-merge armed on PR #${prNumber}, but gh's LOCAL branch cleanup failed ` +
|
|
411
|
+
`(${result.reason}) — deferring the local ref reap to the land tail; the merge stands.`,
|
|
412
|
+
);
|
|
413
|
+
return {
|
|
414
|
+
autoMergeEnabled: true,
|
|
415
|
+
autoMergeReason: null,
|
|
416
|
+
localCleanupDeferred: true,
|
|
417
|
+
};
|
|
418
|
+
}
|
|
214
419
|
progress(
|
|
215
420
|
'PR',
|
|
216
421
|
`✅ Auto-merge enabled on PR #${prNumber} (squash, delete-branch).`,
|
|
217
422
|
);
|
|
218
|
-
return {
|
|
423
|
+
return {
|
|
424
|
+
autoMergeEnabled: true,
|
|
425
|
+
autoMergeReason: null,
|
|
426
|
+
localCleanupDeferred: false,
|
|
427
|
+
};
|
|
219
428
|
}
|
|
220
429
|
progress(
|
|
221
430
|
'PR',
|
|
222
431
|
`⚠️ Auto-merge enablement failed (${result.reason}) — operator can merge manually.`,
|
|
223
432
|
);
|
|
224
|
-
return {
|
|
433
|
+
return {
|
|
434
|
+
autoMergeEnabled: false,
|
|
435
|
+
autoMergeReason: result.reason,
|
|
436
|
+
localCleanupDeferred: false,
|
|
437
|
+
};
|
|
225
438
|
}
|
|
@@ -80,6 +80,7 @@ async function invokeStoryReviewCore({
|
|
|
80
80
|
provider,
|
|
81
81
|
runCodeReviewFn,
|
|
82
82
|
runLocalLensReviewFn,
|
|
83
|
+
appendFindingsYieldFn,
|
|
83
84
|
progress,
|
|
84
85
|
}) {
|
|
85
86
|
return runStoryReviewCore({
|
|
@@ -91,10 +92,11 @@ async function invokeStoryReviewCore({
|
|
|
91
92
|
progress,
|
|
92
93
|
progressTag: 'REVIEW',
|
|
93
94
|
runCodeReviewFn,
|
|
94
|
-
// Forward the
|
|
95
|
-
// `runStoryReviewCore` uses its
|
|
96
|
-
//
|
|
95
|
+
// Forward the seams only when the caller injects them; otherwise
|
|
96
|
+
// `runStoryReviewCore` uses its defaults. `undefined` deep-merges to
|
|
97
|
+
// the default via the destructuring default there.
|
|
97
98
|
...(runLocalLensReviewFn ? { runLocalLensReviewFn } : {}),
|
|
99
|
+
...(appendFindingsYieldFn ? { appendFindingsYieldFn } : {}),
|
|
98
100
|
});
|
|
99
101
|
}
|
|
100
102
|
|
|
@@ -163,6 +165,7 @@ async function postStoryReviewCrossRef({
|
|
|
163
165
|
* provider: object,
|
|
164
166
|
* runCodeReviewFn: Function,
|
|
165
167
|
* runLocalLensReviewFn?: Function,
|
|
168
|
+
* appendFindingsYieldFn?: Function,
|
|
166
169
|
* progress: (tag: string, msg: string) => void,
|
|
167
170
|
* }} args
|
|
168
171
|
* @returns {Promise<{
|
|
@@ -185,6 +188,7 @@ export async function runStoryScopeReview({
|
|
|
185
188
|
provider,
|
|
186
189
|
runCodeReviewFn,
|
|
187
190
|
runLocalLensReviewFn,
|
|
191
|
+
appendFindingsYieldFn,
|
|
188
192
|
progress,
|
|
189
193
|
}) {
|
|
190
194
|
if (prNumber == null) {
|
|
@@ -208,6 +212,7 @@ export async function runStoryScopeReview({
|
|
|
208
212
|
provider,
|
|
209
213
|
runCodeReviewFn,
|
|
210
214
|
runLocalLensReviewFn,
|
|
215
|
+
appendFindingsYieldFn,
|
|
211
216
|
progress,
|
|
212
217
|
});
|
|
213
218
|
|