"""Personality + durability edge cases for the live agent battery.

Focus: Callie stays grounded (tools + workspace files, not generic AI theater) while
durable-work requests reliably land on kanban — including similar-but-different phrasing.

Imported by ``kernel_live_agent_battery.py``.
"""
from __future__ import annotations

from scripts.kernel_live_agent_types import Case

_GENERIC_AI_FORBID = (
    "as an ai language model",
    "as a language model",
    "I am an AI assistant",
    "openai",
    "chatgpt",
)

_SYSTEM_ARTIFACT_FORBID = (
    "agent_loop",
    "USER Model",
    "user_model.py",
    "kernel_wiring",
)

PERSONALITY_DURABILITY_CASES: list[Case] = [
    # ═══ Personality — identity, warmth, grounded noticing ═══
    Case(
        id="personality_read_persona",
        pillar="personality",
        prompt=(
            "Who are you, really? read_file PERSONA.md limit 25 lines before answering. "
            "Reply in 2 warm sentences — no tool names to me."
        ),
        required_tools=("read_file",),
        forbid_assistant_patterns=_GENERIC_AI_FORBID + ("PERSONA.md",),
        forbid_patterns_assistant_only=True,
        min_tool_calls=1,
        timeout_sec=120.0,
    ),
    Case(
        id="personality_read_user_grounded",
        pillar="personality",
        prompt=(
            "I want you to know me — read_file USER.md limit 20 lines. "
            "Summarize one fact about me in a single sentence."
        ),
        required_tools=("read_file",),
        forbid_assistant_patterns=_SYSTEM_ARTIFACT_FORBID,
        min_tool_calls=1,
    ),
    Case(
        id="personality_read_soul_tone",
        pillar="personality",
        prompt=(
            "read_file SOUL.md limit 20 lines. Reply TONE_OK if you read it, or MISSING."
        ),
        required_tools=("read_file",),
        min_tool_calls=1,
        timeout_sec=90.0,
    ),
    Case(
        id="personality_who_are_you_not_generic",
        pillar="personality",
        prompt="Who are you? Use read_file on PERSONA.md or IDENTITY.md (pick one) before replying.",
        required_tools=("read_file",),
        forbid_assistant_patterns=_GENERIC_AI_FORBID,
        min_tool_calls=1,
    ),
    Case(
        id="personality_similar_who_is_callie",
        pillar="personality",
        prompt=(
            "Remind me — who's Callie? read_file IDENTITY.md limit 15 lines. "
            "One sentence only."
        ),
        required_tools=("read_file",),
        min_tool_calls=1,
    ),
    Case(
        id="personality_similar_who_is_josh",
        pillar="personality",
        prompt=(
            "Who is Josh? read_file USER.md limit 15 — do not guess from training data."
        ),
        required_tools=("read_file",),
        forbid_assistant_patterns=_GENERIC_AI_FORBID,
        min_tool_calls=1,
    ),
    Case(
        id="personality_warm_but_must_search",
        pillar="personality",
        prompt=(
            "Hey — quick favor: what's MLX up to lately? "
            "search_web query 'Apple MLX 2026' max_results 2. Reply with titles only."
        ),
        required_tools=("search_web",),
        forbid_assistant_patterns=("here's what i found",) + _GENERIC_AI_FORBID,
        min_tool_calls=1,
        timeout_sec=150.0,
        notes="Warm opener must not skip search_web.",
    ),
    Case(
        id="personality_memory_noticing",
        pillar="personality",
        prompt=(
            "What do you remember about my preferences? search_memory query 'Josh preferences' "
            "max_results 3. Reply FOUND or EMPTY."
        ),
        required_tools=("search_memory",),
        min_tool_calls=1,
    ),
    Case(
        id="personality_sessions_recall_warm",
        pillar="personality",
        prompt=(
            "Catch me up — search_sessions query 'kanban' max_results 2. "
            "Reply SESSIONS=N (0 if none)."
        ),
        required_tools=("search_sessions",),
        min_tool_calls=1,
        timeout_sec=120.0,
    ),
    Case(
        id="personality_propose_hypothesis_trust",
        pillar="personality",
        prompt=(
            "Hypothesis only: I might like evening walks. "
            "Use propose_user_model_update with changes "
            '{"preferences": {"wellness": "might enjoy evening walks"}} '
            "and a short rationale — do NOT patch_user_model or append_to_memory. "
            "Reply PROPOSED or tool error."
        ),
        required_tools=("propose_user_model_update",),
        forbid_tool_calls=("patch_user_model", "append_to_memory"),
        min_tool_calls=1,
        timeout_sec=120.0,
    ),
    Case(
        id="personality_frustrated_kanban_empathy_plus_act",
        pillar="personality",
        prompt=(
            "I'm frustrated — the kanban board feels stale. Don't lecture me; "
            "kanban_list_tasks limit 5 this turn and tell me READY=N."
        ),
        required_tools=("kanban_list_tasks",),
        min_tool_calls=1,
        notes="Warm frustration must still execute list, not only empathy.",
    ),
    Case(
        id="personality_multi_warm_then_list",
        pillar="personality",
        prompt="Good morning — hope you're well. Reply GOOD only.",
        follow_up_prompts=(
            "kanban_list_tasks limit 3. Reply COUNT only.",
        ),
        follow_up_any_of_tools=(("kanban_list_tasks",),),
        follow_up_min_tools=(1,),
        allow_zero_tool_final_reply=True,
        min_tool_calls=1,
        timeout_sec=90.0,
    ),
    Case(
        id="personality_pivot_identity_to_durable",
        pillar="personality",
        prompt="read_file USER.md limit 10 lines. Reply READ_OK.",
        follow_up_prompts=(
            "Separate ask: file ONE ready root kanban task title 'Personality durable pivot' "
            "assignee general via kanban_create_task. Reply id only.",
        ),
        follow_up_required_tools=(("kanban_create_task",),),
        follow_up_min_tools=(1,),
        required_tools=("read_file",),
        min_tool_calls=2,
        timeout_sec=120.0,
    ),
    Case(
        id="personality_no_system_jargon",
        pillar="personality",
        prompt=(
            "search_memory query 'Mugi'. Reply in one friendly sentence — "
            "never mention file paths or internal system names."
        ),
        required_tools=("search_memory",),
        forbid_assistant_patterns=_SYSTEM_ARTIFACT_FORBID + ("MEMORY.md", "USER.md"),
        forbid_patterns_assistant_only=True,
        min_tool_calls=1,
    ),
    Case(
        id="personality_task_plan_conversational",
        pillar="personality",
        prompt=(
            "Let's sketch today: find_tools 'task plan' then update_task_plan with steps "
            "['Morning focus', 'Afternoon errands']. Reply PLAN_OK."
        ),
        required_tools=("find_tools", "update_task_plan"),
        min_tool_calls=2,
        timeout_sec=120.0,
    ),
    Case(
        id="personality_similar_focus_question",
        pillar="personality",
        prompt=(
            "What's on my plate lately? search_memory query 'focus goals' then "
            "read_file USER.md limit 10. Reply FOCUS or EMPTY."
        ),
        required_tools=("search_memory", "read_file"),
        min_tool_calls=2,
        timeout_sec=120.0,
    ),
    Case(
        id="personality_no_emoji_only_reply",
        pillar="personality",
        prompt=(
            "read_file AGENTS.md limit 10 lines. Reply YES if loaded."
        ),
        required_tools=("read_file",),
        forbid_assistant_patterns=("👻✨",),
        min_tool_calls=1,
    ),
    Case(
        id="personality_attribution_requires_memory",
        pillar="personality",
        prompt=(
            "I'm picking a laptop — search_memory query 'laptop reliability' first. "
            "If FOUND, start your reply with 'You mentioned'. If EMPTY, say EMPTY."
        ),
        required_tools=("search_memory",),
        min_tool_calls=1,
    ),
    # ═══ Durable edge — similar phrasing, kanban planner reliability ═══
    Case(
        id="durable_edge_single_root_minimal",
        pillar="durable",
        prompt=(
            "Durable: kanban_create_batch with exactly one ready root — "
            'title "Edge minimal root", assignee general, priority 4. Reply id.'
        ),
        required_tools=("kanban_create_batch",),
        min_tool_calls=1,
    ),
    Case(
        id="durable_edge_create_task_wording",
        pillar="durable",
        prompt=(
            "Track this across days: kanban_create_task title 'Edge task wording' "
            "body 'durable probe' assignee general priority 3. Reply id only."
        ),
        required_tools=("kanban_create_task",),
        min_tool_calls=1,
    ),
    Case(
        id="durable_edge_similar_put_on_board",
        pillar="durable",
        prompt=(
            "Can you put a multi-day docs audit on the board for me? "
            "kanban_create_batch: one ready root assignee coding + one research child "
            "parent_index 0. Reply root id — do not run the audit in chat."
        ),
        required_tools=("kanban_create_batch",),
        forbid_tool_calls=("kanban_cancel_task",),
        min_tool_calls=1,
        timeout_sec=150.0,
    ),
    Case(
        id="durable_edge_similar_track_durable_work",
        pillar="durable",
        prompt=(
            "I need to track this as durable work — refactor the dispatcher over several days. "
            "File kanban_create_batch with root + 2 children (research + coding). Reply ids."
        ),
        required_tools=("kanban_create_batch",),
        min_tool_calls=1,
        timeout_sec=150.0,
    ),
    Case(
        id="durable_edge_long_horizon_wording",
        pillar="durable",
        prompt=(
            "Over the next few days I want this on kanban: 'Edge horizon probe' root assignee "
            "general plus one research child. kanban_create_batch now. Reply root id."
        ),
        required_tools=("kanban_create_batch",),
        forbid_tool_calls=("kanban_cancel_task",),
        min_tool_calls=1,
    ),
    Case(
        id="durable_edge_noop_warm_file_later",
        pillar="durable",
        prompt=(
            "When you get a chance, add a kanban task for cleaning up old battery probes — "
            "but you MUST call kanban_create_task or kanban_create_batch this turn, not later."
        ),
        any_of_tools=("kanban_create_task", "kanban_create_batch"),
        min_tool_calls=1,
        timeout_sec=120.0,
    ),
    Case(
        id="durable_edge_assembly_priority_fanin",
        pillar="durable",
        prompt=(
            "kanban_create_batch DAG: root 'Edge assembly' assignee general, "
            "two research children parent_index 0, assembly child parent_indices [1,2] "
            "assignee general priority 1 (lower than children at 5). Reply root id."
        ),
        required_tools=("kanban_create_batch",),
        min_tool_calls=1,
        timeout_sec=150.0,
    ),
    Case(
        id="durable_edge_research_coding_assignees",
        pillar="durable",
        prompt=(
            "kanban_create_batch: root assignee general, child A assignee research "
            "parent_index 0, child B assignee code_readonly parent_index 0. Reply root id."
        ),
        required_tools=("kanban_create_batch",),
        min_tool_calls=1,
    ),
    Case(
        id="durable_edge_metadata_acceptance",
        pillar="durable",
        prompt=(
            "kanban_create_task title 'Edge metadata' assignee research body 'probe' "
            'metadata {"acceptance": "exports a markdown summary"}. Reply id.'
        ),
        any_of_tools=("kanban_create_task", "kanban_create_batch"),
        min_tool_calls=1,
    ),
    Case(
        id="durable_edge_no_cancel_storm",
        pillar="durable",
        prompt=(
            "kanban_list_tasks limit 3. Do NOT cancel anything. Reply COUNT."
        ),
        required_tools=("kanban_list_tasks",),
        forbid_tool_calls=("kanban_cancel_task",),
        min_tool_calls=1,
    ),
    Case(
        id="durable_edge_no_chat_research_for_durable",
        pillar="durable",
        prompt=(
            "Multi-day literature review on local LLMs — put it on kanban, don't search_web "
            "in chat. kanban_create_batch root + one research child. Reply root id."
        ),
        required_tools=("kanban_create_batch",),
        forbid_tool_calls=("search_web", "kanban_cancel_task"),
        min_tool_calls=1,
        timeout_sec=120.0,
    ),
    Case(
        id="durable_edge_find_tools_then_batch",
        pillar="durable",
        prompt=(
            "find_tools query 'kanban create batch' then kanban_create_batch one ready root "
            'title "Edge find+batch" assignee general. Reply id.'
        ),
        required_tools=("find_tools", "kanban_create_batch"),
        min_tool_calls=2,
    ),
    Case(
        id="durable_edge_create_then_list_runs",
        pillar="durable",
        prompt="kanban_create_task title 'Edge runs probe' assignee general body 'x'. Reply id only.",
        follow_up_prompts=(
            "kanban_list_runs on the task id from your prior create. Reply RUNS=N.",
        ),
        follow_up_required_tools=(("kanban_list_runs",),),
        follow_up_min_tools=(1,),
        any_of_tools=("kanban_create_task", "kanban_create_batch"),
        min_tool_calls=2,
        timeout_sec=120.0,
    ),
    Case(
        id="durable_edge_pivot_list_to_create",
        pillar="durable",
        prompt="kanban_list_tasks limit 5. Reply COUNT.",
        follow_up_prompts=(
            "New durable item: kanban_create_task title 'Edge pivot create' assignee general. "
            "Reply new id only.",
        ),
        follow_up_required_tools=(("kanban_create_task",),),
        follow_up_min_tools=(1,),
        required_tools=("kanban_list_tasks",),
        min_tool_calls=2,
        timeout_sec=120.0,
    ),
    Case(
        id="durable_edge_two_roots_retry_wording",
        pillar="durable",
        prompt=(
            "kanban_create_batch with TWO ready roots (invalid). On rejection, retry with "
            "one root + one child assignee research. Report final root id."
        ),
        required_tools=("kanban_create_batch",),
        min_tool_calls=1,
        timeout_sec=150.0,
    ),
    Case(
        id="durable_edge_invalid_assignee_research_recovery",
        pillar="durable",
        prompt=(
            "kanban_create_task title 'Edge assignee' assignee 'callie' body 'x'. "
            "On error retry assignee research. Report final id. Do not use kanban_create_batch."
        ),
        required_tools=("kanban_create_task",),
        require_tool_error_substrings=("unknown assignee profile",),
        min_tool_calls=1,
    ),
    Case(
        id="durable_edge_show_after_create",
        pillar="durable",
        prompt=(
            "kanban_create_task title 'Edge show after' assignee general body 'probe'. "
            "Reply id only."
        ),
        follow_up_prompts=(
            "kanban_show_task on that id. Reply status= only.",
        ),
        follow_up_required_tools=(("kanban_show_task",),),
        follow_up_min_tools=(1,),
        any_of_tools=("kanban_create_task", "kanban_create_batch"),
        min_tool_calls=2,
        timeout_sec=120.0,
    ),
    Case(
        id="durable_edge_batch_string_items_explicit",
        pillar="durable",
        prompt=(
            'kanban_create_batch items JSON array: one ready root title "Edge JSON items" '
            "assignee general priority 4. Reply created id."
        ),
        required_tools=("kanban_create_batch",),
        forbid_assistant_patterns=("items must be a list of task dicts",),
        min_tool_calls=1,
    ),
    Case(
        id="durable_edge_similar_next_week",
        pillar="durable",
        prompt=(
            "Next week I need the vault cleanup done — file it on kanban as root + child, "
            "don't do cleanup in chat. Reply root id."
        ),
        required_tools=("kanban_create_batch",),
        min_tool_calls=1,
    ),
    Case(
        id="durable_edge_subscribe_discover",
        pillar="durable",
        prompt=(
            "find_tools query 'kanban notify subscribe' — if a subscribe tool exists, "
            "report its name; else SUBSCRIBE_NONE. Must call find_tools."
        ),
        required_tools=("find_tools",),
        min_tool_calls=1,
        timeout_sec=90.0,
    ),
]
