feat(KIN-012): auto followup generation and pending_actions auto-resolution

Auto mode now calls generate_followups() after task_auto_approved hook.
Permission-blocked followup items are auto-resolved: rerun first, fallback
to manual_task on failure. Recursion guard skips followup-sourced tasks.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Gros Frumos 2026-03-15 19:49:34 +02:00
parent 01b269e2b8
commit 3cb516193b
4 changed files with 256 additions and 25 deletions

View file

@ -11,7 +11,7 @@ import sqlite3
from core import models
from core.context_builder import format_prompt, PROMPTS_DIR
_PERMISSION_PATTERNS = [
PERMISSION_PATTERNS = [
r"(?i)permission\s+denied",
r"(?i)ручное\s+применение",
r"(?i)не\s+получил[иа]?\s+разрешени[ея]",
@ -27,7 +27,7 @@ _PERMISSION_PATTERNS = [
def _is_permission_blocked(item: dict) -> bool:
"""Check if a follow-up item describes a permission/write failure."""
text = f"{item.get('title', '')} {item.get('brief', '')}".lower()
return any(re.search(p, text) for p in _PERMISSION_PATTERNS)
return any(re.search(p, text) for p in PERMISSION_PATTERNS)
def _collect_pipeline_output(conn: sqlite3.Connection, task_id: str) -> str:
@ -230,3 +230,30 @@ def resolve_pending_action(
return {"rerun_result": result}
return None
def auto_resolve_pending_actions(
conn: sqlite3.Connection,
task_id: str,
pending_actions: list,
) -> list:
"""Auto-resolve pending permission actions in auto mode.
Strategy: try 'rerun' first; if rerun fails escalate to 'manual_task'.
Returns list of resolution results.
"""
results = []
for action in pending_actions:
result = resolve_pending_action(conn, task_id, action, "rerun")
rerun_success = (
isinstance(result, dict)
and isinstance(result.get("rerun_result"), dict)
and result["rerun_result"].get("success")
)
if rerun_success:
results.append({"resolved": "rerun", "result": result})
else:
# Rerun failed → create manual task for human review
manual = resolve_pending_action(conn, task_id, action, "manual_task")
results.append({"resolved": "manual_task", "result": manual})
return results