feat(agent): align the document tools with the harness-trained shape — ls, read(path), grep(pattern, path?)
This commit is contained in:
@@ -138,6 +138,68 @@ def test_zero_note_prompt_is_byte_identical_to_pre_steering() -> None:
|
||||
)
|
||||
assert "<tuning>" not in build_high_prompt([doc])
|
||||
assert "<tuning>" not in build_deflect_prompt([])
|
||||
# Phase 70: the rewritten <tools> copy stays out of the LOW path —
|
||||
# the byte-identical equality above already proves it; this names
|
||||
# the contract (no <tools>, no new copy) on both empty/non-empty LOW
|
||||
# builds.
|
||||
for low in (build_deflect_prompt(["T1"]), build_deflect_prompt([])):
|
||||
assert "<tools>" not in low
|
||||
assert TOOLS_SECTION not in low
|
||||
|
||||
|
||||
# ---------- <tools> section copy (phase 70: ls / read / grep) ----------
|
||||
|
||||
|
||||
def test_tools_section_markers_and_new_tool_names() -> None:
|
||||
"""Phase 70: the section keeps the ``<tools>``/``</tools>`` markers
|
||||
the E2E mock keys on and teaches the harness-aligned tool names
|
||||
(backticked, exactly as the ``AGENT_TOOLS`` schemas name them)."""
|
||||
assert TOOLS_SECTION.startswith("<tools>\n")
|
||||
assert TOOLS_SECTION.rstrip().endswith("</tools>")
|
||||
for tool in ("`ls`", "`grep`", "`read`"):
|
||||
assert tool in TOOLS_SECTION
|
||||
|
||||
|
||||
def test_tools_section_teaches_the_harness_shapes() -> None:
|
||||
"""Copy pins: ``ls``'s phase-63 catalog-line format (and its
|
||||
optional one-source scope), ``grep``'s case-insensitive exact-string
|
||||
locator contract (up to 20 ``source/path:line: text`` lines, a
|
||||
locator not a context-adder), and ``read``'s combined
|
||||
``source/path`` + full content."""
|
||||
assert "source: X | path: Y | title: Z" in TOOLS_SECTION
|
||||
assert "pass a source name as `path`" in TOOLS_SECTION
|
||||
assert "case-insensitive" in TOOLS_SECTION
|
||||
assert "up to 20" in TOOLS_SECTION
|
||||
assert "source/path:line: text" in TOOLS_SECTION
|
||||
assert "locator, not a context-adder" in TOOLS_SECTION
|
||||
assert "combined `source/path`" in TOOLS_SECTION
|
||||
assert "full content" in TOOLS_SECTION
|
||||
assert "Answer as soon as you have what you need" in TOOLS_SECTION
|
||||
|
||||
|
||||
def test_tools_section_old_names_and_budget_copy_gone() -> None:
|
||||
"""The phase-37/68 tool names and the phase-37 per-tool budget line
|
||||
(phase 45: the round cap is the bound — the prompt does not
|
||||
re-state it) are out of the copy."""
|
||||
for old in ("list_documents", "read_document", "search_documents"):
|
||||
assert old not in TOOLS_SECTION
|
||||
assert "more than one" not in TOOLS_SECTION
|
||||
assert "extra document" not in TOOLS_SECTION
|
||||
|
||||
|
||||
def test_high_prompt_still_ends_with_tools_section() -> None:
|
||||
"""Mock keying intact: the HIGH prompt still ends with the
|
||||
``<tools>`` section after ``</documents>``, now in the phase-70
|
||||
copy — new names in, old names out."""
|
||||
doc = _doc("kubernetes.md", "Talos Linux on three nodes.", "Kubernetes Homelab Cluster")
|
||||
prompt = build_high_prompt([doc])
|
||||
assert TOOLS_SECTION in prompt
|
||||
assert prompt.index("</documents>") < prompt.index("<tools>")
|
||||
assert prompt.rstrip().endswith("</tools>")
|
||||
for tool in ("`ls`", "`grep`", "`read`"):
|
||||
assert tool in prompt
|
||||
for old in ("list_documents", "read_document", "search_documents"):
|
||||
assert old not in prompt
|
||||
|
||||
|
||||
def test_relevance_placeholder_rejected_for_garbage() -> None:
|
||||
|
||||
Reference in New Issue
Block a user