mirror of
https://github.com/garrytan/gstack.git
synced 2026-11-01 14:34:42 +01:00
Merge remote-tracking branch 'origin/main' into gsta-96-preamble-hoist
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> # Conflicts: # CHANGELOG.md # test/fixtures/skill-md-size-allowlist.json
This commit is contained in:
commit
f9aa06cf81
9 files changed
+166
-69
No files matched your search
@@ -34,6 +34,32 @@
|
||||
### Gate integrity
|
||||
- No threshold, budget, timeout, trial count, case kind or assertion weakened. The section heading "Completeness Principle — Boil the Ocean" is unchanged, so every skip list that names it still matches.
|
||||
|
||||
## [1.91.226.0] - 2026-10-26
|
||||
|
||||
**/review can re-review just its own fixes after a fixing pass, under the same rules as /ship (#3339).** Before, every /review fix cycle reran the whole review over the whole branch, so a large branch could hit the three-cycle stop on findings in code the earlier passes had already read. Now the pass after an edited pass starts with `gstack-review-log --start review --fix-range` and its checklist, specialists and QA read only what changed since that pass. The Step 4.8 adversarial review still reads the whole branch on every pass, because its rows carry their own freshness. A narrowed pass is never the final review: when it makes no edits, /review runs one full pass before writing the final record, and a fix-range record is never CURRENT. Garry's "do it" on 2026-10-24 for a fix-range re-review with a final full pass covers it.
|
||||
|
||||
### Changed
|
||||
- **`review/SKILL.md.tmpl`** Step 3: the first pass always starts full. The pass right after an edited pass starts with `--start review --fix-range`, and wherever that pass sets DIFF_BASE outside Step 4.8 it uses the printed `FIX_BASE=<sha>` instead. Step 4.8 and every other `<base>` use (state-matrix detection, the gate, banned-terms and slop scans, the queue check) keep the base branch. State-matrix detection builds `origin/<base>` from its argument, and the slop scan diffs `<base>...HEAD`, which is empty while /review's fixes are uncommitted. If the logger refuses (for example, the first pass read uncommitted work, so no commit marks what it read), the pass starts full.
|
||||
- **Step 5.8**: an edited pass now saves its own record with `converged:false` before the repeat, because the fix-range start takes its base from that record. Before, only the final pass was logged. Step 5.0 never treats this invocation's own records as prior reviews, so a defect the user skipped this invocation is not suppressed on the next pass and still counts as unresolved. "No edits" fills the final record only after a full pass; after a fix-range pass it repeats Steps 3–5 with a full start. Each logged pass finishes its own REVIEW_START.
|
||||
- Nearby prose was tightened to pay for the growth (the slop-scan note, the Step 4.7 probe-reuse rule, the search-before-recommending list, the version-compare note, the final-report and Greptile lines). Every host's review SKILL.md shrank by 36 characters, and its size pin was lowered to match. The Claude skeleton is 80,581 bytes against its 80,900 cap.
|
||||
|
||||
### Tests
|
||||
- `test/review-fix-range.test.ts` adds five cases. Two check the rendered rules: the first pass's start block has no `--fix-range`, only the pass after an edited pass narrows, FIX_BASE replaces only DIFF_BASE outside Step 4.8, a refusal falls back to a full start, the edited pass is logged before the repeat and kept out of Step 5.0, and a fix-range pass is never final. Three run /review's real order on every pass against the real logger: core start, then the Step 4.8 attempt's start and finish, then fixes in the working tree, then the core finish with the pass's own token, and never a commit. A committed first pass narrows the next repeat to the uncommitted fixes, and the following repeat is refused back to a full pass that is CURRENT. A zero-edit fix-range row is UNVERIFIED even if it were logged. A first pass over uncommitted work can't be narrowed.
|
||||
- `test/review-workflow-clarity.test.ts`: three expectations follow the new contract: the "No edits" marker, the edited pass saving its record with `converged:false`, and each pass finishing its own token instead of only the final one. The test formerly named "finish only the final core token without log-time capture" is now "each logged pass finishes its own core token without log-time capture". It still requires one `--finish REVIEW_START`, no `--start review` in Step 5.8 and no log-time token capture.
|
||||
|
||||
### Gate integrity
|
||||
- One gate change to review: /review may narrow a repeat pass. Verdict: this does not weaken what the final review covers, because a narrowed pass can't be the final record. The logger never marks a fix-range row CURRENT, Step 5.8 requires a full pass after a zero-edit fix-range pass, Step 4.8 stays full, and Step 5.0 can't suppress this invocation's skipped defects through its own intermediate records. Mutation checks on the rendered skill, each caught by the suite:
|
||||
- letting a fix-range pass be final;
|
||||
- dropping the full-pass condition on "No edits";
|
||||
- narrowing every repeat;
|
||||
- dropping the refusal fallback;
|
||||
- narrowing the first pass;
|
||||
- not logging the edited pass;
|
||||
- logging after the repeat;
|
||||
- narrowing Step 4.8 and other base uses;
|
||||
- letting Step 5.0 read this invocation's records.
|
||||
- No threshold, budget, timeout, trial count or case kind changed. Size pins only went down.
|
||||
|
||||
## [1.91.225.0] - 2026-10-26
|
||||
|
||||
**/design-html builds landing pages around one visitor action and pages that look finished, without inventing proof; adapted from Elaya's design skills (GSTA-92).** Freeform /design-html asked for purpose, audience and feel, then built. It never asked for the one action the page exists for or where the traffic comes from, and nothing caught a page that shipped with invented customers and numbers, a dead `href="#"`, a scroll-listener reveal, `100vh`, or no description, favicon or working skip link. Now every run reads a craft section at Step 1, and a free checker counts the tells at Step 4. Adapted from Elaya's [ai-design-skills](https://github.com/elayadesign/ai-design-skills) (landing-page-design, design-to-motion) and [redesign-skill](https://github.com/elayadesign/redesign-skill), MIT, © 2026 Elaya. Thank you, Elaya.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# gstack digest v1.91.225.0 — regenerate/re-copy after upgrading gstack
|
||||
# gstack digest v1.91.226.0 — regenerate/re-copy after upgrading gstack
|
||||
|
||||
Behavioral rules from gstack (https://github.com/garrytan/gstack), compressed
|
||||
for agent hosts without a full skill install. The full skills add workflows,
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "gstack",
|
||||
"version": "1.91.225",
|
||||
"version": "1.91.226",
|
||||
"description": "Garry's Stack — Claude Code skills + fast headless browser. One repo, one install, entire AI engineering workflow.",
|
||||
"license": "MIT",
|
||||
"type": "module",
|
||||
|
||||
+25
-26
@@ -255,8 +255,11 @@ git diff "$DIFF_BASE"
|
||||
```
|
||||
|
||||
1. Save the printed REVIEW_START for this core candidate before reading its diff.
|
||||
2. Each re-review captures a new token before reading, never at log time. Earlier
|
||||
core tokens remain unused; Step 5.8 finishes only the final core token.
|
||||
2. Each re-review captures a new token before reading, never at log time. After an
|
||||
edited pass, start the next with `--start review --fix-range`: it prints
|
||||
REVIEW_START, then `FIX_BASE=<sha>`. Wherever this pass sets DIFF_BASE outside
|
||||
Step 4.8, use FIX_BASE instead; Step 4.8 and every other `<base>` use stay full.
|
||||
On refusal, start a full pass.
|
||||
3. Native/outside reviewer attempts own separate PASS_START tokens, not REVIEW_START.
|
||||
4. Read non-ignored untracked source too (`git ls-files --others --exclude-standard`);
|
||||
the captured candidate includes it.
|
||||
@@ -290,13 +293,13 @@ OFFLINE=$(echo "$QUEUE_JSON" | jq -r '.offline // false')
|
||||
- `OFFLINE=true`: skip this section.
|
||||
- Otherwise, include ONE line in the review output: `Version claimed: v<BRANCH_VERSION>. Queue: <CLAIMED_COUNT> PR(s) ahead. <VERDICT>` where VERDICT is either `Slot free` (if `BRANCH_VERSION >= NEXT_SLOT`) or `⚠ queue moved — rerun /ship to reconcile v<BRANCH_VERSION> → v<NEXT_SLOT>`.
|
||||
|
||||
Compare dotted version components as integers from left to right; missing trailing components count as zero.
|
||||
Compare versions numerically per dotted component; missing ones count as zero.
|
||||
|
||||
---
|
||||
|
||||
## Step 3.5: Diff scans
|
||||
|
||||
Run the gate scan first (local, seconds; every diff size), then the slop scan.
|
||||
Run the gate scan first (local; every diff size), then the slop scan.
|
||||
|
||||
### Gate scan
|
||||
|
||||
@@ -339,14 +342,11 @@ category, Step 5.8's record and the final report.
|
||||
|
||||
### Slop scan (advisory)
|
||||
|
||||
Scan changed files for empty catches, redundant `return await` and needless abstractions:
|
||||
|
||||
```bash
|
||||
bun run slop:diff origin/<base> 2>/dev/null || true
|
||||
```
|
||||
|
||||
Include findings as non-blocking informational diagnostics. If slop:diff is
|
||||
unavailable, skip silently.
|
||||
Findings are non-blocking informational diagnostics; skip if unavailable.
|
||||
|
||||
---
|
||||
|
||||
@@ -469,10 +469,8 @@ a clean result. Gate findings are ASK in Step 5 regardless of how mechanical the
|
||||
revert looks. A test-only flake fix (timeout, retry, looser assertion, skip) states `P(fail | regression)` before and after, from a forced probe; without both numbers it is RH-15.
|
||||
|
||||
**Search-before-recommending:** Research proposed fixes through Aside, especially
|
||||
concurrency, caching, auth and framework behavior:
|
||||
- Check current best practice for the installed framework version.
|
||||
- Look for a newer built-in before proposing a workaround.
|
||||
- Verify API signatures against current docs.
|
||||
concurrency, caching, auth and framework behavior: current best practice for the
|
||||
installed version, newer built-ins that replace a workaround, and current API signatures.
|
||||
|
||||
Prompt file text (create, write and send it with the Web research runs in Aside blocks above): `{framework} {version} {pattern} current best practice and whether a built-in replaces it. Reply with up to 5 bullets, each with its source URL.`
|
||||
|
||||
@@ -802,7 +800,7 @@ Verify claims or flag them as unknown; "this looks fine" is not evidence.
|
||||
|
||||
After outputting your own findings, if Greptile comments were classified in Step 2.5:
|
||||
|
||||
**Include a Greptile summary in your output header:** `+ N Greptile comments (X valid, Y fixed, Z FP)`
|
||||
**Greptile summary in your output header:** `+ N Greptile comments (X valid, Y fixed, Z FP)`
|
||||
|
||||
Before replying to any comment, run greptile-triage.md's **Escalation Detection** to choose Tier 1 (friendly) or Tier 2 (firm) reply templates.
|
||||
|
||||
@@ -817,7 +815,7 @@ Before replying to any comment, run greptile-triage.md's **Escalation Detection*
|
||||
|
||||
3. **VALID BUT ALREADY FIXED comments:** Reply with greptile-triage.md's **Already Fixed reply template**, no AskUserQuestion: what was done and the fixing commit SHA; save to both per-project and global greptile-history.
|
||||
|
||||
4. **SUPPRESSED comments:** Skip silently (known false positives from previous triage).
|
||||
4. **SUPPRESSED comments:** Skip silently.
|
||||
|
||||
---
|
||||
|
||||
@@ -826,16 +824,17 @@ Before replying to any comment, run greptile-triage.md's **Escalation Detection*
|
||||
### 1. Re-review after edits
|
||||
|
||||
1. A pass covers Steps 3–5, including all reviewers before fixes. Allow at most 3 fix cycles:
|
||||
- Edited: increment CYCLES once. Below 3, repeat Steps 3–5 with a new
|
||||
REVIEW_START. At 3, persist `converged:false` and remaining findings by filling
|
||||
and saving the record below. Report nonconvergence and coverage gaps, then STOP
|
||||
this invocation, without a clean summary or a fourth pass.
|
||||
- No edits: fill the record below.
|
||||
- Edited: increment CYCLES once, then fill and save the record below with
|
||||
`converged:false`. Step 5.0 never treats this invocation's records as prior
|
||||
reviews. Below 3, repeat Steps 3–5 with a new REVIEW_START. At 3, report
|
||||
nonconvergence and coverage gaps, then STOP this invocation, without a clean
|
||||
summary or a fourth pass.
|
||||
- No edits: after a full pass, fill the record below. A fix-range pass is never
|
||||
final: repeat Steps 3–5 with a full start.
|
||||
2. On a repeat, execute Steps 3–5 in order. At Step 4.7, reuse only this invocation's
|
||||
unchanged-input QA evidence; rerun affected probes after source, test, contract,
|
||||
command or fixture changes. Reusing a probe never skips a review step.
|
||||
A probe is affected when its entrypoint, dependencies, contract or replay inputs
|
||||
change; if uncertain, rerun it.
|
||||
unchanged-input QA evidence; rerun a probe if its source, tests, entrypoint,
|
||||
dependencies, contract, command, fixture or replay inputs changed, or if uncertain.
|
||||
Reusing a probe never skips a review step.
|
||||
3. **Verify completed actions.** On the final zero-edit pass, reconcile this
|
||||
invocation's actions with current findings. Deduplicate by structural identity
|
||||
and advisory/defect kind. For a completed extraction, retain `fixed` and the
|
||||
@@ -871,7 +870,7 @@ pass: report it with its reason.
|
||||
|
||||
- Use Step 4.6's `specialists` object unchanged, including its empty small-diff map.
|
||||
If this host omits Review Army, use `specialists: {}` without claiming specialist coverage.
|
||||
- Build `findings` from Step 5's combined final-pass findings (core, specialist,
|
||||
- Build `findings` from Step 5's combined findings (core, specialist,
|
||||
adversarial, actionable Greptile, verified exploratory QA findings) and invocation actions. Retain `fingerprint`, `severity`
|
||||
(`CRITICAL|INFORMATIONAL`), `action`, and any `advisory`, `evidence_paths`,
|
||||
`helper_target`. Recheck source after fixes. The logger uses `sharedLibsFingerprint`,
|
||||
@@ -899,11 +898,11 @@ were skipped or this host omits Review Army). This default is not completion evi
|
||||
unresolved non-advisory core defects still count in `issues_found`,
|
||||
`critical`, `informational`. The logger builds trusted `review_binding` from the
|
||||
validated captured branch digest, discarding caller bindings. Never invent a binding
|
||||
or replace REVIEW_START at log time; finish only the final core token.
|
||||
or replace REVIEW_START at log time; finish only this pass's own token.
|
||||
|
||||
### Report the final review
|
||||
|
||||
Emit one final report, merging all reviewers rather than concatenating them:
|
||||
Emit one final report merging all reviewers:
|
||||
1. `Pre-Landing Review: N issues (X critical, Y informational)` counts final unresolved
|
||||
non-advisory defects. State INCOMPLETE if `COMPLETED` is false, even when N=0.
|
||||
2. Use the checklist's action groups with confidence-tagged finding lines. Keep fixed,
|
||||
|
||||
+25
-26
@@ -87,8 +87,11 @@ git diff "$DIFF_BASE"
|
||||
```
|
||||
|
||||
1. Save the printed REVIEW_START for this core candidate before reading its diff.
|
||||
2. Each re-review captures a new token before reading, never at log time. Earlier
|
||||
core tokens remain unused; Step 5.8 finishes only the final core token.
|
||||
2. Each re-review captures a new token before reading, never at log time. After an
|
||||
edited pass, start the next with `--start review --fix-range`: it prints
|
||||
REVIEW_START, then `FIX_BASE=<sha>`. Wherever this pass sets DIFF_BASE outside
|
||||
Step 4.8, use FIX_BASE instead; Step 4.8 and every other `<base>` use stay full.
|
||||
On refusal, start a full pass.
|
||||
3. Native/outside reviewer attempts own separate PASS_START tokens, not REVIEW_START.
|
||||
4. Read non-ignored untracked source too (`git ls-files --others --exclude-standard`);
|
||||
the captured candidate includes it.
|
||||
@@ -122,13 +125,13 @@ OFFLINE=$(echo "$QUEUE_JSON" | jq -r '.offline // false')
|
||||
- `OFFLINE=true`: skip this section.
|
||||
- Otherwise, include ONE line in the review output: `Version claimed: v<BRANCH_VERSION>. Queue: <CLAIMED_COUNT> PR(s) ahead. <VERDICT>` where VERDICT is either `Slot free` (if `BRANCH_VERSION >= NEXT_SLOT`) or `⚠ queue moved — rerun /ship to reconcile v<BRANCH_VERSION> → v<NEXT_SLOT>`.
|
||||
|
||||
Compare dotted version components as integers from left to right; missing trailing components count as zero.
|
||||
Compare versions numerically per dotted component; missing ones count as zero.
|
||||
|
||||
---
|
||||
|
||||
## Step 3.5: Diff scans
|
||||
|
||||
Run the gate scan first (local, seconds; every diff size), then the slop scan.
|
||||
Run the gate scan first (local; every diff size), then the slop scan.
|
||||
|
||||
### Gate scan
|
||||
|
||||
@@ -143,14 +146,11 @@ category, Step 5.8's record and the final report.
|
||||
|
||||
### Slop scan (advisory)
|
||||
|
||||
Scan changed files for empty catches, redundant `return await` and needless abstractions:
|
||||
|
||||
```bash
|
||||
bun run slop:diff origin/<base> 2>/dev/null || true
|
||||
```
|
||||
|
||||
Include findings as non-blocking informational diagnostics. If slop:diff is
|
||||
unavailable, skip silently.
|
||||
Findings are non-blocking informational diagnostics; skip if unavailable.
|
||||
|
||||
---
|
||||
|
||||
@@ -180,10 +180,8 @@ a clean result. Gate findings are ASK in Step 5 regardless of how mechanical the
|
||||
revert looks. {{FLAKE_FIX_NUMBER:review}}
|
||||
|
||||
**Search-before-recommending:** Research proposed fixes through Aside, especially
|
||||
concurrency, caching, auth and framework behavior:
|
||||
- Check current best practice for the installed framework version.
|
||||
- Look for a newer built-in before proposing a workaround.
|
||||
- Verify API signatures against current docs.
|
||||
concurrency, caching, auth and framework behavior: current best practice for the
|
||||
installed version, newer built-ins that replace a workaround, and current API signatures.
|
||||
|
||||
Prompt file text (create, write and send it with the Web research runs in Aside blocks above): `{framework} {version} {pattern} current best practice and whether a built-in replaces it. Reply with up to 5 bullets, each with its source URL.`
|
||||
|
||||
@@ -352,7 +350,7 @@ Verify claims or flag them as unknown; "this looks fine" is not evidence.
|
||||
|
||||
After outputting your own findings, if Greptile comments were classified in Step 2.5:
|
||||
|
||||
**Include a Greptile summary in your output header:** `+ N Greptile comments (X valid, Y fixed, Z FP)`
|
||||
**Greptile summary in your output header:** `+ N Greptile comments (X valid, Y fixed, Z FP)`
|
||||
|
||||
Before replying to any comment, run greptile-triage.md's **Escalation Detection** to choose Tier 1 (friendly) or Tier 2 (firm) reply templates.
|
||||
|
||||
@@ -367,7 +365,7 @@ Before replying to any comment, run greptile-triage.md's **Escalation Detection*
|
||||
|
||||
3. **VALID BUT ALREADY FIXED comments:** Reply with greptile-triage.md's **Already Fixed reply template**, no AskUserQuestion: what was done and the fixing commit SHA; save to both per-project and global greptile-history.
|
||||
|
||||
4. **SUPPRESSED comments:** Skip silently (known false positives from previous triage).
|
||||
4. **SUPPRESSED comments:** Skip silently.
|
||||
|
||||
---
|
||||
|
||||
@@ -376,16 +374,17 @@ Before replying to any comment, run greptile-triage.md's **Escalation Detection*
|
||||
### 1. Re-review after edits
|
||||
|
||||
1. A pass covers Steps 3–5, including all reviewers before fixes. Allow at most 3 fix cycles:
|
||||
- Edited: increment CYCLES once. Below 3, repeat Steps 3–5 with a new
|
||||
REVIEW_START. At 3, persist `converged:false` and remaining findings by filling
|
||||
and saving the record below. Report nonconvergence and coverage gaps, then STOP
|
||||
this invocation, without a clean summary or a fourth pass.
|
||||
- No edits: fill the record below.
|
||||
- Edited: increment CYCLES once, then fill and save the record below with
|
||||
`converged:false`. Step 5.0 never treats this invocation's records as prior
|
||||
reviews. Below 3, repeat Steps 3–5 with a new REVIEW_START. At 3, report
|
||||
nonconvergence and coverage gaps, then STOP this invocation, without a clean
|
||||
summary or a fourth pass.
|
||||
- No edits: after a full pass, fill the record below. A fix-range pass is never
|
||||
final: repeat Steps 3–5 with a full start.
|
||||
2. On a repeat, execute Steps 3–5 in order. At Step 4.7, reuse only this invocation's
|
||||
unchanged-input QA evidence; rerun affected probes after source, test, contract,
|
||||
command or fixture changes. Reusing a probe never skips a review step.
|
||||
A probe is affected when its entrypoint, dependencies, contract or replay inputs
|
||||
change; if uncertain, rerun it.
|
||||
unchanged-input QA evidence; rerun a probe if its source, tests, entrypoint,
|
||||
dependencies, contract, command, fixture or replay inputs changed, or if uncertain.
|
||||
Reusing a probe never skips a review step.
|
||||
3. **Verify completed actions.** On the final zero-edit pass, reconcile this
|
||||
invocation's actions with current findings. Deduplicate by structural identity
|
||||
and advisory/defect kind. For a completed extraction, retain `fixed` and the
|
||||
@@ -421,7 +420,7 @@ pass: report it with its reason.
|
||||
|
||||
- Use Step 4.6's `specialists` object unchanged, including its empty small-diff map.
|
||||
If this host omits Review Army, use `specialists: {}` without claiming specialist coverage.
|
||||
- Build `findings` from Step 5's combined final-pass findings (core, specialist,
|
||||
- Build `findings` from Step 5's combined findings (core, specialist,
|
||||
adversarial, actionable Greptile, verified exploratory QA findings) and invocation actions. Retain `fingerprint`, `severity`
|
||||
(`CRITICAL|INFORMATIONAL`), `action`, and any `advisory`, `evidence_paths`,
|
||||
`helper_target`. Recheck source after fixes. The logger uses `sharedLibsFingerprint`,
|
||||
@@ -449,11 +448,11 @@ were skipped or this host omits Review Army). This default is not completion evi
|
||||
unresolved non-advisory core defects still count in `issues_found`,
|
||||
`critical`, `informational`. The logger builds trusted `review_binding` from the
|
||||
validated captured branch digest, discarding caller bindings. Never invent a binding
|
||||
or replace REVIEW_START at log time; finish only the final core token.
|
||||
or replace REVIEW_START at log time; finish only this pass's own token.
|
||||
|
||||
### Report the final review
|
||||
|
||||
Emit one final report, merging all reviewers rather than concatenating them:
|
||||
Emit one final report merging all reviewers:
|
||||
1. `Pre-Landing Review: N issues (X critical, Y informational)` counts final unresolved
|
||||
non-advisory defects. State INCOMPLETE if `COMPLETED` is false, even when N=0.
|
||||
2. Use the checklist's action groups with confidence-tagged finding lines. Keep fixed,
|
||||
|
||||
+8
-8
@@ -7,7 +7,7 @@
|
||||
"agy/gstack-plan-design-review": 120811,
|
||||
"agy/gstack-plan-devex-review": 116557,
|
||||
"agy/gstack-plan-eng-review": 144399,
|
||||
"agy/gstack-review": 103605,
|
||||
"agy/gstack-review": 103569,
|
||||
"claude/design-review": 114874,
|
||||
"codex/gstack-autoplan": 108636,
|
||||
"codex/gstack-design-review": 123041,
|
||||
@@ -15,26 +15,26 @@
|
||||
"codex/gstack-plan-design-review": 121883,
|
||||
"codex/gstack-plan-devex-review": 118065,
|
||||
"codex/gstack-plan-eng-review": 145564,
|
||||
"codex/gstack-review": 103128,
|
||||
"codex/gstack-review": 103092,
|
||||
"copilot/gstack-autoplan": 109336,
|
||||
"copilot/gstack-design-review": 122537,
|
||||
"copilot/gstack-plan-design-review": 121122,
|
||||
"copilot/gstack-plan-devex-review": 116019,
|
||||
"copilot/gstack-plan-eng-review": 144564,
|
||||
"copilot/gstack-review": 103186,
|
||||
"copilot/gstack-review": 103150,
|
||||
"cursor/gstack-autoplan": 108568,
|
||||
"cursor/gstack-design-review": 121802,
|
||||
"cursor/gstack-plan-design-review": 119667,
|
||||
"cursor/gstack-plan-devex-review": 115289,
|
||||
"cursor/gstack-plan-eng-review": 143154,
|
||||
"cursor/gstack-review": 120038,
|
||||
"cursor/gstack-review": 120002,
|
||||
"factory/gstack-autoplan": 110846,
|
||||
"factory/gstack-design-review": 123586,
|
||||
"factory/gstack-land-and-deploy": 100108,
|
||||
"factory/gstack-plan-design-review": 122442,
|
||||
"factory/gstack-plan-devex-review": 118652,
|
||||
"factory/gstack-plan-eng-review": 146262,
|
||||
"factory/gstack-review": 123811,
|
||||
"factory/gstack-review": 123775,
|
||||
"gbrain/gstack-autoplan": 108975,
|
||||
"gbrain/gstack-design-review": 112007,
|
||||
"gbrain/gstack-plan-design-review": 108424,
|
||||
@@ -48,7 +48,7 @@
|
||||
"kiro/gstack-plan-design-review": 119519,
|
||||
"kiro/gstack-plan-devex-review": 115141,
|
||||
"kiro/gstack-plan-eng-review": 143016,
|
||||
"kiro/gstack-review": 119862,
|
||||
"kiro/gstack-review": 119826,
|
||||
"openclaw/gstack-autoplan": 108798,
|
||||
"openclaw/gstack-design-review": 110930,
|
||||
"openclaw/gstack-plan-design-review": 107393,
|
||||
@@ -58,12 +58,12 @@
|
||||
"opencode/gstack-plan-design-review": 120954,
|
||||
"opencode/gstack-plan-devex-review": 115897,
|
||||
"opencode/gstack-plan-eng-review": 144423,
|
||||
"opencode/gstack-review": 120660,
|
||||
"opencode/gstack-review": 120624,
|
||||
"slate/gstack-autoplan": 108455,
|
||||
"slate/gstack-design-review": 121715,
|
||||
"slate/gstack-plan-design-review": 119593,
|
||||
"slate/gstack-plan-devex-review": 115215,
|
||||
"slate/gstack-plan-eng-review": 143085,
|
||||
"slate/gstack-review": 119950
|
||||
"slate/gstack-review": 119914
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* #3339: /ship Step 9 may re-review only the fix range, but a fix-range pass
|
||||
* #3339: /ship Step 9 and /review may re-review only the fix range, but a fix-range pass
|
||||
* can never be the last review. The fix base comes from the review log (never
|
||||
* the working tree or the caller) and is the commit whose tree the fixing pass
|
||||
* started from, a narrowed row is never CURRENT and carries no
|
||||
@@ -214,3 +214,75 @@ describe('ship Step 9 instructions', () => {
|
||||
expect(army).toContain('continue to Step 10, and only from a full pass: after a fix-range pass, run one full Step 9 first.');
|
||||
});
|
||||
});
|
||||
|
||||
describe('review Step 3 and Step 5.8 instructions', () => {
|
||||
const skill = fs.readFileSync(path.join(ROOT, 'review/SKILL.md'), 'utf8');
|
||||
const step3 = skill.slice(skill.indexOf('## Step 3: Get the diff'), skill.indexOf('## Step 3.4:'));
|
||||
const step58 = skill.slice(skill.indexOf('## Step 5.8: Persist Eng Review result'), skill.indexOf('### Report the final review'));
|
||||
const flat3 = step3.replace(/\s+/g, ' '), flat58 = step58.replace(/\s+/g, ' ');
|
||||
|
||||
test('the first pass starts full and only the pass after an edited pass narrows its DIFF_BASE, never Step 4.8 or other base uses', () => {
|
||||
const block = step3.slice(step3.indexOf('```bash'), step3.indexOf('```', step3.indexOf('```bash') + 7));
|
||||
expect(block).toContain('gstack-review-log --start review\ngit diff "$DIFF_BASE"');
|
||||
expect(block).not.toContain('--fix-range');
|
||||
expect(flat3).toContain('After an edited pass, start the next with `--start review --fix-range`: it prints REVIEW_START, then `FIX_BASE=<sha>`. Wherever this pass sets DIFF_BASE outside Step 4.8, use FIX_BASE instead; Step 4.8 and every other `<base>` use stay full. On refusal, start a full pass.');
|
||||
expect(skill.match(/--fix-range/g)).toHaveLength(1);
|
||||
});
|
||||
|
||||
test('an edited pass is logged before the repeat, kept out of Step 5.0, and a fix-range pass is never the final review', () => {
|
||||
const edited = flat58.indexOf("Edited: increment CYCLES once, then fill and save the record below with `converged:false`. Step 5.0 never treats this invocation's records as prior reviews.");
|
||||
const repeat = flat58.indexOf('Below 3, repeat Steps 3–5 with a new REVIEW_START.');
|
||||
const none = flat58.indexOf('No edits: after a full pass, fill the record below. A fix-range pass is never final: repeat Steps 3–5 with a full start.');
|
||||
expect(edited).toBeGreaterThan(-1);
|
||||
expect(repeat).toBeGreaterThan(edited);
|
||||
expect(none).toBeGreaterThan(repeat);
|
||||
expect(flat58).toContain("finish only this pass's own token");
|
||||
});
|
||||
});
|
||||
|
||||
describe('review Step 3/5.8 order against the real logger', () => {
|
||||
// /review's order on every pass: core start, Step 4.8 attempt start and finish, fixes in the working tree, core finish; never a commit.
|
||||
const reviewRow = (fields: Record<string, unknown>) => JSON.stringify({ skill: 'review', status: 'clean', issues_found: 0, critical: 0, informational: 0, ...fields });
|
||||
function reviewPass(fields: Record<string, unknown>, start: string[], fixes?: string) {
|
||||
const started = bin('gstack-review-log', start);
|
||||
expect(started.code).toBe(0);
|
||||
const [token, base] = started.out.split('\n');
|
||||
// Step 4.8: each pass's adversarial attempt saves its row before any fix and before the core row.
|
||||
const attempt = bin('gstack-review-log', ['--start', 'adversarial-review']);
|
||||
expect(attempt.code).toBe(0);
|
||||
expect(bin('gstack-review-log', [JSON.stringify({ skill: 'adversarial-review', status: 'clean', source: 'claude', ...clean }), '--finish', attempt.out]).code).toBe(0);
|
||||
if (fixes) edit(fixes);
|
||||
expect(bin('gstack-review-log', [reviewRow(fields), '--finish', token!]).code).toBe(0);
|
||||
return base;
|
||||
}
|
||||
|
||||
test('a committed first pass narrows the next repeat to the uncommitted fixes, then the chain returns to a full pass', () => {
|
||||
const reviewed = head();
|
||||
reviewPass(fixing, ['--start', 'review'], 'export const a = 2;\n');
|
||||
expect(reviewPass(fixing, ['--start', 'review', '--fix-range'], 'export const a = 3;\n')).toBe(`FIX_BASE=${reviewed}`);
|
||||
expect(gitIn(repo, `diff --name-only ${reviewed}`).trim()).toBe('a.ts');
|
||||
const third = narrowStart();
|
||||
expect(third.code).toBe(1);
|
||||
expect(third.err).toContain('started from uncommitted content');
|
||||
reviewPass(clean, ['--start', 'review']);
|
||||
const last = rows().at(-1)!;
|
||||
expect(last.scope).toBeUndefined();
|
||||
expect(reviewFreshness(last, last.wtree)?.status).toBe('CURRENT');
|
||||
}, 30_000);
|
||||
|
||||
test('a zero-edit fix-range pass is never CURRENT even if it were logged, so the final record needs a full pass', () => {
|
||||
reviewPass(fixing, ['--start', 'review'], 'export const a = 2;\n');
|
||||
reviewPass(clean, ['--start', 'review', '--fix-range']);
|
||||
const narrowed = rows().at(-1)!;
|
||||
expect(narrowed.scope).toBe('fix-range');
|
||||
expect(reviewFreshness(narrowed, narrowed.review_binding.range_end_wtree)?.status).toBe('UNVERIFIED');
|
||||
}, 30_000);
|
||||
|
||||
test('a first pass over uncommitted work cannot be narrowed', () => {
|
||||
edit('export const a = 1; // uncommitted\n');
|
||||
reviewPass(fixing, ['--start', 'review'], 'export const a = 2;\n');
|
||||
const r = narrowStart();
|
||||
expect(r.code).toBe(1);
|
||||
expect(r.err).toContain('started from uncommitted content');
|
||||
}, 30_000);
|
||||
});
|
||||
@@ -229,7 +229,8 @@ test('review finalization ownership: initialize invocation state and capture the
|
||||
expect(flat).toMatch(/REVIEW_START for this core candidate before reading its diff/i);
|
||||
expectMentions(flat, [['never', 'reading', 'before']], 'flat');
|
||||
expect(flat).toMatch(/separate PASS_START tokens, not REVIEW_START/);
|
||||
expectMentions(flat, [['only', 'finishes', 'final']], 'flat');
|
||||
expect(flat).toContain('After an edited pass, start the next with `--start review --fix-range`');
|
||||
expect(flat).toContain('On refusal, start a full pass.');
|
||||
});
|
||||
|
||||
test('review finalization ownership: late findings use Fix-First before the bounded parent transition', () => {
|
||||
@@ -240,7 +241,7 @@ test('review finalization ownership: late findings use Fix-First before the boun
|
||||
'Structured approval does not waive advisory/test_stub ASK gates',
|
||||
'## Step 5.8: Persist Eng Review result',
|
||||
'Edited: increment CYCLES once',
|
||||
'No edits: fill the record below',
|
||||
'No edits: after a full pass, fill the record below',
|
||||
'### 2. Fill the record',
|
||||
'--finish REVIEW_START',
|
||||
];
|
||||
@@ -248,7 +249,7 @@ test('review finalization ownership: late findings use Fix-First before the boun
|
||||
expect(positions.every(position => position >= 0)).toBe(true);
|
||||
expect(positions).toEqual([...positions].sort((a, b) => a - b));
|
||||
expect(flat).toContain('at most 3 fix cycles');
|
||||
expect(flat).toContain('At 3, persist `converged:false`');
|
||||
expect(flat).toContain('Edited: increment CYCLES once, then fill and save the record below with `converged:false`.');
|
||||
const limit = flat.slice(flat.indexOf('At 3,'), flat.indexOf('No edits:'));
|
||||
expect(limit).toMatch(/then stop this invocation/i);
|
||||
expectMentions(limit, [['without', 'summary', 'fourth']], 'limit');
|
||||
@@ -276,14 +277,14 @@ test('review finalization ownership: required native completion and optional out
|
||||
expect(flat).toContain('`CONVERGED`: true only for a completed zero-edit pass');
|
||||
});
|
||||
|
||||
test('review finalization ownership: finish only the final core token without log-time capture', () => {
|
||||
test('review finalization ownership: each logged pass finishes its own core token without log-time capture', () => {
|
||||
const step = skill.slice(skill.indexOf('## Step 5.8: Persist Eng Review result'));
|
||||
const flat = step.replace(/\s+/g, ' ');
|
||||
expect(step.match(/--finish REVIEW_START/g)).toHaveLength(1);
|
||||
expect(step).not.toContain('--start review');
|
||||
expect(step).not.toContain('--finish PASS_START');
|
||||
expect(flat).toMatch(/never invent a binding or replace REVIEW_START at log time/i);
|
||||
expectMentions(flat, [['only', 'finish', 'final']], 'flat');
|
||||
expect(flat).toContain("finish only this pass's own token");
|
||||
expect(step).toContain('"completed":COMPLETED,"converged":CONVERGED,"cycles":CYCLES');
|
||||
});
|
||||
|
||||
|
||||
Reference in new issue
Block a user