Skip to content

Version Packages#259

Merged
jwbron merged 1 commit into
mainfrom
changeset-release/main
Jul 13, 2026
Merged

Version Packages#259
jwbron merged 1 commit into
mainfrom
changeset-release/main

Conversation

@khan-actions-bot

@khan-actions-bot khan-actions-bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

This PR was opened by the Changesets release GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated.

Releases

review@1.5.0

Minor Changes

  • b544a74: Anchor-snap fallback in the change-provenance gate (the round-three top reviewer fix). The reviewer sometimes produces a right-file, right-mechanism finding at a wrong line — observed live as anchors counted against the unified-diff TEXT instead of the file (line 24 of an 18-line file, line 8 of a 3-line file) — and the gate then dropped the correct blocking finding, occasionally flipping REQUEST_CHANGES to APPROVE (seen on adversarial-injection-approve, golden-request-changes-authz, the sql-index replay, and production main's own baseline arm). Before setting a line-anchored finding aside, the gate now snaps it to the nearest changed line in the same file under two windows: a near-miss window of 3 lines (the unified diff's context width, so the snap never reaches past the context block the reviewer was reading), and an overflow window for anchors past the end of the file itself (a line number that does not exist, per the file's real length read from the checkout) and past every line the file's hunks show, by no more than the file's diff-text overhead (headers + hunk headers + removed lines — exactly the amount diff-text counting overshoots by, so such an anchor can only be the counting mis-anchor; an anchor on a line that exists never overflow-snaps, since unshown code below a hunk can carry genuine observations that must keep demoting to advisory). Snapping is RIGHT-side only, matching the RIGHT-side-only precomputed table the gate step reads. Equidistant ties break toward the lower line (the pathology overshoots). A snapped finding keeps its severity, continues through the pipeline, and posts at the snapped anchor; every snap is recorded for audit (out/snapped.json in the production run artifact, snappedByProvenance in eval run results). A finding outside both windows keeps today's behavior: demoted to advisory, recorded in the artifact, never posted — the gate's purpose is unchanged, and an out-of-scope finding in an untouched region still cannot carry a blocking label. provenance.json now carries a precomputed per-file snap lookup (plus per-file lastShownLine/textOverhead facts from the diff parser), so review.md's gate step applies the rule as a pure dictionary lookup with no model-side line arithmetic. The live A/B prices the change per arm: the deterministic gate emulates each arm's own review.md gate version, keyed on the literal anchor-snap marker in the gate step, so a pre-snap baseline replays the pre-snap gate. A new deterministic smoke case (provenance-anchor-snap-rescued, the observed production anatomy) pins the rescue, the verdict, and the unchanged far-anchor set-aside in the per-push CI gate.
  • 618de86: Line-number-annotated staged diffs: remove the anchor mis-counting at the source. The mis-anchor pathology anchor-snap repairs downstream (reviewers counting unified-diff text lines instead of file lines) exists because the staged diff makes the model count; the staging now prints the real number on every content line so anchors are read off the page, never counted. A new deterministic annotateDiffLineNumbers (lib/diff.ts) prefixes each hunk content line with its line number (+/context lines carry the NEW-file RIGHT-side number, - lines the OLD-file LEFT-side number) while keeping the diff marker in column one, so annotated text still splits into file sections. The provenance CLI writes full-stripped-annotated.diff beside the raw stripped diff, and a new annotate <in> <out> subcommand produces pr-annotated.diff after Phase 1 builds pr.diff (the scoped and flip-gated depths refresh the annotated copies the same way). Every finding-producing reviewer (correctness, skill-auditor, conventions, the four whole-change reviewers, and all eleven specialist lenses via the shared disciplines block) now reads the annotated copy, takes anchor.line from the printed number, and strips the prefix when quoting code or authoring a suggested_patch. Everything that PARSES a diff keeps reading the raw files: provenance, re-review hunk fingerprints (whose signatures must not shift), scoped staging, and pattern-triage/claim-validator are untouched. The eval stages the annotated siblings for both arms unconditionally, and only a review.md version that names them reads them, so the A/B against a pre-annotation baseline is a pure prompt delta with no staging flag. The measurement instrument rides along: per-case anchor-snap counts (perCase.snapped) in the arm report and a pooled "Findings anchor-snapped" row in the aggregate, version-tolerant of older artifacts — if annotation works, candidate-arm snaps fall to zero because anchors arrive correct, with the anchor-snap gate remaining as the deterministic backstop.
  • f8da3bb: The live A/B runner (live A/B plan, phase 3). eval/live-match.ts maps a run's posted candidates onto a live case's labeled defect specs (deterministic path/window/mechanism rule first, then an injected hard-capped fallback arbiter whose matches are recorded for audit) and aggregates live metrics: must-catch recall, verdict agreement, clean false-flag, and noise. eval/live-ab.ts runs the model sub-agents from two review.md versions (the merge-base baseline via git show, the working-tree candidate) over the same live corpus, each arm under half a hard USD budget with sticky stop-and-report-skips semantics, replays each live result through the deterministic pipeline (runner.ts gains a validation override on RunOptions so a live validator's output replaces the recorded block), diffs spec-level regressions over the cases both arms scored, judges both arms' comments with the pinned judge (quality aggregates only; extracted to eval/judge-live-model.ts, now shared with live-judge.ts), and emits a JSON report plus a markdown table (also appended to GITHUB_STEP_SUMMARY). Report-only except the playbook's standing rule: the candidate arm failing any adversarial-injection case exits non-zero.
  • 7eb5501: Live-enabled corpus cases (live A/B eval plan, phase 1). The eval corpus gains an opt-in live block carrying what a REAL model run needs and the deterministic replay does not: the PR context (prContext, with the description treated as untrusted author text), a post-change file tree on disk next to the case (<id>/case.json + <id>/tree/, coexisting with the flat <id>.json layout), and labeled defect specs (mustCatchSpecs / mustNotFlagSpecs: path, line window, mechanism keyword alternates) so a live run's model-chosen finding ids can be matched to ground truth. A live case must carry the live tag, a cleanly-parseable diff, and every non-removed changed file in its tree; the loader enforces all of it and loadLiveCorpus() returns the subset. Ten cases are converted with hand-authored real diffs and trees (five smoke incidents, both clean cases, one adversarial injection whose payload lives in the diff, one golden holdout, one synthetic mutation); their recorded line anchors now point at the authored defect lines, and the deterministic suite runs them unchanged, provenance gate included.
  • 2acfbe1: The live producer (live A/B plan, phase 2): everything needed to run the REAL model sub-agents over a live-enabled corpus case. eval/agent-extract.ts parses review.md's ## agent: sections into name/description/model/prompt as pure data (string in, no fs), so an A/B can extract the baseline arm from a git show of the merge-base; parsing is strict and lists every malformed section at once, and an integration test runs it over the real review.md. eval/live-stage.ts materializes the production /tmp/gh-aw/review/ staging layout for a case (pr-context.json, full/pr/full-stripped diffs, files.json with hasPatch, review-files.json, provenance.json, routing.json, out/, and the post-change checkout) and rewrites extracted prompts to point at it. eval/live-producer.ts dispatches the default finders plus the router's lenses through an injected runner seam, maps all three output contracts (label-shape reviewers, structured-schema lenses, the claim-validator's three-state verdicts) into the exact RecordedFinding/CaseVerification shapes the deterministic runner consumes, stages claims.json, resolves {{#runtime-import}} directives from the case tree, retries once on malformed output, keeps partial results on agent failure, and accounts per-agent cost. eval/live-runner.ts is the one SDK-backed runner (Claude Agent SDK; Read/Grep/Glob only, cwd pinned to the staged checkout, hard turn and wall-clock caps) plus a CLI smoke entry (pnpm dlx tsx workflows/review/eval/live-runner.ts --case <id>, requires ANTHROPIC_API_KEY).
  • e1c7fb6: Out-of-lane observations are handed off, never dropped. Observed on the review-v1.4.0 re-run lifecycle: the skill-auditor found a real eventual-consistency bug (dedup reads via a Query immediately after PutMulti) and discarded it, verbatim "that's a correctness concern, not a quotable skill-rule violation, so I'll leave it"; correct under quote-the-rule, but the observation died and the defect shipped unflagged. The skill-auditor and every specialist lens may now return out_of_lane_observations[] (path, optional line, the concern stated concretely, a required concrete failure_scenario, optional suggested_lane) for real concerns their own mandate does not let them report. The orchestrator converts each one into a candidate comment with the code-assigned label question (non-blocking) (a handoff is not a vetted finding and can never block on its own; the claim-validator never upgrades severity) and routes it through the identical provenance gate, scope filter, claims.json, and validation path as every other candidate. The shape is validated by the new validateOutOfLaneObservation in lib/finding-schema.ts (a sibling type, so FINDING_SCHEMA_VERSION stays 2: no serialized finding is invalidated).
  • 7bb2ea3: Re-review accountability, code-rendered. Observed on the review-v1.4.0 re-run lifecycle (Khan/webapp#40730): run 2 resolved the fixed threads and said nothing about the three blocking threads it left open, under a bare "Changes requested" body; run 3 approved with an empty body while resolving 11 threads. The verdict body now accounts for every prior thread, rendered deterministically from the thread-reconciler's keep/resolve lists by the new lib/rereview.ts (never composed by the model): each still-unaddressed prior thread is enumerated as a link to its earlier comment ("as of \<sha>", blocking first, with a verbatim excerpt of the earlier comment's first line), with the resolved count stated; an approval that resolved the last open threads says every prior thread is resolved. threads.json staging gains a url field (the thread's first comment html_url) to power the links, renderReviewBody gains a rereviewSection slot, and the redundant-approval skip treats a non-empty section as content. Fail-open: a missing or unparseable staging input renders an empty section, leaving the body exactly as before.
  • 253660b: Re-review coverage for the eval corpus: a live-enabled case may now carry a live.rereview block that makes it an open-PR snapshot instead of a first review, staging the prior review's unresolved threads (author replies included), a stamped prior review derived from priorDiff (the same hidden-comment mechanics production reads), and the mode dial's depth plan. The live producer dispatches the thread-reconciler on such cases at every depth and sizes the finder roster by the plan (scoped keeps the roster over the scoped diff, flip-gated keeps the correctness pass, fast reconciles only); eval/rereview-match.ts scores thread-resolution accuracy per ground truth, the flip-gate input, and duplicate comments on kept threads, and the A/B runner prices a mode via --re-review-mode on the candidate arm. The deterministic replay learns the same rules: computeVerdict gains keptBlockingCount (the flip rule as code: an approval is floored at REQUEST_CHANGES while a prior blocking thread stays open) and re-review cases render the accountability section into the planned body. Ships with the golden-retention-lifecycle-1/2/3 chain, a sanitized port of a measured seeded live trial: planted bugs, a bad partial fix with added bugs (kept threads plus fresh defects), then the full fix that must flip to APPROVE. A mode sweep (eval/rereview-sweep.ts) prices every dial setting in one command: it runs the working tree's reviewer over the rereview cases at each mode and reports recall, thread resolution, flip-gate correctness, duplicates, and dollars per mode, with the executed depth per case (the tripwire may override the dial). golden-retention-fix-push is the under-threshold pricing case: a one-hunk fix push (unreviewed share 0.2) whose fix resolves the prior blocking thread but plants a fresh defect inside the new hunk, so scoped and flip-gated must catch it and fast definitionally cannot. The sweep is dispatchable in CI (review-rereview-sweep.yml, manual only since it spends model dollars); the table lands in the job summary and the JSON report in the run artifact. Every model-spending eval now has the same manual trigger surface: PR labels (rereview-sweep, live-judge, full-eval now firing on the labeling event itself) plus workflow_dispatch; and the A/B short-circuits before spending when review.md is byte-identical in both arms, posting a "no reviewable delta" verdict and running nothing (--force-arms keeps deliberate wobble controls possible).
  • f57f77b: The re-review mode dial, the runs-per-PR cost lever: a per-repo re-review line in .github/aw/review/ROUTING (full | scoped | flip-gated | fast, default full) decides how much of the roster a repeat review of the same PR runs. scoped runs the whole roster staged only the hunks new since the last fully-reviewed fingerprint; flip-gated runs reconciliation plus the correctness pass, whose validated blocking findings veto a REQUEST_CHANGES→APPROVE flip; fast is reconcile-only. Three deterministic guards (lib/rereview-mode.ts): the anchoring full review is taken at ready-for-review (never on a draft skeleton); the flip gate; and a divergence tripwire that stamps a content-hashed hunk signature into the review body as a hidden comment (surviving cache eviction, dismiss-stale-approvals, and COMMENTED-only histories) and re-arms full review when the unreviewed share reaches 0.4. Adversarial lifecycle cases (rewrite-after-approval, sparse-PR-then-payload) live in eval/lifecycle/ and are replayed deterministically; run cost now aggregates per executed depth (costByRereviewDepth) so the live A/B can price scoped against full on recall and dollars. Ships default-full: no consumer's behavior changes until its repo adds a mode line. Motivated by measured lifecycle costs on the seeded trial (v1.3.1: $7.19/$8.77/$9.14; v1.4.0: $8.31/$9.87/$11.29 per push), where a fresh seeded defect was caught on a re-review push that a reconcile-only path would have missed; the case for scoped as the recommended reduced depth. Supersedes the consumer-side stopgap in Khan/frontend#13420.
  • 4794fc5: Value-ranked shedding and dispatch. The graceful-landing rule's first shed bucket previously said "skip any not-yet-dispatched opt-in reviewers and lenses" with no ordering, so a budget-pressed run shed arbitrarily; the 2026-07-10 production runs showed the consequence (an invocation cap smaller than the roster filled its slots by enablement mechanism, not value, and a matched specialist lens could be shed to afford conventions). The shed order is now explicit, lowest value first: conventions, first-principles, holistic, completeness/test-adequacy, and path-triggered specialist lenses last, since a matched lens is the most targeted signal in the run. The same ranking read from the other end (defaults, lenses, targeted opt-ins, generic opt-ins) is now the mandated dispatch order when maxReviewerInvocations cannot fit the full roster, with every undispatched reviewer recorded as a planned shed. And reviewer requests (Step 8) are removed from the shed list entirely: pulling a human in matters most on exactly the run whose own coverage is partial. The ranking is a first-cut editorial ordering; replace it with measured per-dimension must-catch contribution from the eval corpus when that data is compiled.
  • e6d0ae5: Skill findings show the author the actual rule. Quote-the-rule already requires the exact rule text in a lens skill finding's evidence_trace, but evidence traces never reach the PR: the author reads only model_authored_prose, so they see a paraphrase of a rule they cannot check. The finding schema gains an optional rule_quote field (the exact rule text, verbatim from the skill file; validated non-empty when present, and optional, so FINDING_SCHEMA_VERSION stays 2), each lens's lens-owned-skills discipline says to fill it, and renderComment plus the orchestrator's normalization step surface it into the posted comment as a > **Rule:** … blockquote between the prose and any suggestion block. Only the wrapping is code-owned; the quote is skill-file text copied verbatim.

Patch Changes

  • 25a1ef1: Clamp the router's run budget to the effective per-run AI-credits cap, and make the cap visible to the run. The tier budget table is sized inside the workflow's assumed $10 ceiling, but the cap is enforced runner-side by the firewall api-proxy and was invisible in-container, so a consumer with a tighter max-ai-credits got soft targets that promised more work than the cap could pay for; the graceful-degradation path never fired and the run died at the api-proxy with findings in hand (observed on a 400-credit behavior test: three finders completed, ~390 credits spent, killed mid-persist before validation, nothing posted). The frontmatter now sets max-ai-credits: 1000 explicitly and mirrors it into the agent environment as REVIEW_MAX_AI_CREDITS (kept in sync by consumers that override the cap); the router resolves the cap from that mirror (falling back to GH_AW_MAX_AI_CREDITS, a visible awf config, then gh-aw's 1000-credit default) and scales the selected tier's soft targets proportionally, floored at the trivial tier's values, marking runBudget.capClamped and runBudget.effectiveCreditCap in routing.json. The budget prompt gains a matching estimated-credits proxy (sum of in-band subagent_tokens over completed sub-agents, divided by 5,000) and two mandatory proxy checkpoints, the critical one immediately after the last finder returns and before claim validation, so a tight run sheds and lands a partial review instead of dying at the cap.

  • 53b6815: Dispatch-tax trim: dedupe the specialist-lens discipline snippets. The v1.4.0 re-run's cost premium vs the v1.3.1 baseline sat at dispatch time (uncached input +51-65%, cache writes +18-34% per run), partly because the shared discipline blocks (bounded investigation, untrusted input, lens-owned skills with quote-the-rule, the schema-rules trailer, the tri-state hunt contract) were stamped verbatim into every one of the eleven specialist-lens definitions and paid on every dispatch. The shared text now lives once, in a marker-delimited "REVIEW DISCIPLINES" section of review.md's main body; Step 1 stages it to /tmp/gh-aw/review/disciplines.md with one whole-line-anchored sed extraction of the engine-provided rendered prompt ($GH_AW_PROMPT), verified by grep with a byte-for-byte heredoc fallback, and each lens carries only a pointer plus its own domain notes (its investigation examples, review rules, hunts, and output JSON, all unchanged). Behavior-neutral by construction: the instruction content is unchanged, the three variants that had already drifted apart are unified on the fullest wording, and the label-shape reviewers (whose variants differ materially) keep their own copies. Pinned by lib/disciplines.test.ts: the section extracts cleanly under the exact sed range semantics, every lens points at the staged file and carries no residual copy, and the label-shape reviewers still carry theirs.

  • 6b1b3c7: Fail-fast case selection in the live A/B runner. An explicit --cases list is now an exact selection: it bypasses --smoke-only (which scopes unscoped runs only), preserves the requested order, runs duplicate ids once, and throws before any model spend when an id matches no live case. Previously the smoke scope filtered the corpus before the case filter, so a dispatch naming a non-smoke case silently dropped it: the 2026-07-10 anchor-snap powered run named two cases and the paid report covered one without saying so, and a typo'd case id would shrink a measurement the same way. The workflow needs no change; it already passes both flags and the case list now wins.

  • 2868f95: Make the live eval instrument a measurement tool, not just a tripwire (the tuning memo's rev-2 sizing items). eval/aggregate.ts pools N live-ab-report.json artifacts (local paths or gh run ids) into per-case pass rates per arm with 95% Wilson intervals plus pooled recall/verdict/noise rows, classifies misses true-miss vs found-but-dropped per gate bucket, warns on multi-sha pools, and, when every pooled report ran byte-identical arms, renders per-metric noise-floor bands as data. live-ab.ts gains --repeats <n> (the ~$29 targeted-repeats powered run: each arm runs every selected case n times in one dispatch, budget split per arm-run, report rendered through the aggregation core; the adversarial gate is decided by strict majority across repeats instead of the single-run best-of-three retry) and the A/B workflow exposes cases/repeats/force_arms dispatch inputs. A new scheduled workflow (review-eval-drift.yml, weekly) runs the full live corpus x3 repeats with both arms pinned to main's review.md and publishes the aggregated report (job summary, artifact, and a visibility PR committing the report under .github/review-eval/drift/ so merges accumulate an in-repo time series): the memo's cumulative drift watch, doubling as a rolling noise-floor measurement. Live defect specs gain altLocations (alternate anchor sites with their own line windows, validated like the primary): a defect that spans files has more than one correct anchor, and incident-sql-missing-index (8/16 in the 07-09 wave) turns out to have been measuring anchor-site preference, not recall; replaying all 28 recorded arm-runs, the reviewer found the missing index every time (26 posted, 2 provenance-dropped mis-anchors), so the case now accepts the hot-query anchor and its residual misses classify as the anchor-snap defect class. eval/match-arbiter.ts implements the matcher's fallback seam on the pinned Haiku snapshot (claude-haiku-4-5-20251001): unmatched specs only, same-file candidates only, capped per case, every claim recorded via: "fallback" for audit, prompt biased to refuse, API failures degrade to non-matches; on by default with --no-match-arbiter to opt out. Multi-repeat runs checkpoint their artifact after every repeat, so a crash or cancellation cannot forfeit completed repeats. The measured noise floor (run 29069228968: 6 identical arm-samples, full corpus x3, $58.71) renders as data in every single-run report footer: must-catch recall 54-86%, verdict agreement 75-100%, noise 50-60%, judge quality 0.82-0.86; the drift run's default budget is $85 to cover the 14-case corpus without budget skips. eval/README.md is the operator guide: the three tiers, every CLI flag and CI entry point, powered-run recipes, corpus-growth rules, report-reading guidance with the measured noise floor, costs, model pins, and the harness's historical limits. Reports stamp their ruler (matcher configuration + corpus content hash) and the aggregate warns when a pool mixes rulers or when identical-arm samples scored unequal case sets (budget skips), which would fold case-mix variance into the noise-floor bands; bands now report SD alongside min/max, and repeat budgets roll unspent headroom forward instead of stranding it in fixed slices.

  • d26b4e0: CI wiring for the live A/B (live A/B plan, phase 4): the Review Eval A/B workflow runs on every non-draft PR touching workflows/review/** (plus workflow_dispatch), executing the arm-to-arm live eval against the PR's merge-base and posting the delta report as a sticky PR comment, a job summary, and an artifact. Per-PR runs cover the smoke-tagged live subset; a full-eval label (or the dispatch input) lifts that to every live case, a skip-live-eval label opts out, the changeset release branch is excluded, secretless runs (forks) skip green, and a new push cancels a superseded run. The job fails only when the runner's adversarial hard gate fails on the candidate arm. The runner gains --smoke-only and writes a markdown sibling of the JSON report for the comment step.

  • 82aed74: Document the GH_AW_OTEL_SENTRY_ENDPOINT / GH_AW_OTEL_SENTRY_AUTHORIZATION secrets as a hard install prerequisite (README required-secrets section plus the comment on the observability: block). A consuming repo without them does not degrade gracefully: the compiled lock feeds the empty endpoint into the MCP gateway's OTLP config, whose schema rejects it, and the agent job dies at startup (observed on Enable the automatic AI PR reviewer on this repo #241). Repos without Sentry must comment out the observability: block in their installed review.md and recompile.

  • 2f003f7: Fix the out/ run-artifact upload, which failed on every run under gh-aw v0.81.6. The orchestrator passed the absolute path /tmp/gh-aw/review/out/ exactly as instructed, but gh-aw's upload_artifact tool stages an uploaded directory under its basename and records only the staging-relative name (out), and the safe_outputs job then filters the staged files (out/<agent>.json) against allowed-paths with a fully anchored matcher; the absolute pattern /tmp/gh-aw/review/out/** therefore matched nothing, every run annotated ERR_VALIDATION: upload_artifact: no files matched the selection criteria, and no sub-agent outputs or pre-existing.json reached the run artifacts, blocking post-hoc claim auditing, the live counters, and the A/B runner, which all read them. allowed-paths now lists the staging-relative out/** (plus the absolute form, since the filter is an OR, in case a future gh-aw matches original paths). Step 9 also copies claims.json into out/ before uploading, so the artifact carries the validator's input alongside its verdicts (claim-validator.json) and the provenance gate's set-asides (pre-existing.json).

  • adb052f: Require the introduce-vs-amplify call in the posted comment prose, not just the finding. The discipline already made finders classify a defect as introduced or as a pre-existing mechanism amplified, but nothing required the classification to survive into the text the author reads: on the amplification behavior test the posted comment argued the distinction in substance (named the pre-existing default and attributed the regression to the guard removal) without ever stating it. The finder rule now requires a plain clause in the discussion ("introduced by this change", "pre-existing; this change amplifies it by removing the guard"), including the boundary case where the enabling mechanism predates the diff but the defect is new, and the claim-validator's amplification rule extends its corrected path to add the missing clause on either shape.

  • 8a5783a: Budget and shed tuning from the 2026-07-10 production sheds (the reviews on Khan/actions review: add the live A/B eval plan #232 and review: add the review-trial skill (live A/B phase 5) #238, which shed claim validation and three whole-change dimensions on substantial PRs that had routed to the bottom tiers). Three changes. The tier budget table is recalibrated against measured runs: wall clocks now account for the ~3 minutes of fixed staging/router/triage overhead a run spends before the first reviewer returns (trivial 3->6, low 6->10, medium 12->15), and the low/medium invocation caps now fit the standard seven-reviewer whole-change roster (low 4->8, medium 8->10), which the old low cap of 4 deterministically shed on every run. The invocation cap is now explicitly finding-producers only: pattern-triage, thread-reconciler, and the claim-validator are pipeline steps and never consume a slot (the 07-10 runs counted them inconsistently). And the claim-validator moves to the back of the shed order with a hard-ceiling gate: it may be shed only when the job timeout or credits cap is genuinely close, never at a mere soft-target breach, since its cost tracks the visible candidate count rather than the diff. Skipped-dimension notes now distinguish the two causes: a planned budget shed reads shed under the <tier>-tier run budget and the output unavailable wording is reserved for a sub-agent that was dispatched but returned nothing parseable, so an operator can tell budget arithmetic from an infrastructure failure. (This repo's ROUTING also re-raises .claude/skills/** and workflows/review/eval/**/*.md from the broad trivial-docs rule; that file is consumer config, not part of the package.)

  • d615f20: Add three live-enabled eval corpus cases porting the Khan/webapp#40678 seeded-defect trial into the review-workflow corpus. All three are sanitized structural rewrites: fresh Go code around a generic "notes retention" feature that reproduces the trial's defect mechanisms, carrying no webapp code, paths, or identifiers.

    • trial-retention-deletion (incident-repro): the deletion-path seeds; a flag-gated compliance deletion, a query-default limit of 1, a reimplemented deletion helper, an env-interface widening flagged in both files, and a swallowed prune error.
    • trial-retention-prune-tests (incident-repro): the prune-and-tests seeds; an off-by-one retention cap, a vacuous cap test that passes for a no-op prune, a suite-wide flag-ON mock hiding the flag-off path, and a full-entity fetch where keys-only suffices.
    • trial-batch-delete-wrapper (clean): the trial's deliberate non-defect as a must-not-flag trap; a large single DeleteMulti call that looks over the datastore's 500-entity cap but is chunked internally by the (unchanged, in-tree) datastore wrapper. The recorded false block is refuted by validation and the case must approve.

@khan-actions-bot khan-actions-bot requested review from a team, jaredly and somewhatabstract and removed request for a team July 10, 2026 20:50
@github-actions github-actions Bot force-pushed the changeset-release/main branch 20 times, most recently from e199dc5 to 8db74b2 Compare July 13, 2026 19:34
@github-actions github-actions Bot force-pushed the changeset-release/main branch from 8db74b2 to cdf7305 Compare July 13, 2026 20:15
@jwbron jwbron merged commit 143ed12 into main Jul 13, 2026
1 check passed
@jwbron jwbron deleted the changeset-release/main branch July 13, 2026 20:17
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