[pipeline-dcdad92d][slice-1/12] Foundations: finding schema... - #197
Conversation
🦋 Changeset detectedLatest commit: 123a10f The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
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 |
…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>
1faaa0f to
b119a01
Compare
jeresig
left a comment
There was a problem hiding this comment.
The PR context change seems good to me.
Pushing back as I think this has undone a change that I had made around the body of the review message (we want it to be empty, if possible).
I'm not sure how finding-schema.ts is meant to be used (I guess I'll see that in a follow-up PR) but just a heads-up that right now we'll have to find a different way of bringing scripts over. Importing the review.md doesn't bring in other files: https://github.github.com/gh-aw/practices/sharing-workflows/ it only copies over the .md file itself. So we'll need something else to bring these files over, as well.
| "security-auth", | ||
| "ai-safety-moderation", | ||
| "mass-comms-coppa", | ||
| "caching-resource", | ||
| "data-migrations", | ||
| "concurrency-async", | ||
| "api-federation-compat", | ||
| "cross-deploy-serialization", | ||
| "deploy-infra-config", | ||
| "money-payments", | ||
| "content-i18n", |
There was a problem hiding this comment.
It's kind of awkward that we have to encode these in here.
I'm a bit confused, as well, are you making dedicated review agents for each of these as well? It seems like these should be covered by our existing best practices, I assume?
There was a problem hiding this comment.
This list is the validator's vocabulary, a finding attributed to an unknown lens id gets rejected instead of flowing downstream. It's not a new agent per entry beyond the roster question on #202; once that lands this shrinks to the agreed roster, and when path-to-lens mapping moves into consumer config (your #199 comment) it can be derived from config instead of hardcoded here.
|
Scripts: the plan is to have a checkout step for Khan/actions pinned to the same ref as the import, with the lib scripts run from that checkout, so the prompt and code version together. |
…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.
|
The whole stack was rebuilt in response to this review round plus our roster conversation. Here's the map. Directly from your review comments:
The roster (per our conversation; details on #202): the default roster is exactly the #194 five, and skill-auditor is fully restored, no fold-in. The new whole-change reviewers and all eleven lenses landed as opt-in capability (enable / lens= lines in ROUTING); none run anywhere by default, and the working policy is that a reviewer earns its config line through the eval suite, never by shipping. What still changes for every review with nothing enabled: see my comment on #202. In addition to what's there, the thumbs sweep starts collecting per-comment quality labels from day one, and the eval suite (smoke set as a CI gate on this repo, full suite scheduled) is what gates enabling anything beyond the default roster. |
jeresig
left a comment
There was a problem hiding this comment.
Great - thank you. A couple notes inline.
| - name: Install shared review lib runtime deps | ||
| working-directory: gh-aw-review-lib | ||
| run: npm install --omit=dev --no-audit --no-fund --loglevel=error |
There was a problem hiding this comment.
At the moment this will install the root:
"@swc-node/register": "^1.11.1",
"typescript": "^5.9.3"
via npm - but I'm not sure we actually need this. You told it to just use npx to run the script and I think that's fine, it'll install @swc-node/register for us at that point. I think we can just get rid of this install.
| with: | ||
| repository: Khan/actions | ||
| ref: review-v1.1.1 | ||
| path: gh-aw-review-lib |
There was a problem hiding this comment.
I think we're going to need to update all of the call sites where we tell it that we want to run scripts to look for them in this directory, right?
|
Round 2: what changed across the stack All round-2 feedback is applied and the stack is rebased and force-pushed (CI green per slice). Summary of the changes, slice by slice; slices 2, 4, 5, and 7 only rebased. Slice 1 (#197): Dropped the npm install pre-agent step; scripts now run via npx -y tsx <script> from the gh-aw-review-lib checkout, which fetches the runner on first use, so the checkout needs no install (the now-purposeless runtime dependencies block in package.json is gone too; typescript moved to devDependencies since tsc still needs it). On "update all the call sites": they were already updated; every invocation in the stack runs cd gh-aw-review-lib && ... (you confirmed this on #199), and the remaining node -r @swc-node/register invocations became npx -y tsx along with this change. The empty-body convention was already restored in the round-1 rework. Slice 3 (#199): The open precedence question is resolved with last-match-wins for tier= rules (gitignore/CODEOWNERS-style): write the broad rule first and the exception after it, e.g. services/** tier=high then services//testdata/ tier=trivial. Deterministic, order-controlled by the repo owner, and it composes with direction-dependent (which now applies only when its own rule wins the path). lens= stays a union across matching rules since lenses are additive. Tests cover the override and the direction-dependent-loser case. Also removed the ROUTING format section from the orchestrator prompt (the reviewer only reads routing.json); the format spec now lives in workflows/review/README.md. Slice 6 (#201): Genericized per your three points:
Slice 8 (#203): Reaction sets now match outcome-collector exactly (POSITIVE_REACTIONS = ["+1", "heart", "hooray", "rocket"], NEGATIVE_REACTIONS = ["-1", "confused"]); confused now triggers the follow-up, and tests cover both sets. Slice 9 (#204): Dropped the corpus-size test. Slice 10 (#205): The webapp-40536.md experiment file is deleted; its record moves to the PR description. Updated 2026-07-07: the refuter-panel thread is resolved, and the panel is removed rather than shipped. Before deciding, I audited every blocking review the bot posted on frontend since the claim validator landed (90 PRs, 319 blocking claims, June 30 to July 7): 12 confirmed false blocks, and only 2 were the kind another verification layer could have caught; the rest were one repeated mechanically-refutable claim, severity misreads, and author-intent questions no refuter could adjudicate from code. What ships instead, at zero extra agents: three-state validation (confirmed / plausible / refuted, with symmetric evidence duties; only a confirmed claim can carry a blocking label into the computed verdict), an author-dispute rule (a factually disputed claim cannot re-block unless the re-check traces to actual usage; otherwise it posts as a question), and a false-block tripwire in the eval suite (the no-post runner replays the gate's apply rules, and the smoke corpus gains six audit-seeded production cases: five false blocks that must approve, one confirmed block that must stay blocking). If the false-block metric ever regresses, the refuter is recoverable from the PR's history. Slices 11 and 12 are rebased on top; CI is green on all three. Slice 11 (#206): To answer the review question directly: the live judge never runs review.md and never checks out a consumer repo. The corpus replays recorded findings through the real deterministic downstream path (router, labels, scope filter, verdict, renderer), and the judge scores the quality of the rendered comments; the live-producer arm is the deferred piece. Changes:
Slice 12 (#207): Agreed on versioning: semver is the behavior contract (behavior change = major bump), and the SHA-256 drift stamp is gone. What remains is the cheap part: the Step 7 guidance comment ends with a plain marker () so every review is attributable and rollback is a re-pin. On "when is dismissal-learning run": honestly, nothing ran it; it was a library with no caller, waiting on thumbs-sweep signals that don't exist in production yet. It is pulled from the stack and will come back with its wiring once the sweep is scheduled on webapp/frontend and has accumulated real dismissals. |
Establish the versioned structured finding schema, a single robust review submission call, and staged per-run context for all sub-agents. Unblocks the determinism boundary, the router, and the prompt edits.
Base PR: #196
What's in this PR
Commits (5):
This slice
Foundations: finding schema, submission reliability, context staging
Files affected:
workflows/review/lib/finding-schema.tsworkflows/review/review.mdworkflows/review/lib/finding-schema.test.tsTasks (4) + acceptance criteria
Stack
pipeline-dcdad92degg/pipeline-dcdad92d/work