Fix bootstrap: deep scan, CLAUDE.md fallback, noise filtering

1. Tech stack: recursive file search (depth 3) + CLAUDE.md text fallback
   when config files are on remote server (detects nodejs, postgresql, etc.)
2. Modules: scan */src/ patterns in top-level dirs (frontend/src/, backend-pg/src/)
3. Decisions: filter out unrelated sections (Jitsi, Nextcloud, Prosody, GOIP),
   filter noise (commit hashes, shell commands, external service paths).
   Noise filtering also applied to Obsidian decisions.

Tested on vdolipoperek: 4 tech, 5 modules, 9 clean decisions, 24 Obsidian tasks.
61 tests, all passing.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
johnfrum1234 2026-03-15 13:37:42 +02:00
parent da4a8aae72
commit e5444114bd
3 changed files with 344 additions and 94 deletions

View file

@ -67,6 +67,27 @@ def test_detect_monorepo(tmp_path):
assert "fastapi" in stack
def test_detect_deep_monorepo(tmp_path):
"""Test that files nested 2-3 levels deep are found (like vdolipoperek)."""
fe = tmp_path / "frontend" / "src"
fe.mkdir(parents=True)
(tmp_path / "frontend" / "package.json").write_text(json.dumps({
"dependencies": {"vue": "^3.4"},
"devDependencies": {"vite": "^5.0", "tailwindcss": "^3.4"},
}))
(tmp_path / "frontend" / "vite.config.js").write_text("export default {}")
(tmp_path / "frontend" / "tailwind.config.js").write_text("module.exports = {}")
be = tmp_path / "backend-pg" / "src"
be.mkdir(parents=True)
(be / "index.js").write_text("const express = require('express');")
stack = detect_tech_stack(tmp_path)
assert "vue3" in stack
assert "vite" in stack
assert "tailwind" in stack
def test_detect_empty_dir(tmp_path):
assert detect_tech_stack(tmp_path) == []
@ -104,6 +125,36 @@ def test_detect_modules_backend_pg(tmp_path):
assert any(m["name"] == "services" for m in modules)
def test_detect_modules_monorepo(tmp_path):
"""Full monorepo: frontend/src/ + backend-pg/src/."""
# Frontend
fe_views = tmp_path / "frontend" / "src" / "views"
fe_views.mkdir(parents=True)
(fe_views / "Hotel.vue").write_text("<template></template>")
fe_comp = tmp_path / "frontend" / "src" / "components"
fe_comp.mkdir(parents=True)
(fe_comp / "Search.vue").write_text("<template></template>")
# Backend
be_svc = tmp_path / "backend-pg" / "src" / "services"
be_svc.mkdir(parents=True)
(be_svc / "db.js").write_text("const express = require('express');")
be_routes = tmp_path / "backend-pg" / "src" / "routes"
be_routes.mkdir(parents=True)
(be_routes / "api.js").write_text("const router = require('express').Router();")
modules = detect_modules(tmp_path)
names = {m["name"] for m in modules}
assert "views" in names
assert "components" in names
assert "services" in names
assert "routes" in names
# Check types
types = {m["name"]: m["type"] for m in modules}
assert types["views"] == "frontend"
assert types["components"] == "frontend"
# ---------------------------------------------------------------------------
# Decisions from CLAUDE.md
# ---------------------------------------------------------------------------
@ -124,7 +175,7 @@ FIXME: race condition in useSearch composable
- CSS grid fallback для IE11 (но мы его не поддерживаем)
""")
decisions = extract_decisions_from_claude_md(tmp_path)
decisions = extract_decisions_from_claude_md(tmp_path, "myproj", "My Project")
assert len(decisions) >= 4
types = {d["type"] for d in decisions}
@ -136,6 +187,58 @@ def test_extract_decisions_no_claude_md(tmp_path):
assert extract_decisions_from_claude_md(tmp_path) == []
def test_extract_decisions_filters_unrelated_sections(tmp_path):
"""Sections about Jitsi, Nextcloud, Prosody should be skipped."""
(tmp_path / "CLAUDE.md").write_text("""# vdolipoperek
## Known Issues
1. **Hotel ID mismatch** Sletat GetTours vs GetHotels разные ID
2. **db.js export** module.exports = pool (НЕ { pool })
## Jitsi + Nextcloud интеграция (2026-03-04)
ВАЖНО: JWT_APP_SECRET must be synced between Prosody and Nextcloud
GOTCHA: focus.meet.jitsi must be pinned in custom-config.js
## Prosody config
ВАЖНО: conf.d files принадлежат root писать через docker exec
## Git Sync (2026-03-03)
ВАЖНО: Все среды синхронизированы на коммите 4ee5603
""")
decisions = extract_decisions_from_claude_md(tmp_path, "vdol", "vdolipoperek")
titles = [d["title"] for d in decisions]
# Should have the real known issues
assert any("Hotel ID mismatch" in t for t in titles)
assert any("db.js export" in t for t in titles)
# Should NOT have Jitsi/Prosody/Nextcloud noise
assert not any("JWT_APP_SECRET" in t for t in titles)
assert not any("focus.meet.jitsi" in t for t in titles)
assert not any("conf.d files" in t for t in titles)
def test_extract_decisions_filters_noise(tmp_path):
"""Commit hashes and shell commands should not be decisions."""
(tmp_path / "CLAUDE.md").write_text("""# Project
## Known Issues
1. **Real bug** actual architectural issue that matters
- docker exec -it prosody bash
- ssh dev "cd /opt/project && git pull"
""")
decisions = extract_decisions_from_claude_md(tmp_path)
titles = [d["title"] for d in decisions]
assert any("Real bug" in t for t in titles)
# Shell commands should be filtered
assert not any("docker exec" in t for t in titles)
assert not any("ssh dev" in t for t in titles)
# ---------------------------------------------------------------------------
# Obsidian vault
# ---------------------------------------------------------------------------