.agents/skills/issue-triage/references/workaround-validation.md
Multi-agent validation for code workarounds in triage responses. Prevents publishing broken code.
Trigger when BOTH true:
resolution.proposals[] exists (non-empty)description or add-comment comment contains fenced code (```) or inline SK* API callsSkip when: prose-only proposals, diagnostic commands only (ldd, dotnet --info), or close-as-duplicate.
Phase 3 (Analyze) → resolution + comment
│
▼
┌─ Code gate ─┐
│ Has code? │
│ No → skip │
└──────┬───────┘
│ Yes
▼
┌──────────────────────────────────────┐
│ 3 parallel explore agents (Haiku) │
│ │
│ Agent 1: API Correctness │
│ Agent 2: Behavioral Correctness │
│ Agent 3: Platform Safety │
└──────┬───────────────────────────────┘
│
▼
Synthesize → pass / fix / reject
│
▼
Phase 4 (Schema Validate) continues
Uses explore agents (read-only, Haiku, has grep/glob/view). All 3 are independent — launch in parallel.
Checks: Every SK* type exists in binding/SkiaSharp/, method names and signatures match, factory-vs-constructor usage is correct, no [Obsolete] APIs recommended.
Prompt template:
Validate that every SkiaSharp API call in this code exists with correct signatures.
For each SK* call: grep binding/SkiaSharp/ for the type and method, verify param
types match, flag any [Obsolete] methods.
Code: {extracted_code}
Context: {issue_title} ({issue_type})
Return JSON: { "verdict": "pass|fail|warn", "issues": [{ "api", "problem",
"severity": "error|warning", "fix" }], "checked_count": N, "confidence": 0.0-1.0 }
Checks: IDisposable objects disposed, same-instance trap (Subset(), ToRasterImage()) handled, factory nulls checked, no cross-thread SKCanvas/SKPaint/SKPath sharing, code actually solves reporter's problem.
Prompt template:
Check this SkiaSharp workaround for memory bugs, null-safety, and whether it
solves the stated problem. Rules: (1) IDisposable must use `using`, (2) factory
methods return null on failure, (3) Subset()/ToRasterImage() may return same
instance — check before disposing source, (4) Canvas/Paint/Path not thread-safe.
Code: {extracted_code}
Problem: {issue_summary} — Hypothesis: {hypothesis}
Return JSON: { "verdict": "pass|fail|warn", "issues": [{ "line_hint", "problem",
"severity": "error|warning", "fix" }], "solves_problem": bool,
"solves_problem_reason": "...", "confidence": 0.0-1.0 }
Checks: Platform-specific API compatibility, correct NativeAssets package implied, GPU/CPU concerns, WASM limitations, container constraints, cross-platform file paths.
Prompt template:
Check this SkiaSharp workaround works on the reporter's platform(s). Key rules:
Linux=fontconfig vs NoDependencies, Alpine=linux-musl RID, WASM=no P/Invoke,
Android CI=no GPU, Mac Catalyst≠macOS. Check path separators and font availability.
Consult: references/skia-patterns.md, documentation/dev/packages.md.
Code: {extracted_code}
Platforms: {platforms_json}
Environment: {environment_details}
Return JSON: { "verdict": "pass|fail|warn", "issues": [{ "platform", "problem",
"severity": "error|warning", "fix" }], "platforms_checked": [...],
"confidence": 0.0-1.0 }
Before spawning agents, extract from the triage JSON: (1) all fenced code blocks from resolution.proposals[].description and add-comment comment, concatenated with --- separators; (2) issue metadata — title, type, summary, hypothesis, platforms, environment clues. If no code blocks found, skip validation entirely.
After Phase 3 generates the triage JSON:
commenttask(agent_type="explore") calls| Agent 1 (API) | Agent 2 (Behavior) | Agent 3 (Platform) | Decision |
|---|---|---|---|
| pass | pass | pass | Accept as-is |
| pass | pass | warn | Accept + platform caveat |
| pass | warn | pass | Accept + disposal/null reminder |
| fail | any | any | Fix or reject — API doesn't exist |
| any | fail | any | Fix or reject — memory bug or wrong fix |
| any | any | fail | Fix or reject — platform incompatible |
| warn | warn | warn | Downgrade proposal confidence by 0.15 |
errors = all severity=="error" from 3 agents
warnings = all severity=="warning" from 3 agents
if any verdict == "fail":
if errors have "fix" suggestions → auto-apply, re-run failing agent(s) (max 1 retry)
else → strip code from `comment`, confidence=0.40, set proposal `validated: "no"`
elif warnings:
append as caveats to `comment`
reduce confidence by 0.05/warning (floor 0.50)
--- separators; all agents validate the full setSK[A-Z]\w+\.\w+\( — skip Agents 2/3 (insufficient context){ to last }); if unparseable → verdict: "warn", confidence: 0.5verdict: "warn", confidence: 0.5 — never block triagefix; second failure → strip codeInsert as Phase 3.7 between Workaround Search and Validate:
### Phase 3.7 — Workaround Validation (conditional)
If triage JSON contains code in proposals or `comment`:
1. Extract code blocks (fenced or inline SK* calls)
2. Launch 3 parallel validation agents per references/workaround-validation.md
3. Synthesize results — apply fixes, caveats, or downgrades
If no code → proceed to Phase 4.
Issue: "SKBitmap.Decode crashes with large images" — proposed fenced code block scales image before decode.
Agent results:
pass — all 5 APIs exist with correct signatureswarn — SKBitmap not in using, SKCodec.Create not null-checkedpassSynthesis: Accept with caveats. Append to comment: "Wrap bitmap in using and null-check SKCodec.Create." Confidence: 0.90 → 0.80 (−0.05 × 2 warnings).