Skip to content

feat: show full escalation context before the operator decides - #3

Merged
windaddict merged 1 commit into
mainfrom
feat/escalations-full-context
Jul 30, 2026
Merged

feat: show full escalation context before the operator decides#3
windaddict merged 1 commit into
mainfrom
feat/escalations-full-context

Conversation

@windaddict

Copy link
Copy Markdown
Owner

Problem

When the host prompts the operator to decide an escalated deadlock, it showed only the bare operator_question — not the finding. So the operator decided without the context (claim, evidence, both positions) that resolved items already get via report show. (Reported from real use.)

Change

  • New impasse_report.py escalations <reconciliation.json> renders only the still-open deadlocks in full, reusing _render_finding for parity with show: claim, anchored evidence, both positions, deadlock kind, and the operator_question.
  • SKILL.md step 5 now requires the host to render + paste that full context before invoking AskUserQuestion.
⚖️  1 decision(s) need you — full context before you choose
F002  🟠 high  ⚖️ ESCALATED — needs your decision  · decision
  🔎 Reviewer: The rollout assumes a single-quarter cutover with no dual-run window.
  📌 Evidence: plan.md:12-14 — assumptions[0] states a hard cutover; risks[] has no migration-slippage entry.
  🗣️ Back-and-forth:
     reviewer ▶ The assumption is load-bearing and unhedged.
     you      ◀ Verified real; whether it's an error or deliberate risk is the operator's call.
  ❓ Question for you: Ship the single-quarter cutover, or budget a dual-run quarter?

Guarantee: full context or refuse

_escalation_problems is a total validator; the CLI exits 2 (diagnostic on stderr, nothing on stdout) unless it can show, for every deadlock, the finding's claim + real anchored evidence (so the reviewer-response must be recorded under this review_id), both positions (item- or escalation-level), and a non-blank operator_question. It also rejects unrecognized/typo'd states (which would silently hide an escalation), duplicate finding_ids, and a reviewer-response whose own review_id doesn't match.

Reviewed cross-provider (dogfood) — 3 rounds, 18 findings, all fixed

  • Round 1 (4): a "convenience" fallback would render a hollow full-context panel and exit 0 when data was missing — recreating the very defect. Fixed by refusing (exit 2).
  • Round 2 (9): the validator tracebacked on malformed input outside the exception boundary; a control-char-only string passed strip() but rendered blank. Made the validator total + comprehensive.
  • Round 3 (5): an empty-but-dict anchor still rendered hollow evidence; unhashable state/severity could crash. Tightened evidence to require real anchored content; made lookups crash-safe.

Scope note: stopped after round 3 — the remaining tail is exotic malformed/hostile-input cases already contained by the CLI exit-2 boundary; diminishing returns, not a clean bill.

Verification

  • 33 escalations assertions (full-context render, only-deadlocks filter incl. resolved-but-escalated exclusion, positions-in-escalation, every refusal branch, totality on malformed input, CLI exit codes + stderr/no-stdout).
  • 330 tests pass; ruff + schema gates green.
  • End-to-end: happy path renders full context (exit 0); any incomplete deadlock refuses with a precise stderr diagnostic and empty stdout (exit 2).

🤖 Generated with Claude Code

When the host (Claude Code) prompted the operator to decide an escalated
deadlock, it showed only the bare operator_question — not the finding —
so the operator decided without the context (claim, evidence, both
positions) that resolved items DO get in `report show`.

- New `impasse_report.py escalations <reconciliation.json>` renders ONLY
  the still-open deadlocks in full, reusing `_render_finding` for parity
  with `show`: claim, anchored evidence, both positions, deadlock kind,
  and the operator_question.
- SKILL.md step 5 now requires the host to render + paste that full
  context BEFORE invoking AskUserQuestion.

The command GUARANTEES full context or refuses: `_escalation_problems`
is a total validator, and the CLI exits 2 (diagnostic on stderr, nothing
on stdout) unless it can show, for every deadlock, the finding's claim +
real anchored evidence (so the reviewer-response must be recorded under
this review_id), both positions (item- or escalation-level), and a
non-blank operator_question. It also rejects unrecognized/typo'd states
(which would silently hide an escalation), duplicate finding_ids, and a
reviewer-response whose own review_id doesn't match.

Hardening surfaced by three cross-provider Impasse review rounds (18
findings, all verified + fixed): the shared render helpers now degrade
rather than crash on untrusted reviewer data (non-dict evidence/anchor/
external_source, unhashable severity/state/result), required text is
judged AFTER _clean (a control-char-only value counts as blank), and the
whole load+validate+render runs inside one exception boundary.

Tests: 33 escalations assertions (full-context render, only-deadlocks
filter incl. resolved-but-escalated exclusion, positions-in-escalation,
every refusal branch, totality on malformed input, CLI exit codes +
stderr/no-stdout). 330 tests pass; ruff + schema gates green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X8XaW2bqgYnp7oRVgfHXid
@windaddict
windaddict merged commit 124fc7a into main Jul 30, 2026
2 checks passed
@windaddict
windaddict deleted the feat/escalations-full-context branch July 30, 2026 02:50
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