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:
parent
da4a8aae72
commit
e5444114bd
3 changed files with 344 additions and 94 deletions
|
|
@ -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
|
||||
# ---------------------------------------------------------------------------
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue