Skip to content

[pipeline-dcdad92d][slice-12/12] P2 items (R13, R14, R15, R16, R17) - #207

Merged
jwbron merged 82 commits into
mainfrom
egg/pipeline-dcdad92d/slice-12
Jul 8, 2026
Merged

[pipeline-dcdad92d][slice-12/12] P2 items (R13, R14, R15, R16, R17)#207
jwbron merged 82 commits into
mainfrom
egg/pipeline-dcdad92d/slice-12

Conversation

@jwbron

@jwbron jwbron commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Land the P2 follow-ups: per-finding resolution rule, the drift-guard documentation reusing the version stamp, live counters, dismissal-learning candidates, and the conditional-approval verdict.

Base PR: #196

What's in this PR

Commits (5):

  • Persist BRC history for slice-12 (#2548)
  • implement(coder): slice-12 — fix NUL-byte encoding in dismissal-learning groupKey
  • implement(coder): slice-12 P2 — live counters, dismissal-learning, conditional-approval
  • implement(documenter): slice-12 R14 — correct drift-guard doc (reviewer_code NACK v1)
  • implement(documenter): slice-12 — R13 per-finding re-review resolution + R14 drift-guard doc
.../brc-history/pipeline-dcdad92d-implement-slice-12.json       | 2133 +++++++++++++++++++++++
 .egg-state/brc-history/pipeline-dcdad92d-implement-slice-12.md  | 2433 +++++++++++++++++++++++++++
 workflows/review/README.md                                      |   36 +
 workflows/review/lib/counters.ts                                |  486 ++++++
 workflows/review/lib/dismissal-learning.ts                      |  357 ++++
 workflows/review/lib/render-comment.ts                          |  123 +-
 workflows/review/review.md                                      |   13 +
 7 files changed, 5576 insertions(+), 5 deletions(-)

This slice

P2 items (R13, R14, R15, R16, R17)

Files affected:

  • workflows/review/review.md
  • workflows/review/README.md
  • workflows/review/lib/counters.ts
  • workflows/review/lib/dismissal-learning.ts
  • workflows/review/lib/render-comment.ts
Tasks (5) + acceptance criteria
  • task-12-1: R13 per-finding resolution rule on re-review: every actionable finding gets fixed / deferred-to-filed-issue / disagreed-with-reason.
    • Acceptance criteria: Rule present.
  • task-12-2: R14 config drift guard: document the slice-11 version stamp as the stable consumer-readable sync surface (interface §4.5). Adds NO new mechanism.
    • Acceptance criteria: Doc points to the stamp; no second surface.
  • task-12-3: R15 live counters mined from run logs + review: skip redundant approvals, drop skipped-dimensions note, persist sub-agent outputs #194 per-run JSON artifacts: validator drop rate per lens, comments/PR, verdict mix, thumbs agree rate, cost/run.
    • Acceptance criteria: Counters computed from existing artifacts; no new logging mechanism required.
  • task-12-4: R16 dismissal-learning: dismissed/resolved threads, 👎-with-replies, and correct pushback become candidate do-not-flag-here notes proposed as changes to a committed config file a human approves -- never auto-adopted.
    • Acceptance criteria: Candidates written as a proposed diff for human approval; nothing auto-applied.
  • task-12-5: R17 conditional-approval verdict: APPROVE + a prominent structured obligations comment via the existing add-comment safe output; renders from the schema's pre_merge_obligation field.
    • Acceptance criteria: APPROVE-with-obligations renders from the schema; uses the existing safe output.

Stack

@changeset-bot

changeset-bot Bot commented Jul 3, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 71e3354

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

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

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

@jwbron
jwbron force-pushed the egg/pipeline-dcdad92d/slice-11 branch from ee3bc58 to d7427e8 Compare July 3, 2026 21:37
@jwbron
jwbron force-pushed the egg/pipeline-dcdad92d/slice-12 branch from 2c4b5bc to bbb4d55 Compare July 3, 2026 21:37
@jwbron
jwbron force-pushed the egg/pipeline-dcdad92d/slice-11 branch from d7427e8 to 41c87b4 Compare July 3, 2026 21:42
@jwbron
jwbron force-pushed the egg/pipeline-dcdad92d/slice-12 branch from bbb4d55 to e73288b Compare July 3, 2026 21:42
egg and others added 7 commits July 3, 2026 14:43
…ing (slice-1)

R1 (task-1-2): standardize Step 6 review submission on one robust
submit-pull-request-review call with a real, non-empty body; remove the
empty-body branch and any fallback/retry path.

E2 (task-1-3): stage /tmp/gh-aw/review/pr-context.json in Step 1 and wire
all six sub-agent read blocks to consume it. Extends #194 diff staging;
foundation for slice-7 lenses.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
task-1-1: workflows/review/lib/finding-schema.ts

- FINDING_SCHEMA_VERSION exported constant; each finding carries schema_version
  and the validator rejects an unrecognized version (breaking-shape guard).
- Finding shape (snake_case wire keys, matching #194 per-run JSON artifacts):
  id, lens, anchor, severity, confidence, evidence_trace, optional
  suggested_patch, optional pre_merge_obligation, producing_hunt,
  model_authored_prose.
- Anchor is a discriminated union with the required PR-level type (pr | file |
  line, line supports side + multi-line start_line..line range).
- KNOWN_LENSES (11 specialist + always-on/triage) and SEVERITIES exported for
  reuse by the slice-3 router and slice-2 verdict; lens/severity validated
  against them.
- validateFinding collects ALL violations (diagnosable per-lens drop rate),
  plus isValidFinding narrowing wrapper and throwing assertFinding.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…k-1-4)

Covers the exported FINDING_SCHEMA_VERSION constant, well-formed findings
across every anchor type (line/range/side, file, PR-level) plus optional
suggested_patch/pre_merge_obligation, and malformed findings for every
required field. Asserts validateFinding collects ALL violations (per-lens
drop-rate diagnosability), and exercises isValidFinding narrowing and
assertFinding throwing. 37 tests green under vitest.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…k-1-4)

Covers the exported FINDING_SCHEMA_VERSION constant, well-formed findings
across every anchor type (line/range/side, file, PR-level) plus optional
suggested_patch/pre_merge_obligation, and malformed findings for every
required field. Asserts validateFinding collects ALL violations (per-lens
drop-rate diagnosability), and exercises isValidFinding narrowing and
assertFinding throwing. 37 tests green under vitest.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@jwbron
jwbron force-pushed the egg/pipeline-dcdad92d/slice-11 branch from 41c87b4 to 21b1988 Compare July 3, 2026 21:43
@jwbron
jwbron force-pushed the egg/pipeline-dcdad92d/slice-12 branch from e73288b to 3ce90f4 Compare July 3, 2026 21:43
@jwbron
jwbron marked this pull request as ready for review July 3, 2026 21:44
@jwbron
jwbron requested a review from jeresig July 3, 2026 21:44
@khan-actions-bot
khan-actions-bot requested review from a team and kevinb-khan and removed request for a team July 3, 2026 21:44
…nts)

- Restore the empty-review-body convention: with inline comments present the
  verdict is submitted with an empty body; a non-empty body exists only for
  comment-less reviews and skipped-dimension notes. Keeps the single-call
  submission rule.
- Deliver workflows/review/lib/ to consumer repos: gh-aw's source: import only
  copies the .md, so the job checks out Khan/actions at the pinned review-v*
  release (single version surface for prompt + code) and installs its runtime
  deps.
- Drop planning identifiers (E2, R8, slice numbers, operator-directive note)
  from shipped file comments.
@jwbron
jwbron force-pushed the egg/pipeline-dcdad92d/slice-11 branch from 21b1988 to 0a45c34 Compare July 6, 2026 18:19
@jwbron
jwbron force-pushed the egg/pipeline-dcdad92d/slice-12 branch from 3ce90f4 to 595641f Compare July 6, 2026 18:19
@khan-actions-bot
khan-actions-bot requested a review from a team July 6, 2026 18:20

@jeresig jeresig left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Pushing back on the version stamp stuff as I'm not sure all that logic is needed as we're already versioning things.

Comment thread workflows/review/README.md Outdated
the `actions/` packages use), so the nested `workflows/review/review.md@<ref>` path
resolves for `gh aw add`.

### Config drift guard (the version stamp)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I don't think we need this - if the behavior changes then we should do a major release. If we're still on the same major version then we should assume that the fundamental behavior hasn't changed.

@@ -0,0 +1,361 @@
/**

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

When/how is this being run?

jwbron and others added 3 commits July 7, 2026 11:58
… rendering (slice-2)

task-2-1/2-2 verdict.ts: pure computeVerdict(labels + dimension availability +
policy conflicts) -> APPROVE | REQUEST_CHANGES | HOLD_FOR_HUMAN. Consumes #194's
mechanical label rule (isBlockingLabel); does not re-implement it. R2 gate: a
missing core dimension (correctness/skill-severity) or a policy-named conflict
holds for a human; a lost pattern-triage is note-and-continue. Documented
default blocking threshold = 1 (tunable, not a HITL gate).

task-2-3 render-comment.ts: code-owned Conventional-Comment label taxonomy +
deterministic label-wrapping/templating from the finding schema; models own all
prose. Review-body rendering mirrors review.md Step 6 + skipped-dimension notes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…pshot tests (task-2-4)

Truth-table tests for computeVerdict (verdict.test.ts): APPROVE / REQUEST_CHANGES /
HOLD_FOR_HUMAN precedence, the R2 core-dimension gate (correctness + skill-severity
absence holds; hold dominates a blocking label with all reasons retained),
pattern-triage note-and-continue, policy-named conflicts (verbatim detail
passthrough), blocking-threshold clamping (>=1) + never-RC-on-zero, and purity
(deterministic, non-mutating).

Rendering snapshot tests (render-comment.test.ts): isBlockingLabel over the full
label taxonomy + unknown-label safe default; labelForFinding severity x lens matrix
(conventions => best-practice, specialists => plain); renderComment inline snapshots
(label wrap + verbatim prose + optional suggestion block) with verbatim prose/patch
passthrough asserted; renderReviewBody inline snapshots for every verdict x inline
branch + skipped-dimension notes + non-empty safe-output guard. Fixtures validated
through assertFinding so tests can't pass on schema-invalid findings.

50 tests green; full pnpm test suite 253/253; tsc --noEmit clean (node24).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
egg and others added 7 commits July 7, 2026 13:34
…den aggregate join

Addresses reviewer_code_holistic v1 NACK (dangling cross-slice build dependency):
judge.ts imported `DownvoteReason` from ../lib/thumbs-sweep, but slice-8 (the
thumbs sweep) is not in slice-11's ancestry, so that module does not exist on
this branch. The judge consumes thumbs labels as data and never needs the sweep
module at build time, so the import was gratuitous coupling. Declared a local
`DownvoteReason` union (structurally identical to slice-8's) so judge.ts is
self-contained and typechecks against the branch as it stands.

Also cleared the two non-blocking advisories while re-proposing:
- aggregate() now rejects duplicate finding ids across requests (the join is by
  bare finding id, only case-unique in the schema — a collision would mis-join),
  and throws on a score whose finding id matches no request. The docstring now
  matches the code (previously claimed an unknown-id throw that did not exist).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…sk-11-6)

Adds workflows/review/eval/suite.test.ts, the task-11-6 deliverable:

- Suite self-tests over the coder's slice-11 modules (loader four-dataset
  load, five metrics, adversarial/overfitting gates, LLM-judge with a STUB
  model, and the version-stamp drift surface), exercised against the real
  corpus plus focused synthetic fixtures built through the public
  parseCase/runCase path.
- Whole-suite green-on-baseline check: every corpus case meets its expected
  block; must-catch recall = 100%, clean false-block = 0, adversarial hard
  gate passes (automatic mode allowed).
- CI-wiring guard: the smoke subset is a strict subset (the fast per-PR
  pnpm-test gate), and the ONLY model seam is judgeCorpus (injected model,
  async, off the deterministic path) -- so the live-judge full suite is
  scheduled/opt-in, never per-PR. Metrics+gates run over the full corpus with
  zero model calls.

Deterministic: no model, no network, no clock, no randomness.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@jwbron
jwbron force-pushed the egg/pipeline-dcdad92d/slice-11 branch from f2efbd9 to 983461b Compare July 7, 2026 20:35
@jwbron
jwbron force-pushed the egg/pipeline-dcdad92d/slice-12 branch from 64089d7 to 0932cd9 Compare July 7, 2026 20:36
… is a committed script on a weekly workflow, version-stamp machinery dropped
@jwbron
jwbron force-pushed the egg/pipeline-dcdad92d/slice-11 branch from 983461b to af7ad3a Compare July 7, 2026 20:40
egg and others added 9 commits July 7, 2026 13:40
…n + R14 drift-guard doc

R13 (task-12-1): add the three-way per-finding resolution rule to the
thread-reconciler in review.md — on re-review every actionable prior finding
resolves as fixed / deferred-to-filed-issue / disagreed-with-reason, else keep.

R14 (task-12-2): document the slice-11 version stamp in review/README.md as the
single consumer-readable config-drift surface (interface §4.5); reads the
existing pr-reviewer:version marker, adds no second mechanism.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…er_code NACK v1)

Reviewer_code correctly flagged that the README overstated the version stamp as
'already rendered into the posted review comment'. Grep confirms renderVersionMarker/
computeVersionStamp are invoked only in eval/suite.test.ts; review.md Step 6/7 emit
no pr-reviewer:version marker. Reworded the 'Config drift guard' section to state
accurately: the stamp is produced by lib/version-stamp.ts and exercised by the eval
suite today; the marker is the DESIGNATED single drift surface (Step 7 approval
comment / committed skill snapshot) but is NOT yet emitted by the workflow — wiring
that emit point is pending follow-through. Still adds no new mechanism; no second surface.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…nditional-approval

task-12-3 (R15): counters.ts — pure aggregation over #194 per-run artifacts +
run summary: validator drop rate per source, comments/PR, verdict mix, thumbs
agree rate, cost/run. No new logging mechanism; best-effort fs loader over the
conventional artifact layout, defensive normalization from loosely-typed JSON.

task-12-4 (R16): dismissal-learning.ts — mines resolved-without-fix threads,
👎-with-reply, and correct-pushback signals into candidate do-not-flag rules,
emitted as a unified diff against a committed config for human approval. Never
auto-applied; min-occurrences noise guard; deterministic ordering + diff.

task-12-5 (R17): render-comment.ts — renderObligationsComment() builds the
prominent pre-merge obligations comment from the schema's pre_merge_obligation
field (verbatim), for the existing add-comment safe output; APPROVE body reflects
the obligation count. Determinism boundary preserved (code owns structure only).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ing groupKey

Addresses NACKs from reviewer_code_holistic, reviewer_contract, reviewer_security,
and tester (all the same defect): the groupKey() field joiner and its adjacent
comment held 3 raw U+0000 (NUL) bytes, which made git classify the file as binary
and hid its diff from BRC review. Replaced the raw NUL bytes with the \0 escape
sequence in the template literal and the comment. Runtime delimiter is byte-
identical (NUL remains a collision-safe joiner — it cannot appear in lens/path/
label), so this is semantics-preserving; the file is now plain UTF-8 text and
diffs normally. No logic change.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…contract); defer dismissal-learning until the thumbs sweep has real signals
Base automatically changed from egg/pipeline-dcdad92d/slice-11 to main July 8, 2026 16:57
…/slice-12

# Conflicts:
#	workflows/review/eval/corpus/smoke/adversarial-injection-moderation.json
#	workflows/review/eval/judge.ts
#	workflows/review/eval/smoke.test.ts
#	workflows/review/eval/suite.test.ts
#	workflows/review/lib/lenses.test.ts
#	workflows/review/lib/render-comment.ts
#	workflows/review/review.md
@jwbron
jwbron merged commit 41bdf87 into main Jul 8, 2026
2 of 3 checks passed
@jwbron
jwbron deleted the egg/pipeline-dcdad92d/slice-12 branch July 8, 2026 16:59
jwbron added a commit that referenced this pull request Jul 8, 2026
jwbron added a commit that referenced this pull request Jul 8, 2026
#212)

Stacked on #207.

## Problem

webapp documents sub-tree-specific review expectations in `REVIEW.md` files (a root one plus one per documented top-level directory, next to each `AGENTS.md`), but nothing in the review workflow ever reads them. They are not pulled in by default:

- gh-aw runs the Claude Code CLI headless (`claude --print`, no `--bare`), so the repo's `CLAUDE.md` (webapp symlinks it to `AGENTS.md`) IS loaded for the orchestrator and inherited by the inline sub-agents.
- But `AGENTS.md` references the contracts as plain Markdown links, not `@`-imports, so they are never inlined; `REVIEW.md` is not a memory filename to Claude Code; and the sub-agent prompts point only at the diff, the `.github/aw/review/` runtime imports, and the skill files.

So the review contract only reached the reviewer if a model happened to follow a link.

## Change

- `correctness-reviewer`: when the checkout carries `REVIEW.md` files, read the root contract plus the nearest `REVIEW.md` above each reviewed file, and use them to sharpen `riskReason` wording and calibrate finding severity for that sub-tree.
- `claim-validator`: use the same contracts to calibrate claim labels (a contract calling a category a nit supports correcting an overstated label). Contracts never decide `verification`; that stays code-evidence-only.
- Both steps are conditional on the files existing, so frontend and other consumers without `REVIEW.md` files are unaffected.
- README: document the convention and its trust boundary.

## Trust boundary

Unlike `.github/` and the agent config folders (restored from the base branch by gh-aw before the agent runs), `REVIEW.md` files are read from the PR head. The prompts therefore treat contract text as guidance that can adjust emphasis but never override the workflow's rules, and an edit to a `REVIEW.md` in the diff is reviewed on its merits under the existing steering-text rule.

Author: jwbron

Reviewers: jeresig, somewhatabstract

Required Reviewers:

Approved By: jeresig

Checks: ✅ 3 checks were successful

Pull Request URL: #212
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants