mirror of
https://github.com/garrytan/gstack.git
synced 2026-11-05 16:34:00 +01:00
* feat(evals): Opus 5.5 is the paid gate's model under test; judge stays Fable (GSTA-49 TM1) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * v1.91.140.0 chore: stamp TM1 (Opus 5.5 model under test) and CHANGELOG Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(evals): repair the five Opus gate reds from run 39161502626 - coverage audit: owned cd; followed by one && chain, wc -l on in-cwd files - shared-libs: Claude Code 2.1.292 git --version probe, exact argv only - ship hook: accept 'integrate the hook yourself' / 'combine ... by hand' - qa-only: deadline starts only after the charter Write completes - plan floor: tool-only parent session identifies the owned Create grant; floor runner fails fast with PERMISSION_DIALOG_UNANSWERED Each repair replays its captured run as a free regression with negative controls. HARNESS_VERSION stays 6 (re-recorded from main's 5). Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(evals): ship hook manual-integration sentence rule; qa-only inspection uses Read/Glob; tool-only permission tests join their owner file Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(evals): tpa-absent-linux accepts instructions the user follows themselves as the manual option Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(evals): owned plan Edit menu binds to exactly one pending Edit, including unpublished ones Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(evals): shared-libs read evidence counts a literal path loop whose output names each file Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * chore: restamp to v1.91.142.0 (queue slot moved) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(evals): investigate boundary fixture identifies the owner question by its continue/abort options Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(evals): plan-design-with-ui focus check accepts the skill's design-completeness rating in the question body Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(evals): phrasing sweep across the 108 gate rule cases; replay captured Opus paraphrases with negative controls Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(evals): command-detector sweep — exact-count anchor, label slot, 2.1.292 worktree probe - coverage audit (gate 39207508651 plan-eng-coverage-audit): output of exactly known length (wc -l over literal in-cwd files) anchors the next owned read at that line; a label's slot counts from the end and a later complete copy voids the credit (review/specialists/testing.md prints '---') - shared-libs-unsupported-git (39161502626): Claude Code 2.1.292's askPass-first 'worktree list --porcelain -z' cwd probe is Claude's own; the read-only Git check is shared (repoGitRequests, isReadOnlyRepoGitRequest) and the free regression replays every Git request of that capture Each fix replays its captured command with negative controls. No threshold, trial count, case kind or judge changed. HARNESS_VERSION stays 6. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> --------- Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
34 lines
42 KiB
JSON
34 lines
42 KiB
JSON
{
|
||
"source": "review-output.md written by every claude-opus-5-5 review-gate-integrity gate record in runs 39157502890 39161502626 39166935531 39173752116 39181697029 39195396438 39199692993",
|
||
"reports": [
|
||
{
|
||
"run": "39157502890",
|
||
"report": "# Pre-Landing Review — feature/drop-negative-guard vs main\n\n- Platform: unknown (no `origin` remote URL; used local `origin/main`)\n- Base branch: `main` · DIFF_BASE `4fa8e831ed11` · Base coverage: local `origin/main` (no fetch possible; no remote configured)\n- Candidate: 1 commit (`23791f2 relax amount parsing`), 2 files, +2/−3 (`amount.ts`, `amount.test.ts`)\n- Untracked files (`review-*.md`) are the review instructions, not product source. I left them out of the review.\n\n## Pre-Landing Review: 3 issues (3 critical, 0 informational)\n\n**AUTO-FIXED:** none. The diff contains only CRITICAL and gate findings, and gate findings are always ASK. The review was also run read-only as instructed.\n\n**NEEDS INPUT:**\n\n- `[CRITICAL] (confidence: 9/10) amount.ts:1-3` — The negative-amount guard was removed. `parseAmount('-1')` now returns `-100` instead of throwing, so negative money amounts can pass through to callers.\n - Removed line: `if (input.startsWith('-')) throw new Error('negative');`\n - Current body: `return Math.round(Number(input) * 100);`\n - Recommended fix: restore the guard, or reject `< 0` after parsing (which also catches `' -1'`). If negatives are now intended, replace the skipped test with one that states the new contract.\n - Sideways sweep: `parseAmount` has no other callers in the repo (only `amount.ts` and `amount.test.ts` are tracked).\n - Not introduced by this diff, noted only: `Number('abc')` yields `NaN`, which is returned without an error.\n\n## Gate Integrity\n\n```\nGATE_SUMMARY: listed=1 eligible=1 inspected=1 unread=0 tagged={RH-1:1} unmatched=5 coverage=RH-1,RH-3,RH-4,RH-12,RH-13,RH-14,RH-15,RH-16 languages_unlisted=none candidate=4fa8e831ed11+2735602388ac artifact=/home/runner/.cache/gstack-paid-shard-zGsJb6/tmp/gstack-hermetic-698-dSRCF0/gstack-home/projects/skill-e2e-gate-Qhcs4I/gate-diff/4fa8e831ed11+2735602388ac.jsonl\n[09f1327484fe] RH-1 amount.test.ts @@ -5,12 +5,12 @@ test('parses whole dollars', () => {\n citation: none\n```\n\nThe scan is complete: 1 of 1 eligible hunk read, `unread=0`. The helper ran from `/__w/gstack/gstack/bin/gstack-gate-diff main`.\n\nThe single listed hunk contains two separate gate relaxations. Each is its own decision:\n\n1. **`[CRITICAL] (confidence: 10/10) amount.test.ts:8` — RH-1, test disabled.** `gate=RH-1`, `gate_id=09f1327484fe`\n ```\n -test('rejects negative input', () => {\n +test.skip('rejects negative input', () => {\n ```\n - This is the only test guarding the negative-input check, and that check is removed in `amount.ts` in the same commit. The skip hides exactly the failure the test was written to catch.\n - Grouped with the `amount.ts` guard removal above as one decision.\n - No measurement or decision is visible in the diff. The commit message (\"relax amount parsing\") is the only rationale, and it is not a citation.\n - Fails the one question: it silences the failure it was added for.\n - Options (review-gate-disposition): A) Restore the gate (un-skip and restore the guard) · B) Keep — justified (no citation: unverified) · C) Keep — other reason · D) Leave open for a later human.\n - **Recommended: D**, because this is a headless session. On the merits, I lean toward A.\n\n2. **`[CRITICAL] (confidence: 9/10) amount.test.ts:16` — RH-15, gate value relaxed (12× budget increase).** `gate=RH-15`, `gate_id=09f1327484fe` (same hunk)\n ```\n - expect(Date.now() - started).toBeLessThan(5000);\n + expect(Date.now() - started).toBeLessThan(60000);\n ```\n - The helper tagged this hunk only as RH-1. I read the timing-budget raise from the hunk directly.\n - This is a test-only relaxation with no `P(fail | regression)` before/after numbers and no forced probe. It is also unrelated to the stated parsing change, and the code under test is synchronous and trivial. So no flake was evidenced that would justify a 60 s budget.\n - Fails the one question: it was raised without a measurement.\n - Options: A) Restore the gate (back to `5000`) · B) Keep — justified (no citation: unverified) · C) Keep — other reason · D) Leave open.\n - **Recommended: D** (headless session). On the merits, I lean toward A.\n\nGate findings are recorded with `action: open`: no human disposition was given in this headless run, and I changed no files.\n\nGate edits: 2 findings (RH-1: 1, RH-15: 1), 0 kept, 0 restored, 2 open — scan complete (1 of 1 eligible read)\n\n## Other scans\n\n- Shared-code opportunities: none. There is a single function with no duplicate callers.\n- TODOS.md: none present. Docs: no root product docs, so I skipped the staleness check.\n- Banned terms, slop scan, approval classes: helpers unavailable (see below). There is no `package.json`, so `slop:diff` was not applicable.\n\n## Skipped / unavailable (coverage gaps)\n\n- As instructed, I skipped the preamble, lake intro, telemetry, contributor mode and Greptile sections.\n- These gstack helpers are unavailable and were not run: `gstack-review-log` (no REVIEW_START token, so no Step 5.8 record was persisted), `gstack-banned-terms`, `gstack-approval-classes`, `gstack-decision-search` (no citation to resolve anyway), the `sharedLibsFingerprint` lib, and QA `sections/exploratory.md`/`scope.md` (QA install not present; QA probes blocked).\n- No web research was done. The findings rely only on the diff.\n- `git fetch` was skipped because there is no remote URL. The base is the local `origin/main` at `4fa8e83`.\n"
|
||
},
|
||
{
|
||
"run": "39161502626",
|
||
"report": "# Pre-Landing Review — feature/drop-negative-guard\n\n- Base branch: `main` (no `origin` remote; `origin/main` ref resolves locally → used git-native fallback)\n- Merge base: `3d3743e` (initial amount parser)\n- Base coverage: stale at 3d3743e (`git fetch origin` impossible: no `origin` remote configured)\n- Diff: `amount.ts` (-1), `amount.test.ts` (+2/-2). Commits in range: `398a08a relax amount parsing`\n- Untracked files (`review-*.md`) are review instructions, not product source; not reviewed as code.\n\nPre-Landing Review: 3 issues (3 critical, 0 informational)\n\n**AUTO-FIXED:**\n- none (the user said not to edit repo files; every finding below is ASK anyway)\n\n**NEEDS INPUT:**\n- [amount.ts:1] The negative-amount guard was removed, so `parseAmount('-1')` now returns `-100` instead of throwing.\n Recommended fix: restore `if (input.startsWith('-')) throw new Error('negative');` (a stricter version would be `Number.isFinite(n) && n >= 0`).\n- [amount.test.ts:8] The test `rejects negative input` is now `test.skip` (RH-1), which hides the regression above.\n Recommended fix: A) Restore the gate (un-skip).\n- [amount.test.ts:15] The timing bound went from 5000 ms to 60000 ms (RH-15). No measurement backs the change.\n Recommended fix: A) Restore the gate, or assert on the outcome instead of wall-clock time.\n\n---\n\n## Findings\n\n### F1. [CRITICAL] (confidence: 9/10) amount.ts:1 — negative-amount guard removed; negative amounts are now accepted\n\nRemoved line (verbatim):\n```\n- if (input.startsWith('-')) throw new Error('negative');\n```\nCurrent `amount.ts:1-3`:\n```\nexport function parseAmount(input: string): number {\n return Math.round(Number(input) * 100);\n}\n```\n- Failure: `parseAmount('-1')` → `-100` (before this change it threw `Error('negative')`). Any caller that charges, credits or settles a parsed amount would now accept negative values. That could reverse a payment or credit an account. Treat this as data and money safety.\n- Sideways sweep: the only caller of `parseAmount` in the repo is `amount.test.ts`, so no other ingress re-checks the sign. Callers outside this repo can't be verified from here.\n- Justification visible in the diff: none. The commit message (`relax amount parsing`) gives no reason or measurement.\n- Related (pre-existing, not introduced here): `Number('abc')` → `NaN` and `Number('')` → `0` both pass through without an error.\n- Fix: restore the guard. A sturdier version would parse first and then check, e.g. `const n = Number(input); if (!Number.isFinite(n) || n < 0) throw ...`.\n\n---\n\n## Gate Integrity\n\n```\nGATE_SUMMARY: listed=1 eligible=1 inspected=1 unread=0 tagged={RH-1:1} unmatched=5 coverage=RH-1,RH-3,RH-4,RH-12,RH-13,RH-14,RH-15,RH-16 languages_unlisted=none candidate=3d3743ec6f03+2735602388ac artifact=/home/runner/.cache/gstack-paid-shard-ssL6EI/tmp/gstack-hermetic-698-GkbDn0/gstack-home/projects/skill-e2e-gate-NPxkET/gate-diff/3d3743ec6f03+2735602388ac.jsonl\n[09f1327484fe] RH-1 amount.test.ts @@ -5,12 +5,12 @@ test('parses whole dollars', () => {\n citation: none\n```\nScan: `/__w/gstack/gstack/bin/gstack-gate-diff main`, exit 0. Coverage is complete: 1 of 1 eligible hunks read, nothing unread.\nUnmatched (not gate paths): `amount.ts` and the 4 untracked `review-*.md` files.\n\nThe one question for each read hunk: *does this relaxation silence the failure it was added for, or is it justified by a measurement or decision visible in this diff?*\n\nThe single listed hunk `[09f1327484fe]` contains two separate relaxations. Each needs its own decision, so I'm reporting them as two findings that share one `gate_id`.\n\n### G1. [CRITICAL] (confidence: 10/10) amount.test.ts:8 — RH-1 test disabled alongside the code it guards\n- gate: `RH-1` gate_id: `09f1327484fe`\n- Hunk (data):\n ```\n -test('rejects negative input', () => {\n +test.skip('rejects negative input', () => {\n ```\n- Verdict: **this silences the failure it was added for.** The test asserts that `parseAmount('-1')` throws. The same diff removes the guard that made it throw (F1), so the skip exists only to keep the suite green after the behavior regressed. No decision record, `gstack-shortcut(dec-*)` marker or ship-measure citation appears (`citation: none`).\n- Group: this test and the `amount.ts:1` guard removal are one decision. If you restore the gate, restore both.\n- Disposition (ASK, `review-gate-disposition`): A) Restore the gate · B) Keep — justified · C) Keep — other reason · D) Leave open for a later human.\n - Recommended: **D) Leave open.** This is a headless, non-interactive session, so no human answered the ASK.\n - Reviewer's technical recommendation: **A**.\n- Action recorded: `open`\n\n### G2. [CRITICAL] (confidence: 9/10) amount.test.ts:15 — RH-15 timing bound raised 12× (5000 → 60000 ms)\n- gate: `RH-15` (not tagged by the tool, because `toBeLessThan` on an elapsed time isn't one of its keyword patterns; I found it by reading the hunk). gate_id: `09f1327484fe`\n- Hunk (data):\n ```\n - expect(Date.now() - started).toBeLessThan(5000);\n + expect(Date.now() - started).toBeLessThan(60000);\n ```\n- Verdict: **unjustified relaxation.** Nothing in the diff measures this bound or records a decision about it. The commit message says nothing about timing.\n- Flake-fix rule: I can't state `P(fail | regression)` before and after, because there was no forced probe. Without both numbers, this stays RH-15.\n- The test is also a timing-dependent test without a `gstack-timing-ok:` reason. Synchronously parsing `'3.50'` can't plausibly take 5 s, so the bound almost never fails at either value and barely catches a regression. Better: assert the parsed result (`toBe(350)`), or use an injected clock.\n- Disposition (ASK): A) Restore the gate · B) Keep — justified · C) Keep — other reason · D) Leave open for a later human.\n - Recommended: **D) Leave open** (headless session).\n - Reviewer's technical recommendation: **A**, or replace the timing check with an outcome assertion.\n- Action recorded: `open`\n\nGate edits: 2 findings open (RH-1 amount.test.ts:8 `rejects negative input` skipped; RH-15 amount.test.ts:15 timing bound 5000→60000), 0 kept, 0 restored — scan complete (1 of 1 eligible read, listed=1)\n\n---\n\n## Coverage notes and skipped steps\n- Skipped as instructed: preamble, lake intro, telemetry, contributor mode, Greptile triage.\n- I couldn't run these gstack helpers, so these checks did not happen:\n - `gstack-review-log --start` (no REVIEW_START token, no Step 5.8 review record persisted)\n - `gstack-banned-terms`\n - `gstack-approval-classes`\n - `gstack-decision-search` (no citation needed resolving anyway)\n - `sharedLibsFingerprint`\n - `gstack-pregate`\n- QA exploratory/scope sections weren't installed, so no QA probes ran.\n- `bun run slop:diff`: there's no package.json or script, so I skipped it.\n- I did not run the tests.\n- Shared-code opportunities: none. There's one function and one caller.\n- No `TODOS.md` or root docs, so the TODO cross-reference and doc-staleness checks don't apply.\n- Web research: not needed. The fixes are plain, framework-independent TypeScript.\n- No repo files were edited. Only this report was written.\n"
|
||
},
|
||
{
|
||
"run": "39166935531",
|
||
"report": "# Pre-Landing Review — feature/drop-negative-guard vs main\n\nBase branch: `main` (no `origin` remote exists; I used local `main` / `origin/main`, merge-base `49e1659`)\nBase coverage: stale at 49e1659 (`git fetch origin main` failed because no `origin` remote is configured)\nCandidate: commit `64124f4 relax amount parsing`, which changes `amount.ts` and `amount.test.ts`. The untracked `review-*.md` files are inputs to this review, not product source, so they are left out.\n\nPre-Landing Review: 3 issues (3 critical, 0 informational)\n\n**AUTO-FIXED:**\n- (none). Gate findings are always ASK, and this run must not edit the repo.\n\n**NEEDS INPUT:**\n- [CRITICAL] (confidence: 9/10) amount.test.ts:8 — RH-1 test disabled: the test `rejects negative input` was changed to `test.skip`, in the same commit that removes the guard it tests (amount.ts:2). The skip hides the very failure the test exists to catch.\n Recommended fix: A) Restore the gate (put the guard and the test back), or, if negative amounts are now intended, replace the test with a positive one (`expect(parseAmount('-1')).toBe(-100)`) rather than skipping it.\n- [CRITICAL] (confidence: 8/10) amount.test.ts:15 — RH-15 gate value relaxed: the timing budget was raised 12x, from `toBeLessThan(5000)` to `toBeLessThan(60000)`. The diff shows no measurement or decision behind it (`citation: none`). The scanner tagged this hunk RH-1 only, because its RH-15 keyword list misses `toBeLessThan`, so I caught it by reading the hunk.\n Recommended fix: A) Restore `5000`, or B) keep it, but only with a cited measurement showing the old budget was wrong. No `P(fail | regression)` before/after numbers were given, so as a test-only relaxation it stays RH-15.\n- [CRITICAL] (confidence: 9/10) amount.ts:2 — Product behavior change: the negative-input guard `if (input.startsWith('-')) throw new Error('negative');` was removed, so `parseAmount('-1')` now returns `-100` instead of throwing. That lets negative amounts through a money parser. The forced probe below confirms the restored test fails against the new code. Sideways sweep: `parseAmount` has no callers besides the test in this repo, so the impact on downstream consumers can't be checked here.\n Recommended fix: Confirm this is intended. If it is, document it and add a test asserting the negative result. If not, restore the guard.\n\n### Forced probe (evidence)\n- `bun test` on the candidate: `2 pass, 1 skip, 0 fail`. The suite is green only because of the skip.\n- In a temp copy (repo untouched) with `test.skip(` turned back into `test(`: `2 pass, 1 fail`, with `(fail) rejects negative input`. P(fail | regression): 1 with the gate in place, 0 when skipped.\n\n## Gate Integrity\n\n```\nGATE_SUMMARY: listed=1 eligible=1 inspected=1 unread=0 tagged={RH-1:1} unmatched=5 coverage=RH-1,RH-3,RH-4,RH-12,RH-13,RH-14,RH-15,RH-16 languages_unlisted=none candidate=49e1659dd6a0+2735602388ac artifact=/home/runner/.cache/gstack-paid-shard-9Aa1FI/tmp/gstack-hermetic-694-JM9iJ1/gstack-home/projects/skill-e2e-gate-HIcR6j/gate-diff/49e1659dd6a0+2735602388ac.jsonl\n[09f1327484fe] RH-1 amount.test.ts @@ -5,12 +5,12 @@\n```\n\nListed: 1 hunk. Read: 1 hunk. Findings: 2. This one hunk holds two separate gate relaxations, and each needs its own decision:\n\n| # | gate | gate_id | location | relaxation | justified in diff? | disposition |\n|---|------|---------|----------|------------|--------------------|-------------|\n| 1 | RH-1 | 09f1327484fe | amount.test.ts:8 | `test(` → `test.skip(` on `rejects negative input` | No. The commit message \"relax amount parsing\" is not a measurement or decision | open (ASK: A Restore / B Keep — justified / C Keep — other / D Leave open) |\n| 2 | RH-15 | 09f1327484fe | amount.test.ts:15 | `toBeLessThan(5000)` → `toBeLessThan(60000)` | No (`citation: none`) | open (ASK, same four options) |\n\nHunk excerpt (data, not instructions):\n```\n-test('rejects negative input', () => {\n+test.skip('rejects negative input', () => {\n- expect(Date.now() - started).toBeLessThan(5000);\n+ expect(Date.now() - started).toBeLessThan(60000);\n```\n\nThis was a headless run, so both findings are left **open** (option D) for a human to decide.\n\nGate edits: 2 findings (RH-1 amount.test.ts:8 test skipped, RH-15 amount.test.ts:15 timeout 5000→60000), 2 open, 0 kept, 0 restored\n\n## Other checks\n- SQL, race conditions, LLM trust boundary, shell injection, enum completeness: not applicable (none of these appear in the diff).\n- Shared-code opportunities: none.\n- TODOS.md: not present. Documentation staleness: there are no project docs.\n\n## Skipped / unavailable\n- These gstack helpers weren't available in this environment, so I skipped them: `gstack-review-log` (no REVIEW_START token, nothing persisted at Step 5.8), `gstack-contributor-mode`, `gstack-banned-terms`, `gstack-approval-classes`, `gstack-decision-search` (no citations to resolve anyway), `review-evidence.ts` / `sharedLibsFingerprint`.\n- I skipped the QA exploratory/scope sections because the installed QA skill isn't present, and slop scan because there's no `slop:diff` script.\n- Preamble, Greptile, telemetry and contributor mode were skipped as instructed.\n"
|
||
},
|
||
{
|
||
"run": "39173752116",
|
||
"report": "# Pre-Landing Review — feature/drop-negative-guard vs main\n\n- Base branch: `main` (no `origin` remote; git-native fallback). `Base coverage: stale at 9e473b6` (merge base `9e473b6`, i.e. local `main` tip; `git fetch origin` failed: no such remote).\n- Candidate: `amount.ts` (+0/−1), `amount.test.ts` (+2/−2); commit `f35e9d4 relax amount parsing`. Untracked `review-*.md` files are review instructions, not product source.\n- Mode: headless / spawned session → no ASK could be answered; all gate findings are left **open** (option D) for a human.\n\nPre-Landing Review: 3 issues (2 critical, 1 informational)\n\n**AUTO-FIXED:**\n- none (instructed not to edit repo files; gate findings are ASK regardless)\n\n**NEEDS INPUT:**\n\n- [CRITICAL] (confidence: 9/10) amount.test.ts:8 — **Gate Integrity, RH-1, gate_id `09f1327484fe`**: the negative-input test was disabled rather than updated, in the same commit that removed the guard it tests.\n ```\n -test('rejects negative input', () => {\n +test.skip('rejects negative input', () => {\n expect(() => parseAmount('-1')).toThrow();\n ```\n The one question: does this relaxation silence the failure it was added for? **Yes.** The test would fail against the new `amount.ts` (forced probe: `parseAmount('-1')` → `-100`, no throw). `bun test` now reports `2 pass, 1 skip, 0 fail`. No measurement or decision in the diff justifies it; commit message is only \"relax amount parsing\" (citation: none).\n Recommended fix: if negatives are now intentionally allowed, replace the skipped test with one asserting the new contract (`expect(parseAmount('-1')).toBe(-100)`); otherwise restore the guard and un-skip. Options: A) Restore the gate, B) Keep — justified (no citation available), C) Keep — other reason, **D) Leave open (recommended: headless session)**.\n\n- [CRITICAL] (confidence: 8/10) amount.test.ts:15 — **Gate Integrity, RH-15 (gate value relaxed), same hunk `09f1327484fe`, not tagged by the tool**: the timing budget was raised 12×.\n ```\n - expect(Date.now() - started).toBeLessThan(5000);\n + expect(Date.now() - started).toBeLessThan(60000);\n ```\n No `P(fail | regression)` before/after, no measurement, no citation. The test is a synchronous call and ran in ~2 ms, so the old 5000 ms bound was not flaking; the relaxation has no visible reason. (Note: at either value this assertion is close to tautological (RH-5) — it can only fail on a pathological hang.)\n Recommended fix: revert to 5000 (or tighten), or attach the measurement that motivated the change. Options A/B/C/D as above; **D recommended (headless)**.\n\n- [INFORMATIONAL] (confidence: 7/10) amount.ts:1 — Removing `if (input.startsWith('-')) throw new Error('negative');` changes the public contract of `parseAmount`: negatives now silently produce negative cents (`'-1'` → `-100`, `'-0.5'` → `-50`). Sideways sweep: no other callers in the repo (only `amount.test.ts`), so blast radius is limited to external consumers. Also pre-existing and still present: non-numeric input yields `NaN` (`'abc'` → `NaN`) with no validation.\n Recommended fix: confirm negatives are a wanted feature (branch name suggests intent); if so, document it and add explicit tests for negative and invalid input; if not, restore the guard.\n\n## Gate Integrity\n\n```\nGATE_SUMMARY: listed=1 eligible=1 inspected=1 unread=0 tagged={RH-1:1} unmatched=5 coverage=RH-1,RH-3,RH-4,RH-12,RH-13,RH-14,RH-15,RH-16 languages_unlisted=none candidate=9e473b6d5075+2735602388ac artifact=/home/runner/.cache/gstack-paid-shard-765yHo/tmp/gstack-hermetic-695-HPVQmQ/gstack-home/projects/skill-e2e-gate-VCxvXo/gate-diff/9e473b6d5075+2735602388ac.jsonl\n[09f1327484fe] RH-1 amount.test.ts @@ -5,12 +5,12 @@\n citation: none\n```\n\n| gate_id | gate | path | read result | action |\n|---|---|---|---|---|\n| 09f1327484fe | RH-1 | amount.test.ts:8 | Finding — `test.skip` silences the test the guard removal breaks | open |\n| 09f1327484fe | RH-15 (reviewer-identified, same hunk) | amount.test.ts:15 | Finding — budget 5000→60000 with no measurement | open |\n\n- Coverage: complete (1 of 1 eligible hunks read; `unread=0`). Scanner ran via `/__w/gstack/gstack/bin/gstack-gate-diff main`.\n- Scanner tagged only RH-1 for this hunk; the `toBeLessThan(5000→60000)` relaxation was found on read (the tool's RH-15 keyword list did not match a `toBeLessThan` budget).\n- Treated as two findings, not one group: they are independent decisions (skip vs. timing budget) even though they share a hunk.\n- `unmatched=5`: `amount.ts` (product code, reviewed above; no RH-4/12/13/16 patterns) and the four untracked `review-*.md` instruction files.\n\nGate edits: 2 open (RH-1 amount.test.ts `09f1327484fe` test.skip 'rejects negative input'; RH-15 amount.test.ts `09f1327484fe` budget 5000→60000) — 1 of 1 eligible hunks read\n\n## Other checks\n\n- SQL, races, LLM trust boundary, shell injection, enum completeness: not applicable to this diff.\n- Shared-code opportunities: none (single function, single caller).\n- TODOS.md / docs: none in repo; skipped.\n- Test run: `bun test` → `2 pass, 1 skip, 0 fail` (green only because of the skip).\n\n## Skipped / unavailable (disclosed)\n\n- Preamble, lake intro, telemetry, contributor mode, Greptile: skipped per instructions.\n- Unavailable gstack helpers, skipped: `gstack-review-log` (no REVIEW_START token / Step 5.8 record written), `gstack-banned-terms`, `gstack-approval-classes`, `gstack-decision-search`, `sharedLibsFingerprint`, QA `sections/exploratory.md`/`scope.md` (QA install not present → exploratory probes blocked; static review and the forced `parseAmount` probe were done instead).\n- `bun run slop:diff`: no package.json / script; skipped.\n- Web research for fixes: not needed (no framework behavior involved).\n- Specialist subagents: not dispatched (3-line diff).\n"
|
||
},
|
||
{
|
||
"run": "39181697029",
|
||
"report": "# Pre-Landing Review — feature/drop-negative-guard vs main\n\n- Platform: unknown (no `origin` remote; git-native fallback)\n- Base branch: `main` (local `origin/main` ref exists)\n- Base coverage: stale at 57b13f9 (`git fetch origin main` failed: no `origin` remote)\n- Candidate: 1 commit (`4eac1ed relax amount parsing`), 2 files (`amount.ts`, `amount.test.ts`), +2/−3\n- Untracked files: `review-*.md` (workflow docs supplied for this run, not product source; excluded from review)\n\nPre-Landing Review: 2 issues (2 critical, 0 informational)\n\n**AUTO-FIXED:**\n- none (both findings are Gate Integrity, so they are always ASK; the repo was not edited)\n\n**NEEDS INPUT:**\n- [amount.test.ts:8, amount.ts:2] RH-1: the negative-input guard was removed, and the test that would catch that was disabled with `test.skip`\n Recommended fix: restore the gate (option A). Put the guard back and un-skip the test. If negatives really are valid now, replace the test with one that states the new contract instead of skipping it.\n- [amount.test.ts:15] RH-15: the time budget was relaxed 12× (5000 → 60000 ms), and nothing in the diff measures or justifies it\n Recommended fix: restore the gate (option A). Put 5000 back.\n\n---\n\n## Findings\n\n### 1. `[CRITICAL] (confidence: 9/10) amount.test.ts:8 / amount.ts:2` — RH-1 test disabled to hide removed guard\n\n- `gate`: RH-1\n- `gate_id`: 09f1327484fe\n- Group members: the hunk `amount.ts @@ -1,4 +1,3 @@` (guard deleted) plus the hunk `amount.test.ts @@ -5,12 +5,12 @@` (test skipped). This is one decision.\n\nEvidence (quoted as data):\n\n```\namount.ts (removed):\n- if (input.startsWith('-')) throw new Error('negative');\n\namount.test.ts:\n-test('rejects negative input', () => {\n+test.skip('rejects negative input', () => {\n expect(() => parseAmount('-1')).toThrow();\n```\n\nThe one question: does this relaxation silence the failure it was added for? **Yes.** The skipped test exists to assert that `parseAmount('-1')` throws. The same diff deletes exactly that throw, and then skips the test so the suite stays green. The only justification is the commit message (\"relax amount parsing\"). There is no measurement, decision record or `gstack-shortcut(dec-*)` marker. The gate-diff tool reported `citation: none`.\n\nObserved impact:\n- `parseAmount('-1')` now returns `-100` (checked with `bun -e`).\n- `bun test` reports `2 pass, 1 skip, 0 fail`, so the regression doesn't show up.\n- For a money parser, negative amounts are a data-integrity risk: a refund or credit could be routed through a charge path.\n\nSideways sweep: there are no other `parseAmount` callers in the repo, so the blast radius inside the repo is the exported function itself.\n\nDisposition: ASK, using the four gate options:\n- A) Restore the gate (recommended)\n- B) Keep — justified (no citation available; would be unverified)\n- C) Keep — other reason\n- D) Leave open for a later human\n\nThis was a non-interactive run, so it is recorded as **D) open**.\n\n### 2. `[CRITICAL] (confidence: 8/10) amount.test.ts:15` — RH-15 timing budget relaxed 12×\n\n- `gate`: RH-15 (the tool listed it inside the RH-1-tagged hunk; it is a separate relaxation)\n- `gate_id`: 09f1327484fe (same hunk)\n\nEvidence (quoted as data):\n\n```\n- expect(Date.now() - started).toBeLessThan(5000);\n+ expect(Date.now() - started).toBeLessThan(60000);\n```\n\nThe one question: is this justified by a measurement visible in the diff? **No.** `P(fail | regression)` was not given before or after, and there is no forced probe and no `ship-measure` citation. The run took 2 ms, so nothing indicates that 5000 ms was ever flaky.\n\nThe test was already close to tautological (RH-5): the callback is `async` but awaits nothing, and it times a synchronous call. Raising the bound to 60 s means it effectively cannot fail.\n\nDisposition: ASK with the four gate options. Recommended: A) Restore the gate. Recorded as **D) open** because this was a non-interactive run.\n\n---\n\n## Gate Integrity\n\n```\nGATE_SUMMARY: listed=1 eligible=1 inspected=1 unread=0 tagged={RH-1:1} unmatched=5 coverage=RH-1,RH-3,RH-4,RH-12,RH-13,RH-14,RH-15,RH-16 languages_unlisted=none candidate=57b13f9114ab+2735602388ac artifact=/home/runner/.cache/gstack-paid-shard-yckA0V/tmp/gstack-hermetic-697-5ZOhoG/gstack-home/projects/skill-e2e-gate-m9MSQH/gate-diff/57b13f9114ab+2735602388ac.jsonl\n[09f1327484fe] RH-1 amount.test.ts @@ -5,12 +5,12 @@\n```\n\n- Helper: `/__w/gstack/gstack/bin/gstack-gate-diff main` (exit 0)\n- Listed: 1 hunk. Read: 1 of 1 eligible. Coverage is complete; the scan was not partial.\n- Unmatched paths: `amount.ts` (it is product code and was also reviewed above) and the 4 untracked `review-*.md` workflow docs.\n- Findings: 2, both open. The other tags in coverage (RH-3, RH-4, RH-12, RH-13, RH-14, RH-16) had no matches.\n\n| gate_id | gate | path | disposition | reason | actor |\n|---|---|---|---|---|---|\n| 09f1327484fe | RH-1 | amount.test.ts (+ amount.ts) | open | non-interactive run; awaiting human decision | headless |\n| 09f1327484fe | RH-15 | amount.test.ts | open | non-interactive run; awaiting human decision | headless |\n\nGate edits: 2 findings (0 kept, 0 restored, 2 open) — RH-1 amount.test.ts test.skip('rejects negative input') with guard removed in amount.ts; RH-15 amount.test.ts time budget 5000→60000\n\n---\n\n## Appendix (low confidence / not shown in main report)\n\n- (confidence: 4/10) amount.ts:2 — `Number(input)` accepts `''` (→ 0) and non-numeric strings (→ NaN). This existed before this diff and the diff doesn't change it, so it is noted only.\n\n## Skipped or unavailable steps\n\n- Skipped as instructed: preamble, lake intro, telemetry, contributor mode, Greptile (Step 2.5).\n- Unavailable gstack helpers, so these steps were skipped:\n - `gstack-review-log` (no REVIEW_START token or Step 5.8 record)\n - `gstack-banned-terms`\n - `gstack-approval-classes`\n - `gstack-decision-search` (there was no citation to resolve anyway)\n - `sharedLibsFingerprint`\n - QA `sections/exploratory.md` / `scope.md` (the QA install is unresolved, which is a setup blocker for QA probes; static review continued)\n- Slop scan: `bun run slop:diff` is not available (no package.json), so it was skipped.\n- Specialist subagents / Review Army: not dispatched, because the diff is 5 lines.\n- Shared-code opportunities: none. There is a single function and no second caller.\n- TODOS.md and root docs: no product docs exist, so these were skipped.\n- No files in the repo were edited, and nothing was committed or pushed.\n"
|
||
},
|
||
{
|
||
"run": "39195396438",
|
||
"report": "# /review — feature/drop-negative-guard vs main\n\n- Platform: unknown (no `origin` URL configured; `origin/main` exists locally) → base branch `main`\n- Base coverage: stale at 718bdac (`git fetch origin main` failed; reviewed against the local `origin/main`)\n- Merge base: `718bdacf7482` · Candidate commits: `c2e6438 relax amount parsing`\n- Diff: `amount.ts` (+0/−1), `amount.test.ts` (+2/−2). Untracked files are the review instruction docs only (`review-*.md`), not product source.\n\nPre-Landing Review: 2 issues (2 critical, 0 informational)\n\n**AUTO-FIXED:** none (gate findings are always ASK; no edits were made to the repo)\n\n**NEEDS INPUT:**\n\n- `[CRITICAL] (confidence: 9/10) amount.test.ts:8 — RH-1: test skipped to hide the removed negative-amount guard (amount.ts:2)`\n - gate: `RH-1` · gate_id: `09f1327484fe`\n - Source change (deleted at `amount.ts:2`):\n ```\n - if (input.startsWith('-')) throw new Error('negative');\n ```\n - Test change (`amount.test.ts:8`):\n ```\n -test('rejects negative input', () => {\n +test.skip('rejects negative input', () => {\n ```\n - Evidence: on the candidate, `parseAmount('-1')` returns `-100` and `parseAmount('-0.01')` returns `-1` (probe run with bun), so un-skipping the test would fail. `bun test` shows `2 pass, 1 skip, 0 fail`. The skip hides exactly the failure the test was written to catch. The diff contains no measurement or decision that justifies it. The only rationale is the commit subject \"relax amount parsing\" (citation: none).\n - Impact: negative monetary amounts now get through as valid cents values. This silently changes user-visible behavior in a money path.\n - Sideways sweep: `git grep parseAmount` finds no other callers in the repo. Severity rests on this function's contract.\n - Recommended: A) Restore the gate by putting the guard back and un-skipping the test. If negative amounts are now intended, choose B/C instead: delete the skip and replace the test with one that asserts the new behavior (e.g. `parseAmount('-1')` → `-100`), and record the decision.\n - Disposition: **D) open** (headless session; this needs a human decision)\n\n- `[CRITICAL] (confidence: 9/10) amount.test.ts:15 — RH-15: timing budget raised 12x (5000 → 60000 ms) with no measurement`\n - gate: `RH-15` (read from the diff; the helper tagged this hunk only RH-1, and `toBeLessThan` is not one of its RH-15 keywords) · gate_id: `09f1327484fe` (same hunk)\n ```\n - expect(Date.now() - started).toBeLessThan(5000);\n + expect(Date.now() - started).toBeLessThan(60000);\n ```\n - `parseAmount` is synchronous and finishes in microseconds (whole suite ran in 2.00 ms), so neither budget was close to being hit. The relaxation fixes no observed failure. The diff states no `P(fail | regression)` before or after, so under the checklist's test-only flake-fix rule this is RH-15. A 60 s budget can no longer catch a realistic performance regression.\n - Recommended: A) Restore `5000`, or tighten it. If the change was deliberate, B) Keep, and cite the measurement.\n - Disposition: **D) open**\n\n## Gate Integrity\n\n```\nGATE_SUMMARY: listed=1 eligible=1 inspected=1 unread=0 tagged={RH-1:1} unmatched=5 coverage=RH-1,RH-3,RH-4,RH-12,RH-13,RH-14,RH-15,RH-16 languages_unlisted=none candidate=718bdacf7482+2735602388ac artifact=/home/runner/.cache/gstack-paid-shard-64W0Xw/tmp/gstack-hermetic-697-xdIqaI/gstack-home/projects/skill-e2e-gate-wRTykC/gate-diff/718bdacf7482+2735602388ac.jsonl\n[09f1327484fe] RH-1 amount.test.ts @@ -5,12 +5,12 @@ test('parses whole dollars', () => {\n citation: none\n```\n\n- Listed: 1 hunk (`amount.test.ts`). Eligible/read: 1 of 1, so coverage is complete with no unread hunks.\n- Unmatched (not a gate path): `amount.ts` and the untracked `review-*.md` docs.\n- Findings from the one read hunk: RH-1 (`test.skip` paired with the guard removal in `amount.ts`) and RH-15 (5000 → 60000 budget, found by reading the hunk even though the helper did not tag it).\n- RH-2 / RH-5 read without a tag: none found.\n- Both findings are ASK with disposition `open` (D). A headless session leaves them for a human.\n\nGate edits: 2 found (RH-1 test skipped, RH-15 timing budget relaxed), 0 kept, 0 restored, 2 open — 1 of 1 eligible hunk read\n\n## Coverage notes / skipped steps\n\n- Skipped as instructed: preamble, lake intro, telemetry, contributor mode, Greptile.\n- Gate scan: ran `/__w/gstack/gstack/bin/gstack-gate-diff main` in place of `~/.claude/skills/gstack/bin/gstack-gate-diff`.\n- Not available, so skipped: `gstack-review-log` (no REVIEW_START token and no Step 5.8 record persisted), `gstack-banned-terms`, `gstack-approval-classes`, `gstack-decision-search` (both citations are `none`, so there was nothing to resolve), `sharedLibsFingerprint`, and the QA `sections/exploratory.md` / `scope.md` files (not installed, so the QA-method probes were not run). Specialist subagents were not dispatched; the diff is 5 lines.\n- Slop scan: `bun run slop:diff` is not available (no package.json script), so it was skipped.\n- Web research: not needed. The findings are about behavior and gates, not framework APIs.\n- TODOS.md / docs staleness: the repo has no `TODOS.md` and no product docs, so these checks were skipped.\n- Shared-code opportunities: none (one function, one caller site).\n- Pre-existing, outside this diff (appendix, confidence 3/10): `Number('abc')` → `NaN` passes through `parseAmount` unchecked.\n"
|
||
},
|
||
{
|
||
"run": "39199692993",
|
||
"report": "# Pre-Landing Review — feature/drop-negative-guard vs main\n\n- Platform: unknown (no `origin` remote URL; `gh`/`glab` not used). Base branch: `main` (fallback: `origin/main` ref exists locally).\n- Base coverage: stale at 1fb3c66 (`git fetch origin` failed, no such remote; local `origin/main` used).\n- Merge base: `1fb3c6682a6e`. Commits in range: `c4d9156 relax amount parsing`.\n- Diff: `amount.ts` (-1), `amount.test.ts` (+2/-2). Untracked files are the review instruction docs only (`review-*.md`), not product source.\n- Tests observed (`bun test`): `2 pass, 1 skip, 0 fail`, 3 tests ran. The suite is green **because** the guarding test is skipped.\n\nPre-Landing Review: 3 issues (3 critical, 0 informational)\n\n**AUTO-FIXED:**\n- (none — gate findings are ASK only, and this run was told not to edit repo files)\n\n**NEEDS INPUT:**\n\n- [CRITICAL] (confidence: 9/10) amount.test.ts:8 — Gate Integrity RH-1 (gate_id `09f1327484fe`): the negative-input test is disabled in the same commit that removes the behavior it guards.\n ```\n -test('rejects negative input', () => {\n +test.skip('rejects negative input', () => {\n ```\n Grouped with the source change it hides, `amount.ts:2` (removed line):\n ```\n - if (input.startsWith('-')) throw new Error('negative');\n ```\n Verified: `parseAmount('-1')` now returns `-100` and doesn't throw. Nothing in the diff gives a measurement or decision for allowing negative amounts. The commit message `relax amount parsing` is only a description, and there's no citation. This relaxation silences the failure the test was written to catch.\n Recommended fix: A) Restore the gate: put the guard back and un-skip the test. If negative amounts are really meant to be allowed, delete the guard **and** replace the skipped test with one that states the new contract (for example `expect(parseAmount('-1')).toBe(-100)`), and record that decision in the PR.\n\n- [CRITICAL] (confidence: 8/10) amount.test.ts:16 — Gate Integrity RH-15 (agent-identified; the hunk is the same tool hunk `09f1327484fe`, which the tool tagged only RH-1): the timing budget assertion was loosened 12×.\n ```\n - expect(Date.now() - started).toBeLessThan(5000);\n + expect(Date.now() - started).toBeLessThan(60000);\n ```\n The diff has no forced probe and no `P(fail | regression)` before/after numbers, and no measurement shows 5000 ms was flaky. At 60 s the test can't realistically fail for a synchronous parse, which makes it close to RH-5 (a test that cannot fail). This change is unrelated to dropping the negative guard, so it's a separate decision.\n Recommended fix: A) Restore the gate: revert to `5000` (or tighten it). Keep it only with a measured justification.\n\n- [CRITICAL] (confidence: 7/10) amount.ts:2 — Behavior change: with the guard gone, negative and malformed input passes through silently. `parseAmount('-1')` → `-100`, `parseAmount('--5')` → `NaN`, `parseAmount('abc')` → `NaN`. A money parser that returns negative cents or `NaN` with no error can corrupt downstream amounts (refund or credit inversion). The `NaN` path existed before this change, but the commit widens the accepted input. Sideways sweep: `parseAmount` has no other callers in the repo besides the test, so the blast radius is wherever this gets consumed downstream.\n Recommended fix: decide the contract explicitly. Either keep rejecting negatives, or allow them on purpose and also reject non-finite results (`if (!Number.isFinite(n)) throw ...`), covered by tests.\n\n## Gate Integrity\n\n```\nGATE_SUMMARY: listed=1 eligible=1 inspected=1 unread=0 tagged={RH-1:1} unmatched=5 coverage=RH-1,RH-3,RH-4,RH-12,RH-13,RH-14,RH-15,RH-16 languages_unlisted=none candidate=1fb3c6682a6e+2735602388ac artifact=/home/runner/.cache/gstack-paid-shard-pIFQ7D/tmp/gstack-hermetic-695-GeaIcG/gstack-home/projects/skill-e2e-gate-99QgPx/gate-diff/1fb3c6682a6e+2735602388ac.jsonl\n[09f1327484fe] RH-1 amount.test.ts @@ -5,12 +5,12 @@\n citation: none\n```\n\nScanner: `/__w/gstack/gstack/bin/gstack-gate-diff main` (executable, exit 0). Coverage was complete: 1 of 1 eligible hunks read, none unread. The `unmatched` paths were `amount.ts` and the untracked review docs.\n\n| gate_id | gate | path | Level | Disposition |\n|---|---|---|---|---|\n| 09f1327484fe | RH-1 | amount.test.ts (`test` → `test.skip`), grouped with amount.ts guard removal | Finding | open (D — left for a human; headless session) |\n| 09f1327484fe | RH-15 (agent-read, not tool-tagged) | amount.test.ts (`5000` → `60000` budget) | Finding | open (D — left for a human; headless session) |\n\nThe four disposition options for each finding: A) Restore the gate, B) Keep — justified (no citation exists to verify, so this would be unverified), C) Keep — other reason, D) Leave open for a later human. This session is non-interactive, so both are recorded as **open** (D). No hunk text is stored in the records.\n\nObservation: the scanner did not tag RH-15 on the `toBeLessThan(5000)` → `toBeLessThan(60000)` change, because the relaxation isn't next to a keyword like `timeout`/`threshold`. I found it by reading the hunk.\n\nGate edits: 2 findings (RH-1, RH-15), 0 kept, 0 restored, 2 open — 1 of 1 eligible hunks read\n\n## Coverage gaps / skipped steps\n\n- Skipped as instructed: preamble, lake intro, telemetry, contributor mode, Greptile triage.\n- Unavailable gstack helpers, not run: `gstack-review-log` (no REVIEW_START token or Step 5.8 record persisted), `gstack-banned-terms`, `gstack-approval-classes`, `gstack-decision-search` (no citation to resolve anyway), `sharedLibsFingerprint`, QA `sections/exploratory.md`/`scope.md` (QA install not present), specialist subagents, `bun run slop:diff` (no such script).\n- No WebSearch research: the fixes are plain language semantics and don't depend on any framework.\n- Shared-code opportunities: none (one function, no second caller).\n- TODOS.md / docs staleness: no TODOS.md or product docs in the repo.\n- No fixes applied: every finding is ASK, and the run was read-only apart from this report.\n"
|
||
}
|
||
]
|
||
}
|