pi-gauntlet 5.0.2 → 5.0.3
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/CHANGELOG.md +4 -0
- package/README.md +3 -1
- package/package.json +1 -1
- package/skills/gatekeep-pr/SKILL.md +63 -44
- package/skills/gatekeep-pr/verification-brief.md +73 -21
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## v5.0.3 - 2026-08-25
|
|
4
|
+
|
|
5
|
+
- gatekeep-pr defaults to green exact-head CI evidence (gh-14): normative six-path "Evidence resolution" table at the top of verification-brief.md Section B (opt-out / failed-CI / CI-sufficient / pending / fallback / stale-head, top-down); the local verification command runs only on fallback/opt-out rows; source-discriminated Verifier output (`source: ci|local`) with the exact CI claim form `verified by CI: <check name(s)> succeeded on <sha> (run <url>)`; any blocking conclusion in the resolved set mints a `P#` with a third disposition `CI-infrastructure-broken` that triggers the fallback run; two new `## PR gate` keys `local verification: always` and `ci checks:`. Spec: `doc/specs/2026-09-06-gh-14-gatekeep-ci-evidence-default.md` (partially supersedes `doc/specs/2026-08-18-gh-9-gatekeep-pr-skill.md`, verification-evidence scope only).
|
|
6
|
+
|
|
3
7
|
## v5.0.2 - 2026-08-24
|
|
4
8
|
|
|
5
9
|
- Plan fidelity (gh-13): `writing-plans` task template gains a required spec-anchor line (`**Spec:** <path> § "<heading>" L<start>-L<end>`), a verbatim-quote rule for exact-string requirements, an extraction-first `## Spec coverage` table, and four mechanical self-review checks (quote integrity spec->task, anchor resolution, three-leg table closure, paths exist). `subagent-driven-development` spec-reviewer contract becomes spec+task: dispatches pass the spec path + the task's anchors in both modes and the Dispatch sketch, the spec wins every dispute, task-vs-spec divergence is unconditionally flagged with the spec literal, and `spec-reviewer-prompt.md` gains a `## Spec Authority` section plus `plan transcription gap` / `out-of-anchor-slice` finding labels. Spec: `doc/specs/2026-08-23-gh-13-plan-fidelity-anchors.md` (partially supersedes `doc/specs/2026-07-06-parallel-wave-spec-reviewer-dispatch.md`, SR contract scope only).
|
package/README.md
CHANGED
|
@@ -69,7 +69,7 @@ Everything between gate 1 and gate 2 - task breakdown, implementation, both revi
|
|
|
69
69
|
|
|
70
70
|
pi-gauntlet ships three kinds of pieces, layered on top of pi-cohort's dispatch:
|
|
71
71
|
|
|
72
|
-
- **16 skills** - the workflow logic. Twelve activate automatically when pi sees the matching kind of task, and each one gates the next: `brainstorming`, `writing-plans`, `roasting-the-spec`, `test-driven-development`, `subagent-driven-development`, `dispatching-parallel-agents`, `verification-before-completion`, `requesting-code-review`, `receiving-code-review`, `using-git-worktrees`, `finishing-a-development-branch`, `writing-skills`. Four more are explicit-invocation-only (`disable-model-invocation: true`): `shape-ticket` creates or repairs one tracker issue per run against a Context/Problem/Idea/Acceptance-Criteria template, gated by an AC integrity check, a cheap council roast, and a single human-confirmed write - run it with `/skill:shape-ticket`. `gatekeep-pr` is consent-gated pre-merge verification of a PR against its issue - read-only gathering,
|
|
72
|
+
- **16 skills** - the workflow logic. Twelve activate automatically when pi sees the matching kind of task, and each one gates the next: `brainstorming`, `writing-plans`, `roasting-the-spec`, `test-driven-development`, `subagent-driven-development`, `dispatching-parallel-agents`, `verification-before-completion`, `requesting-code-review`, `receiving-code-review`, `using-git-worktrees`, `finishing-a-development-branch`, `writing-skills`. Four more are explicit-invocation-only (`disable-model-invocation: true`): `shape-ticket` creates or repairs one tracker issue per run against a Context/Problem/Idea/Acceptance-Criteria template, gated by an AC integrity check, a cheap council roast, and a single human-confirmed write - run it with `/skill:shape-ticket`. `gatekeep-pr` is consent-gated pre-merge verification of a PR against its issue - read-only gathering, verification evidence resolved CI-first (green checks on the exact assessed head count as evidence; the project's verification command runs only as fallback), a rubric-based review, then a deterministic authorship-aware menu with stable finding IDs (P#/L#/C#/F#) and numbered pre-composed courses (fixes execute as a single parallel-safe wave: one gate run, one re-review, one push); nothing mutates (fixes, pushes, reviews, merges) until you pick a row - run it with `/skill:gatekeep-pr <pr>`. `check-delivery` is a post-merge detective control: proves an issue actually shipped (default-branch landing, delivery target, per-AC evidence) before its tracker status advances; it never writes a terminal status - run it with `/skill:check-delivery <ref>`. `chase-bug` is human-only bug triage: read-only root-cause discovery to an evidenced verdict menu (real bug -> ticket/brainstorm/respond; five negative verdicts), then a gated response to the reporter - it never fixes during triage - run it with `/skill:chase-bug`.
|
|
73
73
|
- **7 subagent personas** - the specialized child agents the skills dispatch via pi-cohort: `implementer`, `code-reviewer`, `spec-reviewer`, `conformance-reviewer`, `spec-summarizer`, `spec-council-member`, `spec-council-synthesizer`. See [doc/personas.md](./doc/personas.md) for what each one does and why its permissions are scoped the way they are.
|
|
74
74
|
- **3 runtime extensions** - the enforcement layer. `plan-tracker` and `phase-tracker` are tools skills call to track progress (with a TUI widget); `verify-before-ship` is a hook that warns if you push or open a PR without a passing test run since your last edit; a phase-tracker flow guard reminds on implement-phase commits missing spec/code review. See [doc/configuration.md](./doc/configuration.md) for the settings each one reads.
|
|
75
75
|
|
|
@@ -355,6 +355,8 @@ customization lives in two places, never in the wrapper itself:
|
|
|
355
355
|
- verification command: <command> # required unless documented elsewhere
|
|
356
356
|
- timeout minutes: 15 # optional; default 15
|
|
357
357
|
- requires credentials: false # optional; true => skill reports "not run" as missing evidence
|
|
358
|
+
- local verification: always # optional; default (absent) = CI-first; "always" forces the local run even when exact-head CI is green
|
|
359
|
+
- ci checks: <comma-separated check names> # optional; narrows which checks count as evidence; absent = all checks on the assessed head
|
|
358
360
|
- worktree wrapper: <command> # optional
|
|
359
361
|
- issue fetch: <command with <ref> placeholder> # optional, replaces gh issue view
|
|
360
362
|
- merge policy: squash | merge-commit # optional
|
package/package.json
CHANGED
|
@@ -9,8 +9,9 @@ argument-hint: "<pr> [issue-ref] (e.g. 123, or 123 gh-45)"
|
|
|
9
9
|
|
|
10
10
|
Verify, don't trust. A PR description is a claim, not proof: over-claimed coverage,
|
|
11
11
|
hallucinated references, and "tests pass" that were never rerun are the normal case,
|
|
12
|
-
not the exception - especially on generated code. This skill gathers evidence,
|
|
13
|
-
the project's own verification command
|
|
12
|
+
not the exception - especially on generated code. This skill gathers evidence, accepts green CI on the exact assessed head as
|
|
13
|
+
verification evidence (running the project's own verification command only as
|
|
14
|
+
the fallback), reviews the diff against a rubric, and
|
|
14
15
|
presents a deterministic, authorship-aware menu. Authorship sets which row carries
|
|
15
16
|
`[recommended]`; it never changes which rows are offered.
|
|
16
17
|
|
|
@@ -40,7 +41,7 @@ a wrapper skill:
|
|
|
40
41
|
baseline and reviewer-persona defaults on any conflict.
|
|
41
42
|
2. **Gauntlet overrides file** (3-location discovery, first found wins): the
|
|
42
43
|
`## PR gate` section (verification command, `timeout minutes`, `requires credentials`, issue
|
|
43
|
-
fetch, worktree wrapper, merge policy). An existing `## verification-before-completion`
|
|
44
|
+
fetch, worktree wrapper, merge policy, `local verification`, `ci checks`). An existing `## verification-before-completion`
|
|
44
45
|
section is an accepted equivalent source for the verification command.
|
|
45
46
|
3. **Repo documentation** - an explicitly documented command or tool (e.g. `AGENTS.md`'s
|
|
46
47
|
canonical test entrypoint, a documented worktree wrapper, a documented tracker CLI,
|
|
@@ -56,6 +57,8 @@ which is required unless documented elsewhere):
|
|
|
56
57
|
- verification command: <command> # required unless documented elsewhere
|
|
57
58
|
- timeout minutes: 15 # optional; default 15
|
|
58
59
|
- requires credentials: false # optional; true => skill reports "not run" as missing evidence
|
|
60
|
+
- local verification: always # optional; default (absent) = CI-first; "always" forces the local run even when exact-head CI is green
|
|
61
|
+
- ci checks: <comma-separated check names> # optional; narrows which checks count as evidence; absent = all checks on the assessed head
|
|
59
62
|
- worktree wrapper: <command> # optional
|
|
60
63
|
- issue fetch: <command with <ref> placeholder> # optional, replaces gh issue view
|
|
61
64
|
- merge policy: squash | merge-commit # optional
|
|
@@ -81,7 +84,7 @@ configuration.
|
|
|
81
84
|
## Progress tracking
|
|
82
85
|
|
|
83
86
|
Use `plan_tracker`, never `phase_tracker`. Init with the stage names: `gather`,
|
|
84
|
-
`provision worktree`, `
|
|
87
|
+
`provision worktree`, `resolve evidence`, `claim-check`, `review`, `consent menu`.
|
|
85
88
|
Append one task per material claim as the Verifier enumerates them. A passing stage or
|
|
86
89
|
a matched claim -> `complete`. A failed stage or a contradicted claim -> `failed`
|
|
87
90
|
(shown crossed, error color) and stays failed while the skill stops at the menu -
|
|
@@ -124,14 +127,15 @@ merge-ready and surfaced (see the merge preconditions below).
|
|
|
124
127
|
**Phase 3 - Verify, then Review** (sequential, same worktree - deliberate: the
|
|
125
128
|
verification command may write to the tree while the Reviewer reads it):
|
|
126
129
|
|
|
127
|
-
- Run verification-brief.md Section B: the
|
|
128
|
-
|
|
130
|
+
- Run verification-brief.md Section B: resolve the verification evidence per its
|
|
131
|
+
Evidence resolution table (green exact-head CI is the default evidence); run
|
|
132
|
+
the resolved verification command only when the table selects a fallback or
|
|
133
|
+
opt-out row, under its safety contract - self-contained and non-interactive (no prompts; run under a
|
|
129
134
|
non-interactive environment), bounded by a timeout (default 15 minutes, `timeout
|
|
130
135
|
minutes` override) via the first available mechanism: the harness's own bash
|
|
131
136
|
timeout parameter, else the `timeout`/`gtimeout` CLI when installed, else a
|
|
132
137
|
background-and-kill fallback - then material-claim checking against the PR body.
|
|
133
|
-
After
|
|
134
|
-
the orchestrator asserts tracked-only cleanliness (`git status --porcelain
|
|
138
|
+
After a local run, the orchestrator asserts tracked-only cleanliness (`git status --porcelain
|
|
135
139
|
--untracked-files=no` empty, equivalently `git diff --quiet && git diff --cached
|
|
136
140
|
--quiet`; HEAD unmoved) - untracked gate artifacts, including the Verifier's
|
|
137
141
|
`log_path`, are expected and do not fail this check as long as `log_path` sits
|
|
@@ -147,11 +151,16 @@ verification command may write to the tree while the Reviewer reads it):
|
|
|
147
151
|
- **Provenance:** `worktree_root` matches the provisioned path, every `run_cwd` is
|
|
148
152
|
inside it, `head_sha` matches the digest's `headRefOid`. On mismatch, re-fetch the
|
|
149
153
|
PR head once and re-sync + re-run Phase 3 if it advanced; a second mismatch, or any
|
|
150
|
-
path mismatch, is treated as missing evidence - not merge-ready. The claim stated in
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
154
|
+
path mismatch, is treated as missing evidence - not merge-ready. The claim stated in output names its source. Local path: precisely "reproduced
|
|
155
|
+
locally under the project's documented verification command" - nothing
|
|
156
|
+
stronger; never worded to imply a deployed, staging, or CI environment.
|
|
157
|
+
CI path (`source: ci`): precisely
|
|
158
|
+
`verified by CI: <check name(s)> succeeded on <sha> (run <url>)`
|
|
159
|
+
- never phrased as local reproduction, never implying the local command ran;
|
|
160
|
+
`<sha>` is the assessed `headRefOid`, `<url>` degrades to `unavailable` when
|
|
161
|
+
absent. Provenance checks on `worktree_root`/`run_cwd` bind only to the local
|
|
162
|
+
path.
|
|
163
|
+
- **Evidence:** On the CI path, list each satisfying check's name, conclusion, assessed SHA, and run URL - there is no command or raw_tail to paste. On the local path, paste each run's `command` and `raw_tail` verbatim, fenced - never
|
|
155
164
|
paraphrased. Any authored summary is labeled as a summary and never substitutes for
|
|
156
165
|
`raw_tail`.
|
|
157
166
|
- **Severity translation:** Critical -> blocking, Moderate -> blocking, Minor ->
|
|
@@ -165,18 +174,25 @@ verification command may write to the tree while the Reviewer reads it):
|
|
|
165
174
|
claim is a blocking finding. An `unverifiable-pre-merge` claim used as merge proof
|
|
166
175
|
(appears in the PR body's evidence/result/test-plan content) is blocking; stated as
|
|
167
176
|
an explicit post-merge observation instead, it is a non-blocking follow-up.
|
|
168
|
-
- **
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
green,
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
+
- **CI checks:** any blocking conclusion in the resolved check set (required or
|
|
178
|
+
not - see the brief's Evidence resolution table) withholds merge from every
|
|
179
|
+
pre-composed course until the user explicitly dispositions it, and mints a
|
|
180
|
+
`P#`. Three dispositions: **flaky** (proceed via the custom row), **real** (it
|
|
181
|
+
blocks until green), **CI-infrastructure-broken** (the checks themselves are
|
|
182
|
+
untrustworthy: triggers the fallback local run, and merge stays withheld until
|
|
183
|
+
that fallback produces green evidence). A **pending** required check (still
|
|
184
|
+
running - the normal case, not a defect) is **wait-until-green, not
|
|
185
|
+
dispositionable**: it mints no `P#`, is never dispositioned, and the withhold
|
|
186
|
+
auto-lifts the moment it turns green - or, if it instead fails, converts into
|
|
187
|
+
an undispositioned failing check with its own `P#` at that point. While
|
|
188
|
+
pending, the report notes it under Evidence and every merge course simply does
|
|
189
|
+
not render (a pending-only PR is not a blocking verdict - findings groups can
|
|
177
190
|
all read "None" - the recommended course falls to `stop` or `review-comment`,
|
|
178
|
-
never a merge course, until it resolves).
|
|
179
|
-
|
|
191
|
+
never a merge course, until it resolves). The evidence decision is
|
|
192
|
+
independent: a green check elsewhere in the resolved set still satisfies
|
|
193
|
+
verification evidence while a pending required check withholds merge. The
|
|
194
|
+
CI-sufficient path changes no consent surface: still read-only, no auto-merge,
|
|
195
|
+
no posting, no menu change beyond the third disposition.
|
|
180
196
|
- **Doc drift:** when the review finds committed doc drift as a **blocking** finding,
|
|
181
197
|
the orchestrator applies the doc fixes itself, in the provisioned worktree (created
|
|
182
198
|
or reused), as part of assessment - real edits, uncommitted, worktree-local. The
|
|
@@ -215,9 +231,9 @@ issue is linked, committed doc drift, anything the merged rubric maps to blockin
|
|
|
215
231
|
**follow-ups only** (never gate merge), or **clean**.
|
|
216
232
|
|
|
217
233
|
**Merge preconditions** (all must hold): gate green with every blocking finding fixed,
|
|
218
|
-
not deferred; `mergeable == MERGEABLE` (`UNKNOWN` after the one post-provision
|
|
219
|
-
re-poll withholds merge, same as `CONFLICTING`); no undispositioned failing
|
|
220
|
-
pending required check; evidence pasted with clean provenance; worktree clean and synced with the remote
|
|
234
|
+
not deferred; verification evidence present per the brief's Evidence resolution table (a CI claim or a green local run - a table-sanctioned CI skip is evidence, not missing "not run" evidence; result: not run blocks only when the table required a fallback run that didn't happen); `mergeable == MERGEABLE` (`UNKNOWN` after the one post-provision
|
|
235
|
+
re-poll withholds merge, same as `CONFLICTING`); no undispositioned failing check in
|
|
236
|
+
the resolved set, no pending required check; evidence pasted with clean provenance; worktree clean and synced with the remote
|
|
221
237
|
head (fixes pushed first); explicit selection with a head compare-and-swap that
|
|
222
238
|
passes. A merge selection while any precondition fails is refused, naming the failing
|
|
223
239
|
precondition, and the menu re-renders - never a dead end, never a silent merge. Merge
|
|
@@ -253,7 +269,7 @@ findings, menu. No restating diffs, no narration, no recap prose.
|
|
|
253
269
|
<one line + the deciding factor>
|
|
254
270
|
|
|
255
271
|
## Evidence
|
|
256
|
-
<verbatim command + raw_tail per run; claims checked;
|
|
272
|
+
<CI path: satisfying check name(s)/conclusion/sha/url; local path: verbatim command + raw_tail per run; claims checked; resolved-set check dispositions>
|
|
257
273
|
|
|
258
274
|
## Findings (blocking)
|
|
259
275
|
Blocking findings (P#):
|
|
@@ -295,8 +311,8 @@ Requirement/doc drift (linked issue, committed doc drift, or spec conflict):
|
|
|
295
311
|
nothing. Code-level spec bugs (the diff contradicts the spec) are `P#` `[spec]`;
|
|
296
312
|
requirement/doc mismatches (the spec or docs are stale relative to intent) are
|
|
297
313
|
`L#`.
|
|
298
|
-
- **
|
|
299
|
-
|
|
314
|
+
- **Failing checks close by disposition, not by fix:** an undispositioned failing check in the resolved set
|
|
315
|
+
is `P#` `[test]` referencing the check name; it is never a target
|
|
300
316
|
of a worktree `fix`. The user's Phase-4 disposition annotates the same ID rather
|
|
301
317
|
than closing it outright: dispositioned **flaky** -> annotate
|
|
302
318
|
`(dispositioned: flaky)`; this annotation excepts the `P#` from the unfixed-blocker
|
|
@@ -304,6 +320,9 @@ Requirement/doc drift (linked issue, committed doc drift, or spec conflict):
|
|
|
304
320
|
"every blocking finding fixed", and the merge path is Phase 4's explicit flaky
|
|
305
321
|
disposition via the custom row. Dispositioned **real** -> annotate
|
|
306
322
|
`(dispositioned: real)` and the `P#` keeps blocking until the check is green.
|
|
323
|
+
Dispositioned **CI-infrastructure-broken** -> annotate
|
|
324
|
+
`(dispositioned: ci-infrastructure-broken)`; the fallback local run executes,
|
|
325
|
+
and the `P#` keeps blocking until that fallback is green.
|
|
307
326
|
- **Severity is decided at triage, not by the category tag:** a finding lands in
|
|
308
327
|
`P#` only when it must be fixed before merge (correctness, security, material
|
|
309
328
|
performance trap, a convention the repo enforces); improvements that don't
|
|
@@ -363,7 +382,7 @@ pre-composed or custom, bundles a push-producing action (`fix`, `push-docs`) wit
|
|
|
363
382
|
| Author | State | Courses (first = `[recommended]`) |
|
|
364
383
|
|---|---|---|
|
|
365
384
|
| you | clean / follow-ups only | 1. merge-squash; 2. merge-commit; 3. stop; 4. review-comment (post no-blockers note) |
|
|
366
|
-
| you | blocking | 1. fix (worktree-fixable P#s only - `all` covers only those) [+ push-docs when uncommitted doc edits exist]; 2. push-docs (alone, when doc edits exist); 3. stop; 4. review-comment (post findings). When no P# is worktree-fixable (blocking is
|
|
385
|
+
| you | blocking | 1. fix (worktree-fixable P#s only - `all` covers only those) [+ push-docs when uncommitted doc edits exist]; 2. push-docs (alone, when doc edits exist); 3. stop; 4. review-comment (post findings). When no P# is worktree-fixable (blocking is failing-check-only or L#-only), course 1 (fix) is not rendered: push-docs becomes first when doc edits exist, else stop is first |
|
|
367
386
|
| you | blocking, post-fix re-render (gate green, preconditions hold) | 1. merge-squash; 2. merge-commit; 3. stop; 4. review-comment |
|
|
368
387
|
| someone else | clean / follow-ups only | 1. approve; 2. merge-squash (offered-unrecommended); 3. review-comment (no-blockers note) |
|
|
369
388
|
| someone else | blocking | 1. request-changes; 2. fix all (courtesy, their branch - omitted when nothing is worktree-fixable); 3. reply <C#s> (omitted when the `C#` group is None); 4. review-comment |
|
|
@@ -382,18 +401,18 @@ also dropped (never offered on your own PR) - fork|you|clean renders
|
|
|
382
401
|
branch course is also absent, since it is your own PR). A fork PR authored by someone
|
|
383
402
|
else uses the someone-else cells above with `fix`/`push-docs`/`merge-*` removed.
|
|
384
403
|
|
|
385
|
-
**
|
|
386
|
-
required check withholds every pre-composed course containing `merge-*` (per the
|
|
404
|
+
**CI-check gate on merge courses:** an undispositioned failing check in the resolved
|
|
405
|
+
set, or a pending **required** check, withholds every pre-composed course containing `merge-*` (per the
|
|
387
406
|
Verdict merge preconditions) - none render, whatever the author/state cell says. A
|
|
388
407
|
pending check mints no `P#` and is wait-until-green, not dispositionable (see Phase
|
|
389
|
-
4); a failing one mints a `P#` and takes a disposition. A **flaky** disposition does
|
|
408
|
+
4); a failing one mints a `P#` and takes a disposition (flaky / real / CI-infrastructure-broken). A **flaky** disposition does
|
|
390
409
|
not restore merge to a pre-composed course; merge proceeds only via the custom row
|
|
391
410
|
naming the disposition explicitly. A **real** disposition, or an unresolved pending
|
|
392
|
-
check, keeps every merge course withheld until the check is green - a pending-only
|
|
411
|
+
check, keeps every merge course withheld until the check is green; a **CI-infrastructure-broken** disposition keeps them withheld until the triggered fallback run is green - a pending-only
|
|
393
412
|
render is not itself a blocking verdict (findings groups may all read "None"); the
|
|
394
413
|
recommended course falls to `stop` or `review-comment` in the meantime. This never
|
|
395
|
-
falls through to the clean cell's recommended `merge-squash` - a
|
|
396
|
-
|
|
414
|
+
falls through to the clean cell's recommended `merge-squash` - a failing resolved-set
|
|
415
|
+
check or a pending required check means the PR is not in the clean state to begin with.
|
|
397
416
|
|
|
398
417
|
Rows a cell offers but GitHub would refuse (branch protection, missing permission)
|
|
399
418
|
render listed-but-unavailable with the reason. Zero mutation courses is a legal
|
|
@@ -434,7 +453,7 @@ The menu is a state machine, not a one-shot report:
|
|
|
434
453
|
next CAS check runs against the new head on the next external write.
|
|
435
454
|
2. Execute only the selected course. **Fix wave** (`fix <set>`): first filter the
|
|
436
455
|
selected set to worktree-fixable `P#`s - drop any `P#` closed by disposition
|
|
437
|
-
(an undispositioned
|
|
456
|
+
(an undispositioned failing-check `P#` is never a `fix` target; a **flaky**
|
|
438
457
|
disposition already excepts it) - and route file-less `P#`s (a claim or a gate
|
|
439
458
|
command as `source_ref`, no draft touching a file) to run inline/sequentially,
|
|
440
459
|
never as part of a parallel file-batch.
|
|
@@ -463,7 +482,7 @@ The menu is a state machine, not a one-shot report:
|
|
|
463
482
|
Once every dispatched/inline batch returns, the orchestrator commits the golden
|
|
464
483
|
course as one local commit set - the code fixes plus any already-applied
|
|
465
484
|
reviewed doc edits selected alongside them (one commit, or one per batch
|
|
466
|
-
sequentially; subjects name the fixes) - then re-
|
|
485
|
+
sequentially; subjects name the fixes) - then re-resolves the evidence for the new head **once** (the brief's stale-head row: prior evidence is stale; the local command executes only on a fallback/opt-out resolution). **On
|
|
467
486
|
green**, push **once**; gate and push are per-wave invariants, never per-fix or
|
|
468
487
|
per-batch. **On red**, do not push: leave the commit(s) local, re-render with
|
|
469
488
|
the unresolved `P#`s still open, and warn that unpushed fix commits sit in the
|
|
@@ -474,9 +493,9 @@ The menu is a state machine, not a one-shot report:
|
|
|
474
493
|
with the drafted payload for the selected IDs.
|
|
475
494
|
3. After any mutation that can change readiness (fix wave pushed, docs pushed, PR
|
|
476
495
|
head moved), re-run the claim-check and Review on the synced worktree: claims
|
|
477
|
-
are re-checked against the new head and findings are re-rendered, but
|
|
478
|
-
verification command itself is **not** re-executed here - step 2's
|
|
479
|
-
already was the wave's one and only
|
|
496
|
+
are re-checked against the new head and findings are re-rendered, but
|
|
497
|
+
the verification command itself is **not** re-executed here - step 2's evidence re-resolution
|
|
498
|
+
already was the wave's one and only gate pass. Re-render the report:
|
|
480
499
|
each selected `P#`/`L#` confirmed resolved is annotated `(fixed in <sha>)`
|
|
481
500
|
under its original ID; unresolved ones stay open unchanged; new findings
|
|
482
501
|
continue the sequence. Merge, if now available, renders as row 1.
|
|
@@ -512,14 +531,14 @@ overrides file - see Project overrides.
|
|
|
512
531
|
- Any mutation (fix, push, review, merge) without an explicit menu selection
|
|
513
532
|
- Pasting paraphrased evidence instead of verbatim `raw_tail`
|
|
514
533
|
- A provenance mismatch (worktree, `run_cwd`, or `head_sha`) noticed and ignored
|
|
515
|
-
- Merging around an undispositioned blocking finding or
|
|
534
|
+
- Merging around an undispositioned blocking finding or failing-check `P#`
|
|
516
535
|
- Reading configuration (rubric, verification command, or ladder sources) from the
|
|
517
536
|
PR's head instead of the base branch's merge-base
|
|
518
537
|
- Renumbering or reusing a finding ID between menu rounds
|
|
519
538
|
- Presenting findings without IDs, a blocking verdict with no `P#`/`L#`, or a
|
|
520
539
|
`## Decision` rendered without its action vocabulary
|
|
521
540
|
- Treating `[quality]` or `[performance]` as a downgrade signal on a `P#` - only
|
|
522
|
-
an explicit Phase-4 flaky disposition excepts a
|
|
541
|
+
an explicit Phase-4 flaky disposition excepts a failing-check `P#` from the
|
|
523
542
|
unfixed-blocker set, never a category tag
|
|
524
543
|
- A course (pre-composed or custom) bundling a push-producing action with
|
|
525
544
|
`merge-*`
|
|
@@ -57,7 +57,7 @@ invent ACs.
|
|
|
57
57
|
provisioning, so it never re-polls; the orchestrator re-polls once after
|
|
58
58
|
provisioning the worktree (see SKILL.md Phase 2) and treats a still-`UNKNOWN`
|
|
59
59
|
result as not merge-ready. Bot author noted
|
|
60
|
-
(`author_is_bot`). Capture each status check's `isRequired` where exposed.
|
|
60
|
+
(`author_is_bot`). Capture each status check's `isRequired` where exposed (digest field: `required`).
|
|
61
61
|
|
|
62
62
|
**Gather digest output schema (normative):**
|
|
63
63
|
|
|
@@ -65,7 +65,7 @@ result as not merge-ready. Bot author noted
|
|
|
65
65
|
- pr: { number, title, body, author, author_is_bot, state, isDraft, headRefName, baseRefName,
|
|
66
66
|
isCrossRepository, mergeable, headRefOid, files, additions, deletions, reviewDecision }
|
|
67
67
|
- viewer: { login, is_author, permission }
|
|
68
|
-
- status_checks: [ { name, status, conclusion, required } ] #
|
|
68
|
+
- status_checks: [ { name, status, conclusion, required, url } ] # evidence semantics: Section B Evidence resolution
|
|
69
69
|
- comments: { inline[], top_level[], review_threads[]? }
|
|
70
70
|
- issue: { ref, title, body, acceptance_criteria[], comments[] } | null
|
|
71
71
|
- worktree_discovery: { expected_path, exists, branch, dirty, ahead, behind }
|
|
@@ -73,18 +73,57 @@ result as not merge-ready. Bot author noted
|
|
|
73
73
|
```
|
|
74
74
|
|
|
75
75
|
`viewer_is_author` lives at `viewer.is_author` in the digest, computed as
|
|
76
|
-
`viewer.login == pr.author.login`. `status_checks`
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
76
|
+
`viewer.login == pr.author.login`. Each `status_checks` entry's `url` is the CheckRun `detailsUrl` / StatusContext
|
|
77
|
+
`targetUrl` already present in the fetched payload; when the payload omits it,
|
|
78
|
+
downstream CI claims record `url: unavailable` - absence never disqualifies the
|
|
79
|
+
check. GraphQL enums are case-folded; a StatusContext's `state` is its
|
|
80
|
+
conclusion, with `ERROR` blocking and `PENDING` pending. Missing `required` is
|
|
81
|
+
treated as non-required. `ci checks:` matches check name, workflow name, or
|
|
82
|
+
status context, trimmed, case-insensitive. What checks mean for verification evidence is owned by
|
|
83
|
+
Section B's Evidence resolution table; what they mean for merge is owned by the
|
|
84
|
+
orchestrator's required-check rule (SKILL.md Phase 4) - two independent
|
|
85
|
+
consumers of the same data.
|
|
80
86
|
|
|
81
87
|
## Section B - Verifier
|
|
82
88
|
|
|
83
|
-
|
|
84
|
-
|
|
89
|
+
Resolves the verification evidence per the table below - green exact-head CI is
|
|
90
|
+
the default evidence; the resolved verification command runs inside the
|
|
91
|
+
provisioned worktree only when the table selects a fallback or opt-out row -
|
|
92
|
+
then claim-checks the PR body. Report only - do not
|
|
85
93
|
edit, fix, or commit anything; you are running a gate and claim-checking,
|
|
86
94
|
not implementing.
|
|
87
95
|
|
|
96
|
+
**Evidence resolution (normative).** The single rule for whether the local
|
|
97
|
+
command runs. Inputs come from Section A's existing `gh pr view` call - no
|
|
98
|
+
second fetch.
|
|
99
|
+
|
|
100
|
+
- **Resolved check set** = checks named by `ci checks:` if configured, else all
|
|
101
|
+
checks on the assessed `headRefOid`.
|
|
102
|
+
- **Conclusion semantics**: `success` satisfies; `failure`/`timed_out`/
|
|
103
|
+
`action_required`/`error` block; `neutral`/`skipped`/`cancelled`/`stale`/
|
|
104
|
+
`startup_failure` are inert; a check with `status != completed` is pending; a
|
|
105
|
+
completed check with a missing/unreadable conclusion cannot satisfy
|
|
106
|
+
(fail-safe).
|
|
107
|
+
|
|
108
|
+
Row precedence is top-down: the first matching row wins.
|
|
109
|
+
|
|
110
|
+
| Path | Trigger | Action | Evidence recorded |
|
|
111
|
+
|---|---|---|---|
|
|
112
|
+
| Opt-out | `local verification: always` in `## PR gate` | Run local command unconditionally; a Failed-CI block below still applies independently | Local, as today |
|
|
113
|
+
| Failed CI | Any blocking conclusion in resolved set | Blocks: mints a `P#` (any resolved-set failure, required or not). A green local run never overrides it. Only an explicit human CI-infrastructure-broken disposition triggers the fallback run; merge stays withheld until the fallback produces green evidence | The disposition; plus the fallback run's result only when CI-infrastructure-broken triggered one |
|
|
114
|
+
| CI-sufficient | >=1 `success` in resolved set | Skip local run | CI claim: check name(s), conclusion, assessed SHA, run URL |
|
|
115
|
+
| Pending | Zero `success` and >=1 pending check in resolved set | Evidence decision waits until the set reaches a completed conclusion - never a fallback trigger, never an evidence-less merge; merge is withheld as missing evidence until the table re-resolves | n/a (waiting) |
|
|
116
|
+
| Fallback | No checks on assessed head, or zero `success` with none pending (all inert / fail-safe) | Run local command (protocol below, unchanged) | Local command + raw tail, existing provenance rules |
|
|
117
|
+
| Stale head | Head advances since evidence was resolved (e.g. a fix-wave push); fires across runs - a single gather is same-head by construction | All prior evidence (CI or local) is stale; re-resolve this table for the new head before merge is offered | Fresh evidence for the new head |
|
|
118
|
+
|
|
119
|
+
CI-sufficient predicate, stated once (the rows implement exactly this): **>=1
|
|
120
|
+
completed `success`, zero blocking conclusions, no opt-out.** Pending checks are
|
|
121
|
+
excluded from the predicate - they neither satisfy nor veto it. The evidence
|
|
122
|
+
decision ("run local?") and the merge decision ("can this merge?") are separate
|
|
123
|
+
consumers of the same `status_checks` data: a green non-required check satisfies
|
|
124
|
+
evidence even while a pending required check blocks merge under the existing
|
|
125
|
+
wait rule. The only evidence-path wait is the Pending row's zero-success case.
|
|
126
|
+
|
|
88
127
|
**Safety contract:**
|
|
89
128
|
|
|
90
129
|
- Timeout default 15 minutes, overridable by the resolved `timeout minutes`
|
|
@@ -95,7 +134,9 @@ not implementing.
|
|
|
95
134
|
non-interactive.
|
|
96
135
|
- If the resolved config states `requires credentials: true`, do not run
|
|
97
136
|
the command; report "verification requires credentials, not run" as
|
|
98
|
-
missing evidence instead of prompting for secrets
|
|
137
|
+
missing evidence instead of prompting for secrets; this arises only when
|
|
138
|
+
the table selected a fallback or opt-out row - a CI-sufficient resolution
|
|
139
|
+
needs no credentials.
|
|
99
140
|
- Capture full output to a `log_path` inside the (disposable) worktree, under a
|
|
100
141
|
gitignored path (e.g. `.worktrees/pr-<N>/.gatekeep-logs/`) so it never counts as a
|
|
101
142
|
tracked change; keep only the last ~100 lines verbatim in the digest as `raw_tail`.
|
|
@@ -103,19 +144,27 @@ not implementing.
|
|
|
103
144
|
**Verifier output schema (normative):**
|
|
104
145
|
|
|
105
146
|
```text
|
|
106
|
-
-
|
|
107
|
-
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
-
|
|
147
|
+
- source: ci | local
|
|
148
|
+
- source: ci ->
|
|
149
|
+
head_sha: <the assessed headRefOid>
|
|
150
|
+
checks: [ { name, conclusion, url } ] # url: unavailable when the payload omits it
|
|
151
|
+
(no command, no raw_tail - nothing ran locally)
|
|
152
|
+
- source: local ->
|
|
153
|
+
worktree_root: <absolute path>
|
|
154
|
+
head_sha: <git rev-parse HEAD at run time>
|
|
155
|
+
runs: [ { run_cwd, command (verbatim), exit_code, result: pass|fail|not run,
|
|
156
|
+
raw_tail: <last ~100 lines of combined stdout+stderr, verbatim, fenced>,
|
|
157
|
+
log_path: <file inside the worktree holding the full captured output> } ]
|
|
158
|
+
- claims: [ { claim, disposition: matched|contradicted|unverifiable-pre-merge, evidence } ] # both sources
|
|
112
159
|
```
|
|
113
160
|
|
|
114
|
-
`raw_tail` is captured output, not authored prose; anything written in your
|
|
161
|
+
Local provenance and raw-tail rules bind only to source: local. `raw_tail` is captured output, not authored prose; anything written in your
|
|
115
162
|
own words is labeled `summary` and must never be pasted in place of
|
|
116
163
|
`raw_tail`.
|
|
117
164
|
|
|
118
|
-
**Material-claim check.**
|
|
165
|
+
**Material-claim check.** Always runs, on both sources - on the CI path,
|
|
166
|
+
dispositions are judged against the recorded CI evidence and the diff; on the
|
|
167
|
+
local path, against the run and the diff. Claim-check the PR body -
|
|
119
168
|
**material claims only** (test/verification/behavior assertions: "added
|
|
120
169
|
X", "tests cover Y", "fixed Z"), not qualitative prose. Disposition each
|
|
121
170
|
claim as one of:
|
|
@@ -130,7 +179,7 @@ proof* (it appears in the PR body's evidence/result/test-plan content) is
|
|
|
130
179
|
blocking; the same claim stated as an explicit post-merge observation is
|
|
131
180
|
non-blocking follow-up only.
|
|
132
181
|
|
|
133
|
-
After
|
|
182
|
+
After a local run (`source: local` only), the orchestrator asserts tracked-only cleanliness
|
|
134
183
|
(`git status --porcelain --untracked-files=no` empty, equivalently
|
|
135
184
|
`git diff --quiet && git diff --cached --quiet`; HEAD unmoved); untracked gate
|
|
136
185
|
artifacts - including `log_path` itself, provided it sits under a gitignored path
|
|
@@ -171,9 +220,12 @@ blocking/follow-up happens later, at integration.
|
|
|
171
220
|
judges against stated intent only, never inventing ACs; scope-creep findings
|
|
172
221
|
do not apply.
|
|
173
222
|
- No resolvable verification command (ladder exhausted, user asked, user
|
|
174
|
-
declines)
|
|
175
|
-
|
|
176
|
-
|
|
223
|
+
declines) **when the Evidence resolution table selected a fallback or opt-out
|
|
224
|
+
row**: the gate runs without local verification evidence; record
|
|
225
|
+
`result: not run` in the Verifier output. Missing evidence blocks merge the
|
|
226
|
+
same as a failed gate - the PR is not merge-ready. A table-sanctioned CI skip
|
|
227
|
+
(`source: ci`) is evidence, never missing evidence, and needs no command at
|
|
228
|
+
all.
|
|
177
229
|
- Linked-issue fetch fails (tracker unreachable, bad ref): proceed judging
|
|
178
230
|
against the PR's stated intent, mark `issue: null` in the digest plus a
|
|
179
231
|
truncation/availability note explaining why, and never invent ACs; AC
|