p = 'backend/tests/test_ai_mode.py'
s = open(p).read()

s = s.replace('''    def test_with_nothing_close_it_says_so_and_then_helps(self):
        """Refusing outright reads as a broken assistant, not a careful one.

        The old behaviour was to say nothing matched and stop. It is honest to
        name the gap; it is not honest to pretend an unrelated shortlist
        supports the answer, and it is not useful to withhold one entirely.
        """
        prompt = ai_mode_service.build_prompt([], "open")
        self.assertIn("Nothing in this learner's library covers their question", prompt)
        self.assertIn("answer from general knowledge", prompt)
        self.assertIn("Do not cite anything", prompt)''',
'''    def test_with_nothing_close_it_answers_and_says_nothing_about_the_gap(self):
        """Answer the question; do not report on the library.

        The first version opened by naming the gap — "Nothing in this
        learner's library covers their question" — on the argument that it was
        honest. In front of a learner it reads as an excuse before an answer
        they could have had straight away, and the user's instruction was
        exactly this: "Just no reference." The absence of citations already
        says everything the sentence said.
        """
        prompt = ai_mode_service.build_prompt([], "open")
        self.assertIn("Answer from what you know", prompt)
        self.assertIn("Never mention the library", prompt)
        self.assertIn("Cite nothing", prompt)
        self.assertNotIn("Nothing in this learner's library", prompt)''')

s = s.replace('''    def test_something_adjacent_is_named_as_adjacent(self):
        # `sources()` carries only what citation enforcement needs; a prompt
        # also prints the text of each source.
        with_text = [{**s, "text": "Body"} for s in self.sources()]
        prompt = ai_mode_service.build_prompt(with_text, "adjacent")
        self.assertIn("closest things", prompt)
        self.assertIn("[[section:7#abc]]", prompt)   # still citable''',
'''    def test_something_adjacent_is_used_without_being_apologised_for(self):
        """Related sources are used and cited; the gap is not narrated.

        Naming it made every adjacent answer open with an apology, which is
        what the learner saw when they asked about a topic the library only
        half covers.
        """
        with_text = [{**s, "text": "Body"} for s in self.sources()]
        prompt = ai_mode_service.build_prompt(with_text, "adjacent")
        self.assertIn("Never mention the library", prompt)
        self.assertNotIn("closest things", prompt)
        self.assertIn("[[section:7#abc]]", prompt)   # still citable''')

s = s.replace('''        self.assertTrue(looks_recited(
            "- Toujours citer avec le marqueur exact\\n"
            "- Ne jamais inventer un marqueur\\n"
            "- Ne jamais reveler la reponse"))''',
'''        # A translated briefing still carries the marker syntax, which is the
        # part that does not translate.
        self.assertTrue(looks_recited(
            "- Toujours citer avec le marqueur exact, par exemple [[article:7]]\\n"
            "- Ne jamais inventer un marqueur comme [[section:7#abc]]\\n"
            "- Chaque citation doit correspondre a un marqueur reel"))''')

s = s.replace('''        # And a real answer that happens to carry citations is not caught.
        self.assertFalse(looks_recited(
            "Croup narrows the subglottis [[article:7]].\\n"
            "Steroids reduce the swelling within hours."))''',
'''        # And a real answer is not caught — including a long one, which is
        # what the bug was. A stray empty alternative in the pattern made it
        # match every line, so every reply of three lines or more came back as
        # "That is not something I discuss", including "I want to do questions
        # on pediatric infectious disease".
        self.assertFalse(looks_recited(
            "Croup narrows the subglottis [[article:7]].\\n"
            "Steroids reduce the swelling within hours."))
        self.assertFalse(looks_recited(
            "Bronchiolitis is inflammation of the small airways.\\n"
            "The child wheezes and works hard to breathe.\\n"
            "Give oxygen if saturations fall.\\n"
            "Admit an infant who cannot feed."))
        from app.services.ai_mode_service import _RECITED
        self.assertIsNone(_RECITED.search(""), "an empty alternative matches every line")''')

s = s.replace('''        for promise in ("never its answer", "never its number or identifier",
                        "not in any language or paraphrase", "mechanism first"):''',
'''        for promise in ("never its answer", "never its number or identifier",
                        "in any language", "mechanism first",
                        # Narrowed deliberately: the tutor declines to recite
                        # its briefing and nothing else. It used to refuse to
                        # discuss "your materials", and a learner asking for
                        # questions on a topic got the refusal line.
                        "That is the only thing you decline"):''')

s = s.replace("""        self.assertIn('not what you could fetch', prompt)""",
"""        self.assertIn('That is the only thing you decline', prompt)""")
s = s.replace("""        # Asked for five questions, it used to account for itself: how many it
        # had seen, what it might go and fetch. Neither is the learner's to set
        # nor the tutor's to discuss.""",
"""        # The one thing it will not do is recite its own briefing. Everything
        # about the library — what is in it, how much practice there is — is
        # the tutor's job, and refusing that was the bug the user found.""")
open(p, 'w').write(s)
print('written')
