Skip to content

Commit 36da03e

Browse files
committed
2 parents ab3afb0 + f509e4b commit 36da03e

File tree

6 files changed

+64
-8
lines changed

6 files changed

+64
-8
lines changed
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
---
2+
title: Make Ruff import sorting deterministic across local and CI
3+
type: delta
4+
link: ruff-import-order-determinism
5+
path: pyproject.toml
6+
depth: 1
7+
seams: [M]
8+
ontological_relations:
9+
- affects: [[tooling]]
10+
- affects: [[ci]]
11+
- affects: [[imports]]
12+
tags:
13+
- ruff
14+
- pre-commit
15+
- ci
16+
- import-order
17+
created_at: 2026-03-03T04:30:00+00:00
18+
updated_at: 2026-03-03T04:30:00+00:00
19+
uuid: 1563860a-585a-49eb-a57a-52eb721c5912
20+
---
21+
22+
# Make Ruff import sorting deterministic across local and CI
23+
24+
## Summary
25+
26+
Added `src = ["src"]` under `[tool.ruff]` so Ruff/isort classifies first-party modules from `src/` only.
27+
28+
This prevents local environment differences (for example, an untracked `tinyAgent/` directory) from changing how `tinyagent` imports are grouped.
29+
30+
Re-applied import sorting in files that were flipping between local and CI:
31+
32+
- `src/tunacode/core/agents/agent_components/agent_config.py`
33+
- `src/tunacode/core/agents/main.py`
34+
- `src/tunacode/tools/decorators.py`
35+
- `tests/benchmarks/bench_discover.py`
36+
37+
## Why
38+
39+
PR #407 was failing the `pre-commit` GitHub check because Ruff auto-fixed imports in CI and exited with code 1.
40+
Local pre-commit passed after fixes, but CI still re-sorted imports due different module classification.
41+
42+
## Validation
43+
44+
- `uv run pre-commit run --all-files`
45+
- `uv run pytest tests/integration/core/test_minimax_execution_path.py tests/integration/core/test_mtime_caches_end_to_end.py tests/system/cli/test_repl_support.py tests/unit/tools/test_tinyagent_tool_adapter.py -q`

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ Documentation = "https://github.com/alchemiststudiosDOTai/tunacode#readme"
9191

9292
[tool.ruff]
9393
line-length = 100
94+
src = ["src"]
9495

9596
[tool.ruff.lint]
9697
select = [

src/tunacode/tools/decorators.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -191,10 +191,7 @@ async def execute(
191191
bound = sig.bind(**args)
192192
bound.apply_defaults()
193193
except TypeError as exc:
194-
raise ToolRetryError(
195-
f"Invalid arguments for tool '{tool_name}': {exc}. "
196-
f"Expected schema: {parameters_schema}"
197-
) from exc
194+
raise ToolRetryError(f"Invalid arguments for tool '{tool_name}': {exc}") from exc
198195

199196
result = await func(**cast(dict[str, Any], bound.arguments))
200197

src/tunacode/ui/repl_support.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,13 @@ def _truncate_for_safety(content: str | None) -> str | None:
187187
return truncated_result
188188

189189

190+
def _is_validation_error(result: str | None) -> bool:
191+
"""Check if result is a validation error that should go to model, not user."""
192+
if result is None:
193+
return False
194+
return "Invalid arguments for tool" in result and "missing a required argument" in result
195+
196+
190197
def build_tool_result_callback(app: AppForCallbacks) -> ToolResultCallback:
191198
def _callback(
192199
tool_name: ToolName,
@@ -204,6 +211,10 @@ def _callback(
204211
app.status_bar.complete_running_action(tool_name)
205212
app.status_bar.update_last_action(tool_name)
206213

214+
# Don't show validation errors to users - they go back to model for retry
215+
if status == "failed" and _is_validation_error(result):
216+
return
217+
207218
safe_result = _truncate_for_safety(result)
208219

209220
app.post_message(

tests/integration/core/test_minimax_execution_path.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,10 @@ async def _fake_stream(model: Any, context: Any, options: dict[str, Any]) -> _Fa
5959
return _FakeResponse()
6060

6161
monkeypatch.setattr(agent_config, "stream_alchemy_openai_completions", _fake_stream)
62-
monkeypatch.setattr(agent_config, "load_system_prompt", lambda _base_path, model=None: "")
63-
monkeypatch.setattr(agent_config, "load_tunacode_context", lambda: "")
62+
monkeypatch.setattr(
63+
agent_config, "load_system_prompt", lambda _base_path, model=None: ("", None)
64+
)
65+
monkeypatch.setattr(agent_config, "load_tunacode_context", lambda: ("", None))
6466

6567
agent = agent_config.get_or_create_agent(MINIMAX_CODING_PLAN_MODEL, state_manager)
6668
response_text = await agent.prompt_text("Reply with ok")

tests/integration/core/test_mtime_caches_end_to_end.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ def test_tunacode_context_cache_invalidates_on_mtime_ns(
4343
second = load_tunacode_context()
4444

4545
assert first == second
46-
assert "one" in first
46+
assert "one" in first[0]
4747

4848
agents_path.write_text("two\n", encoding="utf-8")
4949

@@ -54,7 +54,7 @@ def test_tunacode_context_cache_invalidates_on_mtime_ns(
5454
third = load_tunacode_context()
5555

5656
assert third != first
57-
assert "two" in third
57+
assert "two" in third[0]
5858

5959

6060
def test_ignore_manager_cache_invalidates_on_mtime_ns(

0 commit comments

Comments
 (0)