Skip to content

feat(guardian): context upgrades, cross-model skeptic, inline comments#156

Merged
zaebee merged 21 commits into
mainfrom
feat/guardian-context-skeptic-inline
Jun 11, 2026
Merged

feat(guardian): context upgrades, cross-model skeptic, inline comments#156
zaebee merged 21 commits into
mainfrom
feat/guardian-context-skeptic-inline

Conversation

@zaebee

@zaebee zaebee commented Jun 11, 2026

Copy link
Copy Markdown
Owner

Implements spec §§4–6 of docs/specs/2026-06-10-guardian-sprint-design.md (Plan 2: docs/specs/plans/2026-06-10-guardian-context-skeptic-inline.md). Every feature benchmark-gated; raw data in benchmarks/guardian/results.jsonl.

What's new

  • Context upgrades behind ablation flags (GUARDIAN_FEATURES=full_files,flow,drift): full HEAD file contents (1200-line/120K-char budgets, smallest-first, explicit omission notes), flow-graph fallback for new files (feat(guardian): inject flow graph (downstream) for new files #94), architectural drift section (first consumer of drift v2 + quotient outside tests).
  • Cross-model skeptic pass (GUARDIAN_SKEPTIC=gemini|mistral|off, GUARDIAN_SKEPTIC_MODEL): second model rules on each finding (confirmed/refuted/uncertain); refuted findings stay in metrics but disappear from the report; any skeptic failure degrades to single-pass (skeptic_status=failed, never breaks a review).
  • Inline PR comments: findings with resolvable diff positions post as a GitHub review (gh api); the rest go in the review body; any failure falls back to the classic big comment (peter-evans step is now conditional on posted_inline).

Benchmark results (6 curated PRs, ground truth from real review history)

Re-baseline: gemini-3.5-flash vs committed gemini-2.5-flash

finder runs mean recall precision noise/PR
gemini-2.5-flash (Plan 1 baseline) 18 0.22 0.61 0.94
gemini-3.5-flash 18 0.19 ~1.0 0.17

3.5-flash: near-zero noise but mute on large diffs; high run-to-run variance in both models.

Task 12 — context ablation (gemini-3.5-flash, N=1, skeptic off)

arm mean recall noise/PR
baseline 0.191 0.17
full_files 0.193 0.00
flow 0.182 0.17
drift 0.182 0.33
all three 0.208 0.17

Decision: no feature ships on by default. None lifts recall (large PRs stay at 0 even at 94K prompt tokens — the failure mode is attention dilution, not missing context → #154). Features land behind flags, off.

Task 13 — skeptic arms (features off, N=1)

arm outcome
finder 3.5 + skeptic 2.5 finder went mute this round; arm uninformative
finder 2.5 + skeptic 3.5 (refute-by-default) over-kill: 7/7 refuted incl. 2 GT matches — gate FAILED
finder 2.5 + skeptic mistral fails on large PRs (per-minute token cap), degrades to single-pass as designed
finder 2.5 + skeptic 3.5 (confirm-by-default) noise 0.83 vs 0.94, lost GT = 0 — gate PASSED

Decision: repo vars set to the winnerGUARDIAN_MODEL=gemini-2.5-flash, GUARDIAN_SKEPTIC=gemini, GUARDIAN_SKEPTIC_MODEL=gemini-3.5-flash. The skeptic stance flip (refute→confirm-by-default) is the single highest-leverage prompt change measured this sprint.

Bugs found by the bench itself

  • Finder LLM hallucinating skeptic-owned schema fields (skeptic_status, verdict) — a hallucinated verdict=refuted would silently hide a finder finding. Fixed with _sanitize_finder_result; verified zero scoring impact on committed rows.

Notes for review

  • parse_features raising on unknown names is intentional fail-loud — a typo silently disabling an ablation arm corrupts benchmark comparisons. Everything else degrades gracefully.
  • lgtm=False when all findings are refuted is by design (finder flagged something; the skeptic killed it).
  • Known accepted edge: a +++ content line inside a hunk misparses in diff_line_index → that finding falls back to the review body.

Follow-ups

🤖 Generated with Claude Code

Live smoke note

/guardian review ran green on this PR (LGTM, finder gemini-2.5-flash from the updated repo vars). Caveat: issue_comment workflows execute the YAML from the default branch, so the new step wiring (--inline, skeptic env, conditional fallback) only goes live after merge — this run used the new code but the old workflow wiring. First post-merge PR review exercises the full inline path.

zaebee and others added 19 commits June 10, 2026 22:21
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…odel

- GuardianReviewer.__init__ now accepts optional skeptic_provider; finder logic
  extracted into _finder_pass(); run_review() orchestrates the two-pass flow
  (skip when no findings/parse_failed; degrade to single-pass on any exception)
- build_skeptic_provider() added to runner: defaults to the opposite provider,
  GUARDIAN_SKEPTIC overrides (gemini|mistral|off), GUARDIAN_SKEPTIC_MODEL allows
  same-provider/different-model pairs; missing API key degrades to None silently
- record_review() extended with skeptic_model/skeptic_status kwargs (defaults
  preserve backward compat; Task 10 will wire them through run_guardian)
- 7 new tests (3 core skeptic scenarios + 4 provider-selection cases); 605 total

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds render_inline_comment and render_review_body helpers to render.py
(spec §6.3), and a new github_poster.py module with build_review (pure
splitter) and post_inline_review (subprocess gh api, spec §6.4).
Tests: 15 render + 3 poster, all green; full gate clean.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Review-backlog minors:
- explicit encoding="utf-8" in collector file reads
- per-file line cap off-by-one: a file of exactly 1200 lines is now included
- get_git_diff() cached (needed twice per run: LLM context + inline index)
- post_inline_review moved off the event loop via asyncio.to_thread
- drift section returns "" instead of a header-only table when no domains
- documented lgtm semantics under all-refuted findings

Real bug found in bench telemetry: ReviewResult doubles as the finder's
structured-output schema, so the model sometimes fills skeptic_status /
verdict / skeptic_note itself. A hallucinated verdict="refuted" would make
visible_findings() silently drop a finder finding. _sanitize_finder_result
now wipes skeptic-owned fields after the finder pass. Verified: no scoring
impact on the 18 committed re-baseline rows (verdicts were all null).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Mean recall ~0.21 (vs 0.22 on gemini-2.5-flash), but noise drops from
0.94/PR to ~0.19/PR with near-perfect precision. PRs 142/143/144 score
zero recall — the large-diff targets for the full_files ablation arm.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…lash N=1

No arm lifts recall (baseline 0.191 → best combo 0.208, within run
variance); large PRs 142-144 stay at zero even with 94K-token context.
full_files zeroes noise; drift doubles it. Decision: GUARDIAN_FEATURES
stays empty by default — features ship behind flags, off.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… results

Arm matrix (6 PRs, N=1, features off): refute-by-default 3.5-flash skeptic
killed 7/7 finder findings — 3 noise (good), 2 ambiguous (neutral), and
2 ground-truth matches on PR 122 (file-container-regression,
container-zorder), failing the spec gate of at most 1 lost match.
Mistral skeptic fails on large PRs (per-minute token cap) and degrades
to single-pass as designed. Per plan: flip SKEPTIC_SYSTEM_PROMPT to
confirm-by-default (refute only on concrete contrary evidence) and
re-run the best arm once.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ate PASSED

finder gemini-2.5-flash + skeptic gemini-3.5-flash, 6 PRs N=1:
noise 0.83/PR vs 0.94 no-skeptic baseline (strictly down), lost GT
matches = 0 (gate allows 1). All 3 skeptic kills were noise/ambiguous.
Repo vars set: GUARDIAN_SKEPTIC=gemini, GUARDIAN_SKEPTIC_MODEL=gemini-3.5-flash.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@zaebee

zaebee commented Jun 11, 2026

Copy link
Copy Markdown
Owner Author

/guardian review

@gemini-code-assist gemini-code-assist 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.

Code Review

This pull request implements the Guardian Context, Skeptic, and Inline Comments plan. It introduces feature flags to ContextCollector to gate new context sections (full file contents, flow-fallback for new files, and architectural drift), adds a cross-model skeptic pass to verify findings, updates report rendering to hide refuted findings, and adds a unified-diff line indexer and GitHub review poster to support inline comments. The review feedback is highly constructive, suggesting a robust improvement to the diff line indexer in src/cgis/guardian/diff_index.py to prevent lines starting with +++ inside a hunk from being misparsed as new file headers.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread src/cgis/guardian/diff_index.py Outdated
@github-actions

Copy link
Copy Markdown
Contributor

LGTM — no defects found in this diff.

The Pull Request introduces significant enhancements to the CGIS Guardian, including dynamic context collection (full file contents, flow graphs, architectural drift), a robust cross-model skeptic pass, and inline GitHub review comment posting. The implementation meticulously adheres to the stated engineering standards, prioritizing correctness and type safety through Pydantic models, comprehensive type annotations, and graceful degradation for external API interactions. Critical areas like the _sanitize_finder_result logic correctly prevent LLM hallucinations from corrupting the skeptic pass, and the diff-parsing for inline comments correctly handles edge cases. The changes are well-tested with new unit tests covering the added functionality and edge cases. Overall, the code is of high quality and correctly implements the detailed plan.


🤖 gemini-2.5-flash · 95,900 prompt + 161 completion = 96,061 tokens · graph 10/19 files (53%)

github-actions Bot added a commit that referenced this pull request Jun 11, 2026
zaebee and others added 2 commits June 11, 2026 01:36
diff_line_index: a `+++ ` content line inside a hunk (diff quoted in
markdown, string literal) was misparsed as a file header, dropping the
rest of the file and shifting line numbers. Real headers only appear
between hunks — check _NEW_FILE_RE only when not in_hunk. Resolves the
known accepted edge from the plan; suggested by review on PR #156.

Sonar duplication (4.3% > 3% gate): _StubProvider and the canned finding
JSON were copy-pasted across test_guardian_core/runner — extracted to
tests/unit/guardian_stubs.py.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Merge the identical added-line and context-line branches into one fall-
through, collapse the skip guards into a single condition, and extract
the /dev/null ternary into _new_file_path. Cognitive complexity 22 -> ~12
(limit 15). Behavior unchanged - covered by existing 7 diff_index tests
incl. the +++-inside-hunk regression.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@sonarqubecloud

Copy link
Copy Markdown

@zaebee zaebee merged commit 3d42815 into main Jun 11, 2026
3 checks passed
@zaebee zaebee deleted the feat/guardian-context-skeptic-inline branch June 11, 2026 01:53
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.

1 participant