Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 13 additions & 4 deletions src/core/auto_doc_updater.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ def _update_generated_docs(self, root: Path) -> str:

# ─── Internal: обновление README.md ───────────────────

def _count_tools(self, root: Path) -> int:
def _count_tools(self, root: Path, *, include_env_optional: bool = True) -> int:
"""Считает количество MCP-инструментов по местам регистрации.

Зеркалит runtime-константы register_all_tools (32 core + 16 intel +
Expand All @@ -191,7 +191,12 @@ def _count_tools(self, root: Path) -> int:
- intel: @mcp_app.tool(\" в src/core/intelligence/tools_reg.py (14);
- inline: @mcp.tool(\" в server_tools.py (12);
- dev: @mcp_app.tool(\" в src/mcp/tools/dev_tools.py (4);
- ExecuteScriptTool: +1 только при MSCODEBASE_EXECUTE_SCRIPT_ENABLED=true.
- ExecuteScriptTool: +1 только при MSCODEBASE_EXECUTE_SCRIPT_ENABLED=true
и include_env_optional=True.
- include_env_optional=False: базовое детерминированное число (65) без
опционального execute_script — нужно _update_readme, чтобы публичный
заголовок не зависел от локального .env (2026-09-26: README «грязнел»
после каждого reindex на машине с включённым флагом).
"""
mcp_dir = root / "src" / "mcp"
if not mcp_dir.exists():
Expand Down Expand Up @@ -240,7 +245,7 @@ def _count_tools(self, root: Path) -> int:
os.environ.get("MSCODEBASE_EXECUTE_SCRIPT_ENABLED", "false").lower()
== "true"
)
if exec_script_defined and exec_enabled:
if exec_script_defined and exec_enabled and include_env_optional:
core_classes += 1

return core_classes + inline + intel + dev
Expand All @@ -264,7 +269,11 @@ def _update_readme(self, root: Path) -> bool:

text = readme_path.read_text(encoding="utf-8")

tool_count = self._count_tools(root)
# README-контракт (строка "65 registered = ... + опциональный
# execute_script → 66") требует ДЕТЕРМИНИРОВАННОГО числа: опциональный
# инструмент не должен менять публичный заголовок из-за локального .env,
# иначе README «грязнеет» после каждого reindex (2026-09-26).
tool_count = self._count_tools(root, include_env_optional=False)
test_count = self._count_tests(root)

# Бейдж тестов: обновляем только точную форму tests-N%20passed
Expand Down
24 changes: 24 additions & 0 deletions tests/test_auto_doc_updater.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,3 +157,27 @@ def test_count_tools_real_project_guard():
assert tools >= 44, f"_count_tools вернул {tools} — снова баг подсчёта?"
if os.environ.get("MSCODEBASE_EXECUTE_SCRIPT_ENABLED", "false").lower() != "true":
assert tools == 65, f"ожидалось 65 (README-контракт), получено {tools}"


def test_update_readme_tools_count_is_env_independent(tmp_path, monkeypatch):
"""Заголовок README не зависит от MSCODEBASE_EXECUTE_SCRIPT_ENABLED.

Контракт README (строка «65 registered ... опциональный execute_script → 66»)
и AGENTS.md требует ДЕТЕРМИНИРОВАННОГО публичного числа. Иначе на машине с
включённым флагом README «грязнеет» после каждого reindex (2026-09-26):
заголовок → 66, а примечание остаётся 65.
"""
root = _make_tree(tmp_path)
(tmp_path / "src" / "mcp" / "tools" / "codebase_tool.py").write_text(
"class CodebaseTool:\n pass\n\nclass ExecuteScriptTool:\n pass\n",
encoding="utf-8",
)
monkeypatch.setenv("MSCODEBASE_EXECUTE_SCRIPT_ENABLED", "true")

updater = AutoDocUpdater()
assert updater._count_tools(root) == 5 # runtime-счётчик видит опцию
assert updater._update_readme(root) is True

text = (tmp_path / "README.md").read_text(encoding="utf-8")
assert "## 🔧 MCP Tools (4 total)" in text # базовое число (не 5)
assert "#mcp-tools-4-total" in text
Loading