"""Every create_* tool says what it is NOT for (#3123).

WHY THIS EXISTS

Scribe's record kinds are reached for interchangeably — a note written where
a task was owed, a rule written where a snippet belonged — and the moment of
choice is the only moment a correction is cheap. The tool docstring IS the
agent-facing contract (rule 119 puts product guidance there and nowhere
else), so a docstring that only documents parameters answers "how do I call
this" while leaving "should I be calling this at all" unasked.

The gap was lopsided before this: `create_rule` and `start_planning` both
carried a real disambiguator, and `create_note` — far and away the
highest-volume surface — carried none. Guidance sat in the rarest tool and
was missing from the most common one.

WHAT THIS PINS, AND WHAT IT DOES NOT

It asserts STRUCTURE, never wording: each create surface must name at least
two sibling surfaces, so a caller who reached for the wrong one is told
where the right one is. Prose stays free to be rewritten — pinning phrasing
would make every improvement a test failure, and a test that punishes
editing is a test that gets deleted.

It cannot tell whether the guidance is any GOOD. It only catches the
regression that actually happens: a docstring rewritten down to its
parameters, with the "is this even the right tool" paragraph quietly gone.
"""
import re

import pytest
from tests.helpers import tool_doc as _doc

# The create surfaces and where they live. `start_planning` is here because
# it is a create in everything but name — it is how a plan comes into being.
_SURFACES = [
    ("scribe.mcp.tools.notes", "create_note"),
    ("scribe.mcp.tools.tasks", "create_task"),
    ("scribe.mcp.tools.tasks", "start_planning"),
    ("scribe.mcp.tools.snippets", "create_snippet"),
    ("scribe.mcp.tools.processes", "create_process"),
    ("scribe.mcp.tools.rulebooks", "create_rule"),
    ("scribe.mcp.tools.rulebooks", "create_project_rule"),
]

# What a caller could have wanted instead. A surface naming two of these has
# pointed somewhere; naming none has left them where they were.
_ALTERNATIVES = [
    "create_note", "create_task", "create_rule", "create_project_rule",
    "create_snippet", "create_process", "start_planning", "design system",
]


@pytest.mark.parametrize(("module", "name"), _SURFACES)
def test_a_create_surface_names_at_least_two_alternatives(module, name):
    """Reaching for the wrong tool must still put the right one in view."""
    doc = _doc(module, name)
    named = {
        alt for alt in _ALTERNATIVES
        if alt != name and re.search(re.escape(alt), doc, re.IGNORECASE)
    }
    assert len(named) >= 2, (
        f"{name}'s docstring names {sorted(named) or 'no'} alternative "
        f"surface(s). A caller who reached for it by mistake gets no "
        f"correction. Say what belongs elsewhere and why — see create_rule "
        f"or create_note for the shape."
    )


@pytest.mark.parametrize(("module", "name"), _SURFACES)
def test_a_create_surface_still_documents_its_arguments(module, name):
    """The guard above must not be satisfiable by deleting the parameter docs.

    Both halves matter and they pull in opposite directions: a docstring can
    be made to pass the disambiguator check by becoming an essay about the
    other tools, which would be a worse contract than the one being fixed.
    """
    assert "Args:" in _doc(module, name), (
        f"{name}'s docstring lost its Args: block — the parameter contract is "
        f"what a caller reads to make the call at all."
    )
