Skip to content

feat: operator channel polish — 0.3.6#91

Merged
fakechris merged 2 commits into
mainfrom
feat/explainer-tier-0.3.6
Apr 23, 2026
Merged

feat: operator channel polish — 0.3.6#91
fakechris merged 2 commits into
mainfrom
feat/explainer-tier-0.3.6

Conversation

@fakechris

@fakechris fakechris commented Apr 22, 2026

Copy link
Copy Markdown
Owner

Summary

  • Adds deep_explainer_model so assess_drift can opt into a heavier reasoner while routine explanations stay on the cheap explainer_model (with graceful fallback to the routine model and then the stub).
  • Introduces frozen DriftAssessment and ExchangeView dataclasses (supervisor.operator.models) with from_dict() that accepts both legacy last_*_summary and post-explainer shapes — type-safe projections for TUI / IM channel adapters.
  • Emits a dedicated explainer_answer timeline event tagged source="explainer" alongside the existing clarification_response, and adds a confidence-gated escalation_recommended flag + clarification_escalation_recommended event when answer confidence falls below clarification_escalation_confidence (default 0.4). Escalation is advisory — the operator still chooses whether to route to the worker.

Test plan

  • pytest tests/test_operator_models.py (new — 13 tests)
  • pytest tests/test_operator_actions.py (existing test updated to assert 4-event sequence + escalation_recommended)
  • Full suite: pytest — 1216 passed
  • Manual: run thin-supervisor inspect against a live run and confirm clarification now surfaces escalation_recommended (after merge / tag)

Open in Devin Review

- deep_explainer_model (+ temperature/max_tokens) opts drift assessment
  into a heavier reasoner while routine explanations stay on
  explainer_model. Falls back to the routine model, then the structured
  stub, when the deep model is unset or the call fails.
- DriftAssessment and ExchangeView frozen dataclasses (from_dict accepts
  legacy last_*_summary and post-explainer shapes). Unknown drift status
  collapses to "watch"; non-numeric confidence collapses to None.
- Dedicated explainer_answer session-log event with source="explainer",
  emitted alongside the existing clarification_response so future
  worker-side clarification flows can be distinguished without touching
  existing consumers.
- Confidence-gated escalation: when answer confidence <
  clarification_escalation_confidence (default 0.4), the result carries
  escalation_recommended=True and a clarification_escalation_recommended
  event is written. Advisory only — operator still routes.
@coderabbitai

coderabbitai Bot commented Apr 22, 2026

Copy link
Copy Markdown

Warning

Rate limit exceeded

@fakechris has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 50 minutes and 3 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 50 minutes and 3 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 70ae2cfe-4687-459a-a80a-d2500d02e77c

📥 Commits

Reviewing files that changed from the base of the PR and between 05007d6 and bf15c3a.

📒 Files selected for processing (11)
  • CHANGELOG.md
  • README.md
  • pyproject.toml
  • supervisor/config.py
  • supervisor/daemon/server.py
  • supervisor/llm/explainer_client.py
  • supervisor/operator/actions.py
  • supervisor/operator/clarification.py
  • supervisor/operator/models.py
  • tests/test_operator_actions.py
  • tests/test_operator_models.py
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/explainer-tier-0.3.6

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

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 upgrades the supervisor to version 0.3.6, introducing a tiered LLM explainer system and new frozen dataclasses for structured drift assessment and exchange views. It also adds a confidence-gated escalation mechanism for operator clarifications. Review feedback suggests refactoring duplicated logic found in the daemon and operator modules—specifically for confidence value parsing and the processing of clarification results—into shared utility functions to ensure consistency.

Comment thread supervisor/operator/models.py Outdated
Comment on lines +225 to +230
conf = data.get("confidence")
if conf is not None:
try:
conf = float(conf)
except (TypeError, ValueError):
conf = None

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The logic for parsing and coercing the confidence value is duplicated in ExchangeView.from_dict and DriftAssessment.from_dict (lines 287-292), as well as in server.py and actions.py. Consider extracting this into a shared utility function to ensure consistent behavior and reduce boilerplate.

Comment thread supervisor/daemon/server.py Outdated
Comment on lines +997 to +1023
confidence = result.get("confidence")
try:
conf_value = float(confidence) if confidence is not None else None
except (TypeError, ValueError):
conf_value = None
escalate = conf_value is not None and conf_value < escalation_threshold
result["escalation_recommended"] = escalate

_write_event("explainer_answer", {
"source": "explainer",
"question": question,
"answer": result.get("answer", ""),
"confidence": confidence,
})
_write_event("clarification_response", {
"question": question,
"answer": result.get("answer", ""),
"confidence": result.get("confidence"),
"confidence": confidence,
"source": "explainer",
"escalation_recommended": escalate,
})
if escalate:
_write_event("clarification_escalation_recommended", {
"question": question,
"confidence": confidence,
"threshold": escalation_threshold,
})

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This block of logic for processing the clarification result and emitting timeline events is identical to the implementation in supervisor/operator/actions.py (lines 419-461). Duplicating this business logic (including the escalation threshold check and the specific event payloads) increases the risk of inconsistencies when the protocol or requirements change. Consider refactoring this into a shared helper function.

Comment thread supervisor/operator/actions.py Outdated
Comment on lines +419 to +461
confidence = result.get("confidence")
try:
conf_value = float(confidence) if confidence is not None else None
except (TypeError, ValueError):
conf_value = None
escalate = conf_value is not None and conf_value < escalation_threshold
result["escalation_recommended"] = escalate

# Emit explainer_answer — explicit source marker distinguishes
# this from a future worker-side response.
append_timeline_event(
ctx.session_log_path, ctx.run_id,
"explainer_answer",
{
"source": "explainer",
"question": question,
"answer": result.get("answer", ""),
"confidence": confidence,
},
)
# Record the answer in the timeline (legacy event kept for
# backward compatibility with existing consumers).
append_timeline_event(
ctx.session_log_path, ctx.run_id,
"clarification_response",
{
"question": question,
"answer": result.get("answer", ""),
"confidence": result.get("confidence"),
"confidence": confidence,
"source": "explainer",
"escalation_recommended": escalate,
},
)
if escalate:
append_timeline_event(
ctx.session_log_path, ctx.run_id,
"clarification_escalation_recommended",
{
"question": question,
"confidence": confidence,
"threshold": escalation_threshold,
},
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This block of logic for processing the clarification result and emitting timeline events is identical to the implementation in supervisor/daemon/server.py (lines 997-1023). Duplicating this business logic (including the escalation threshold check and the specific event payloads) increases the risk of inconsistencies when the protocol or requirements change. Consider refactoring this into a shared helper function.

devin-ai-integration[bot]

This comment was marked as resolved.

- Fix Devin finding: assess_drift used `is not None` on deep_model while
  line 118 used a falsy check, so an empty-string
  SUPERVISOR_DEEP_EXPLAINER_MODEL env var fell into the deep branch
  and kept deep_temperature/deep_max_tokens even though the effective
  model dropped back to the routine one. Switch to a consistent falsy
  check so empty-string is treated as unset.
- Extract coerce_confidence() helper in operator.models — single
  source of truth for non-numeric → None coercion, now used by
  ExchangeView, DriftAssessment, and the clarification pipeline.
- Extract finalize_clarification() helper in operator.clarification
  so the daemon and local-async paths share the same event sequence
  (explainer_answer + clarification_response + optional escalation)
  and escalation threshold semantics. Eliminates the two copies
  flagged by gemini-code-assist.
@fakechris
fakechris merged commit 10d7a30 into main Apr 23, 2026
6 checks passed
@fakechris
fakechris deleted the feat/explainer-tier-0.3.6 branch April 23, 2026 00:30
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