Skip to content

review-trial: record three operational lessons from the preview trials - #306

Merged
jwbron merged 3 commits into
mainfrom
jwies/trial-protocol-hygiene
Jul 31, 2026
Merged

review-trial: record three operational lessons from the preview trials#306
jwbron merged 3 commits into
mainfrom
jwies/trial-protocol-hygiene

Conversation

@jwbron

@jwbron jwbron commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Three lessons the last two preview trials taught the hard way, none of which the skill said.

1. Never force-push a trial branch between rounds (Step 3)

A re-review round that cannot anchor on a prior fingerprint reports stampSource: null in out/rereview-plan.json and executes depth: full with staging: whole-diff even where ROUTING says scoped. That is visually indistinguishable from a genuine carrier gap, and it silently voids the scoped-cost sample the round was supposed to produce.

The skill now also names what the carrier does and does not tolerate, because it is easy to assume the wrong one:

  • the hunk signature is content-hashed over each hunk's added and removed lines, so SHA rewrites and shifted line numbers do not move it (workflows/review/lib/rereview-mode.ts:63-70, 88-92; asserted by rereview-mode.test.ts:64);
  • the cache record's commitSha is written (workflows/review/lib/cache-record.ts:401) and read by nothing in the repo.

So a rebase alone should not refuse the carrier. What loses the anchor is losing the record (cache eviction, or a credit-capped run that dies before Step 9 writes it, which the skill already warns about); a force-pushed round is simply the round where that goes unnoticed and gets blamed on the rebase. Guidance: forward-only pushes once a round has been reviewed, rebase the stack before the first review, read stampSource out of the plan artifact every round instead of inferring it, and discard scoped-cost samples from any round that did not anchor.

2. Fresh lock filename per trial (Step 1)

GitHub's workflow registry keys the display name to the file path and keeps the stale one. Two consecutive trials that reused review-preview.lock.yml both appeared in the Actions list as "PR Reviewer" while the files on the branches declared "PR Reviewer Preview v1.8.0" and "...v1.9.0". Concurrency was unaffected (distinct groups, and the production workflow recorded zero runs on either branch), but a run list that names every arm after the production reviewer is unreadable and invites exactly the "did production just run?" scare the existing naming rule exists to prevent.

3. Suppression tests need an unfixed finding (Required input 4)

A lifecycle push where the fixer repairs everything lets the reconciler resolve every thread, so threads.json comes back empty and open-thread suppression has nothing to suppress. A plan that means to exercise suppression must leave at least one finding unfixed.

Plus two lines in the Guardrails recap.

Docs only; no code paths touched.

… lessons from the preview trials

Three things the last two trials taught the hard way, none of which the
skill said:

- Never force-push a trial branch between rounds. A round that cannot
  anchor on a prior fingerprint reports `stampSource: null` and executes
  `depth: full` with `staging: whole-diff` even where ROUTING says
  `scoped`, which looks identical to a genuine carrier gap and voids the
  scoped-cost sample. The carrier itself is content-hashed and rebase
  stable (`rereview-mode.ts`) and its `commitSha` is never read back, so
  the thing that actually loses the anchor is losing the record; a
  force-pushed round is just where that goes unnoticed. Read
  `stampSource` out of the plan artifact every round instead of
  inferring it.
- Give each trial's compiled workflow a fresh lock filename. GitHub
  keys the workflow display name to the file path and keeps the stale
  one, so two trials that reused `review-preview.lock.yml` both listed
  as "PR Reviewer" while their files declared "PR Reviewer Preview
  v1.8.0" and "...v1.9.0". Concurrency was unaffected, but the run list
  invites the "did production just run?" scare the naming rule exists
  to prevent.
- A lifecycle plan that means to test open-thread suppression has to
  leave one finding unfixed; if the fixer repairs everything the
  reconciler resolves every thread, `threads.json` is empty, and the
  round proves nothing either way.
@changeset-bot

changeset-bot Bot commented Jul 31, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: ac523fd

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
review Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@khan-actions-bot
khan-actions-bot requested review from a team, jeresig and kevinb-khan and removed request for a team July 31, 2026 16:51
Comment thread .claude/skills/review-trial/SKILL.md
Comment thread .claude/skills/review-trial/SKILL.md Outdated
…t; make `stampSource` the authoritative anchoring signal

The Lints job failed for want of a changeset. Skill-doc changes take a
`review` patch, matching #291.

Review feedback, both non-blocking:

- The recap carried the force-push ban but not the rule the section says
  actually matters, leaving a skimming operator unprotected against record
  loss, which is the real anchor-loss cause. Adds the `stampSource` line.
- The carrier internals (hunk-hash tolerance, `commitSha` written but never
  read back) are accurate today but are incidental implementation properties,
  not contracts. They now sit under the `stampSource`-is-authoritative rule,
  dated, with a note saying which half goes stale if a later change starts
  validating `commitSha` on restore.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved — no blocking issues found.

Re-review: both prior review threads are now resolved.

  • The recap (stampSource line) was added, addressing the earlier suggestion.
  • The carrier-internals paragraph is now dated (As of 2026-07:) and framed as incidental implementation properties rather than contracts, with a note on which half goes stale if commitSha restore-validation is ever added — addressing the earlier note.

Both factual claims in the diff check out against the current source: the content-hashed hunk signature is force-push/rebase stable (workflows/review/lib/rereview-mode.ts), and commitSha is written at workflows/review/lib/cache-record.ts:401 but has no read site in the repo. Docs-only change; no code paths touched.

…runs by events, keep injections out of the diff

From the 2026-07-31 suppression trial on webapp#41204.

Counting runs by events, not pushes. A closed PR fires no pull_request event, so
pushes onto it are free; `reopened` is in the reviewer's trigger list, so a
reopen fires exactly one run; pushing to an open PR fires `synchronize`, one more
each time. Push-while-closed then reopen therefore buys a round for one run. The
larger saving is not building the round at all: a closed PR whose last round's
comments are still unresolved already IS a partially-fixed round, and reopening
webapp#41204 produced the round that made open-thread suppression fire in
production for the first time (run 30650642317) against a two-run budget.
Unresolving a thread is a GraphQL mutation an agent's tooling may refuse, so it
belongs to the operator.

Keeping fault injections out of the diff under review. Mis-staging to trip a
fail-open reporter works (run 30654454047 reported unusableThreads: 9), but
injecting through the prompt or lock file on the trial branch makes that edit the
newly-changed code: all five of that run's candidates landed on the prompt file
and none on the Go fixture, so the duplicate re-posting the reporter warns about
went unobserved, and the round was spent correctly flagging the injected prose as
agent-directing instructions.

Cleanup gains the corollary the closed-PR shortcut needs. Keeping a resumable
branch is fine, but it is reverted to a safe state in the pass that closes the
PR, with the resumable details (unresolved threads, run IDs, what a reopen fires)
in the closing comment: a surviving branch that still carries a planted panic is
a trap, and the reopen reviews immediately.
@@ -0,0 +1,5 @@
---
"review": patch

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question (non-blocking): Does a doc outside workflows/review/ warrant a review: patch bump? The skill lives at repo-level .claude/skills/review-trial/, outside the review package, and the changeset's own closing line says "No change to the shipped review workflow" — yet this bump cuts review-v1.9.1 and rewrites the pinned review-v<semver> literal in review.md. If the changeset gate only needs a file to exist, pnpm changeset --empty lands the lessons without minting a contentless release; keep the patch bump only if trial docs are deliberately versioned with the package.

@jwbron
jwbron merged commit baa5fc7 into main Jul 31, 2026
9 checks passed
@jwbron
jwbron deleted the jwies/trial-protocol-hygiene branch July 31, 2026 20:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants