Python · 3049 bytes Raw Blame History
1 """Tests for Loader's typed system-prompt builder."""
2
3 from __future__ import annotations
4
5 from pathlib import Path
6
7 from loader.context.project import ProjectContext
8 from loader.runtime.prompting import (
9 SYSTEM_PROMPT_DYNAMIC_BOUNDARY,
10 build_system_prompt_result,
11 )
12
13
14 def _tool_schema(name: str = "read") -> dict[str, object]:
15 return {
16 "name": name,
17 "description": "Inspect repository files.",
18 "parameters": {
19 "type": "object",
20 "properties": {
21 "file_path": {
22 "type": "string",
23 "description": "Path to inspect.",
24 }
25 },
26 "required": ["file_path"],
27 },
28 }
29
30
31 def test_prompt_builder_renders_dynamic_sections_with_metadata(temp_dir: Path) -> None:
32 context = ProjectContext(
33 root=temp_dir,
34 project_type="python",
35 package_manager="uv",
36 test_framework="pytest",
37 structure=["src/", "tests/"],
38 test_command="uv run pytest -q",
39 )
40
41 result = build_system_prompt_result(
42 tools=[_tool_schema()],
43 use_react=False,
44 project_context=context,
45 workflow_mode="clarify",
46 permission_mode="prompt",
47 cwd=temp_dir,
48 current_task="Clarify the acceptance criteria for Loader.",
49 )
50
51 assert result.prompt_format == "native"
52 assert result.dynamic_section_names == [
53 "Runtime Config",
54 "Workflow Context",
55 "Mode Guidance",
56 "Project Context",
57 "Project Tips",
58 ]
59 assert SYSTEM_PROMPT_DYNAMIC_BOUNDARY in result.content
60 assert "## Clarify Mode" in result.content
61 assert "Permission mode: `prompt`" in result.content
62 assert "Current task: Clarify the acceptance criteria for Loader." in result.content
63 assert "Package manager: uv" in result.content
64
65
66 def test_prompt_builder_keeps_sections_stable_across_formats(temp_dir: Path) -> None:
67 native = build_system_prompt_result(
68 tools=[_tool_schema("bash")],
69 use_react=False,
70 workflow_mode="execute",
71 permission_mode="workspace-write",
72 cwd=temp_dir,
73 )
74 react = build_system_prompt_result(
75 tools=[_tool_schema("bash")],
76 use_react=True,
77 workflow_mode="execute",
78 permission_mode="workspace-write",
79 cwd=temp_dir,
80 )
81
82 assert native.section_names == react.section_names
83 assert native.dynamic_section_names == react.dynamic_section_names
84 assert "`native`" in native.content
85 assert "`react`" in react.content
86 assert "<tool_call>" in react.content
87 assert "call tools" in native.content.lower()
88
89
90 def test_execute_mode_guidance_prefers_file_tools_for_text_edits(temp_dir: Path) -> None:
91 result = build_system_prompt_result(
92 tools=[_tool_schema("edit")],
93 use_react=False,
94 workflow_mode="execute",
95 permission_mode="workspace-write",
96 cwd=temp_dir,
97 )
98
99 assert "Prefer `edit`/`patch`/`write` over shell one-liners" in result.content