Skip to content
Open
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
8 changes: 8 additions & 0 deletions AGENT_DIARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -1757,3 +1757,11 @@ BREACH: MSC-P-19 | date: 2026-10-03 | rule: §12 | guard_at_time: no | detected_
**Fix:** `_stderr_drain()` — фоновый поток с ring-buffer на 20 строк (пайп всегда вычитывается, хвост попадает в сообщение FAIL), плюс `LOG_LEVEL=WARNING` для пробы (`src/main.py:126` читает эту переменную) — сервер не заливает пайп на холодной машине. `_read_message` остался ограниченным по времени.
**Проверка:** локально 5/5 PASS, 13 s; CI run `43092017919` (head `20f287b`) — **7/7 jobs success**: `test` (ubuntu + windows), `clean-state`, `manifest-parity`, `secret-scan`, `docker-build`, `transport-equiv-e2e`.
**Урок:** дочерний процесс с `stdout/stderr=PIPE` обязан иметь читателя на каждом пайпе; «я прочитаю stderr только при ошибке» — это дедлок, который воспроизводится только там, где логов больше буфера.

## [2026-11-12] G6: doctor/clean и text-first по умолчанию — «что стоит и сколько весит»
**Симптом:** установщик предлагал ~657 МБ моделей при штатном `MSCODEBASE_DENSE_OFF=true`; команды «сколько это занимает и как убрать» не было; uninstaller существовал, но не был описан; лимиты кэшей жили в коде (`artifact_gc`, `log_manager`), а не в документации.
**Fix:** `install.py --doctor [--json]` (слои: install root / data root / проектные артефакты, размеры через `os.walk`, число чанков из `chunks.db`, пути без создания каталогов) и `install.py --clean [--dry-run] [--yes] [--json]` с guard'ами (отказ на исходный чекаут, корень ФС, домашний каталог) и ненулевым exit при остатке (заблокированные файлы работающим хостом). Модели стали opt-in: `models_enabled()` + `--with-models`; `--skip-models/--no-models` остались совместимыми.
**Замеры (реальная машина, 2026-11-12):** install root **2.7 GB / 21 372 файла**, data root **302.7 MB / 2 861 файл**, итого **3.0 GB / 24 233 файла**. `--sync-only` в пустой каталог: **871 файл / 18.7 MB за 3.1 с**.
**Автотест DoD:** `tests/test_install_cli.py::test_real_sync_install_then_doctor_then_clean_leaves_zero` — реальный `--sync-only` → `--doctor --json` (install_root.files > 100) → `--clean --yes` → `remaining_bytes == 0`, каталог удалён. Синтетический кейс отдельно проверяет dry-run (ничего не удалено), отказ без `--yes` (exit 2) и `doctor` после clean (`total_bytes == 0`).
**Найденный по ходу баг:** двойная обёртка stdout в UTF-8 (`_utf8_stdout()` в main + старый TUI-блок) закрывала буфер: `ValueError: I/O operation on closed file` на `--sync-only`. Убран дубль, оставлена одна обёртка на все режимы.
**Урок:** «очистка по слоям» без dry-run и guard'ов — это удаление чужого кэша по недопониманию; ноль остатка надо доказывать на файловой системе (`remaining_bytes == 0`), а не на числе вызванных `rmtree`.
17 changes: 13 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -231,14 +231,22 @@ MCP host: OpenCode (primary) or Zed
└── Optional embedding providers, reranker, LSP rename
```

Canonical data locations (outside the repository):
Canonical data locations (four layers; full inventory with sizes and policies in
[docs/en/DATA_MAP.md](docs/en/DATA_MAP.md)):

- `%LOCALAPPDATA%/mscodebase/projects/<hash>/` — per-project graph, memory,
- install root (`MSCODEBASE_INSTALL_ROOT`, default the historical Zed extension
directory) — the code copy, `venv/`, optional ONNX/GGUF models, uninstaller.
- `%LOCALAPPDATA%/mscodebase/projects/<hash8>/` — per-project graph, memory,
job state, commit memory, telemetry.
- `%LOCALAPPDATA%/mscodebase/logs/` — server logs.
- `%LOCALAPPDATA%/mscodebase/logs/` — server logs (2 MB × 3 rotation, 7-day retention).
- `%LOCALAPPDATA%/mscodebase/models/`, `repos/` — shared model cache and LRU(5)+24 h
repo clones.
- `<project>/.mscodebase/chunks.db` — the text chunk store used by the default
search path.

`python install.py --doctor` prints every layer with its measured size;
`python install.py --clean --dry-run` lists what `--clean` would delete.

LanceDB is part of the optional vector path and is not required by the default
text-first configuration.

Expand Down Expand Up @@ -343,7 +351,8 @@ stale/empty index, and gold-label mismatch.
| [docs/FACTS.md](docs/FACTS.md) | Every public number and the command that regenerates it |
| [docs/en/ARCHITECTURE.md](docs/en/ARCHITECTURE.md) | Layers, DI, module boundaries, tool profile |
| [docs/en/SEARCH_PIPELINE.md](docs/en/SEARCH_PIPELINE.md) | Retrieval, ranking, docs routing, investigate fan-out |
| [docs/en/INSTALL.md](docs/en/INSTALL.md) | Installation, the sync/restart loop, troubleshooting |
| [docs/en/INSTALL.md](docs/en/INSTALL.md) | Installation, the sync/restart loop, doctor/clean, troubleshooting |
| [docs/en/DATA_MAP.md](docs/en/DATA_MAP.md) | Every path the installer/server creates, with sizes and retention policies |
| [docs/en/CONFIGURATION.md](docs/en/CONFIGURATION.md) | Every environment variable and its default |
| [docs/en/CLIENTS.md](docs/en/CLIENTS.md) | OpenCode, Zed, Claude Code, VS Code, CLI, Docker |
| [docs/en/HOOKS_AND_GATES.md](docs/en/HOOKS_AND_GATES.md) | The OpenCode plugin, the 12 pre-commit gates, CI jobs |
Expand Down
2 changes: 1 addition & 1 deletion docs/en/CLIENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ Linux : ~/.local/share/zed/extensions/mscodebase-intelligence

Move it anywhere with `MSCODEBASE_INSTALL_ROOT=<path>`; caches, logs and per-project
artifacts live elsewhere (`MSCODEBASE_DATA_DIR`, default `%LOCALAPPDATA%\mscodebase`).

The full inventory is in [DATA_MAP.md](DATA_MAP.md).

Alternative without the installer (any Python package manager that exposes console
scripts):
Expand Down
111 changes: 111 additions & 0 deletions docs/en/DATA_MAP.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
# Where MSCodeBase puts data

> Written 2026-11-12 and verified against `install.py` v3.2,
> `src/core/artifact_paths.py`, `src/core/artifact_gc.py`,
> `src/core/log_manager.py`, `src/sources/git_url/__init__.py` and a live
> `install.py --doctor` run. Numbers are measured, not estimated.

One question this page answers: *what did the installer and the server create on
my disk, who owns each path, and how do I get rid of it?*

```bash
python install.py --doctor # what is installed and how much it weighs
python install.py --clean --dry-run # paths and sizes; deletes nothing
python install.py --clean --yes # delete every layer below
```

## 1. The four layers

| Layer | Path (default) | Created by | What it is |
|---|---|---|---|
| **Install root** | Windows `%LOCALAPPDATA%\Zed\extensions\mscodebase-intelligence`; macOS `~/Library/Application Support/Zed/extensions/…`; Linux `~/.local/share/zed/extensions/…` | `install.py` steps `step_copy`, `step_venv`, `step_pip`, `step_llama`, `step_gguf`, `step_models`, `step_uninst` | The installed copy: code, `venv/`, optional models, uninstaller |
| **Data root** | `%LOCALAPPDATA%\mscodebase` (Win) · `$XDG_CACHE_HOME/mscodebase` or `~/.cache/mscodebase` (POSIX) | `src/core/artifact_paths.py::get_data_root` | Per-project caches, logs, shared models, repo clones |
| **Project artifacts** | `<project>/.mscodebase/chunks.db` | server (`MSCODEBASE_SQLITE_CHUNKS`) | FTS5 text index for that project |
| **Host config** | Zed: `%APPDATA%\Zed\settings.json` (`context_servers`) | `install.py` step `step_zedcfg` → `adapters/zed/zed_config.py` | One entry telling the host how to launch the server |

Both roots are relocatable: `MSCODEBASE_INSTALL_ROOT` and `MSCODEBASE_DATA_DIR`
(`BASE_INDEX_DIR` is still accepted as a legacy alias for the second).

## 2. Install root — what is inside

| Path | Owner | Purpose | Size |
|---|---|---|---|
| `src/`, `scripts/`, `adapters/`, `locales/`, `docs/` | `step_copy` (`_sync_dir`) | Executable copy of the repository (without `experiments/`) | a few MB |
| `venv/` | `step_venv`, `step_pip` | Python environment with pinned dependencies | ~1 GB |
| `venv/Scripts/mscodebase-mcp.exe` | `pip` entry point (`pyproject.toml [project.scripts]`) | The stdio command hosts launch | — |
| `.codebase_models/onnx/…` | `step_models` (only with `--with-models`) | ONNX embedder + reranker | ~657 MB |
| `llama_msvc/` | `step_llama` | llama-server binary for the GGUF path | ~200 MB |
| `models/*.gguf` | `step_gguf` (only with `--with-models`) | GGUF embedder + reranker | ~700 MB |
| `uninstall.bat` / `uninstall.sh` | `step_uninst` (`_build_uninstaller`) | Kills the server and removes this directory | < 1 KB |
| `__mscodebase_ext__.marker` | `step_copy` | Tells `src/main.py` it runs from an installed copy | < 1 KB |

Measured on the development machine (2026-11-12, models installed):
**3.0 GB over 28 429 files**, of which `venv/` plus models make up almost all of it.

## 3. Data root — what is inside

| Path | Owner | Purpose | Policy |
|---|---|---|---|
| `projects/<hash8>/graph.db` | `artifact_paths.get_graph_db_path` | PropertyGraph: files, symbols, calls, imports | deleted with the project dir |
| `projects/<hash8>/lancedb_v2/` | `get_index_dir`, `get_db_path` | Vector index (only when dense is enabled) | same |
| `projects/<hash8>/intelligence/` | `get_intelligence_dir` | Project memory: ADRs, incidents, debt | same |
| `projects/<hash8>/metrics/` | `get_metrics_dir` | Indexing job history (ETA model) | same |
| `projects/<hash8>/commit_memory/` | `get_commit_memory_dir` | Semantic commit cache | same |
| `projects/<hash8>/branches/` | `get_branches_dir` | Per-branch index state | same |
| `projects/<hash8>/telemetry/` | `get_telemetry_dir` | Daily JSON snapshots | files older than **90 days** pruned |
| `projects/<hash8>/summaries_cache/` | `get_summaries_cache_dir` | LLM chunk summaries | same as project dir |
| `projects/<hash8>/progress.json` | `get_progress_file` | Indexing progress contract | overwritten |
| `projects/<hash8>/action_receipts.jsonl` | `src/core/action_receipt.py` | Receipts for write actions | verified 60 d / inconclusive 7 d (`purge`) |
| `logs/mscodebase-intelligence.log` | `log_manager.get_main_log_path` | Server log | rotates at 2 MB × 3 files, deleted after **7 days** |
| `logs/crash.json` | `get_crash_log_path` | Last resource-monitor crash | overwritten |
| `models/.codebase_models/onnx/…` | `get_onnx_models_base` | Shared copy of downloaded models | only `--clean` |
| `repos/<hash8>/` | `get_repos_cache_dir` | Clones of remote repositories | LRU(5) + TTL 24 h (`src/sources/git_url`) |
| `projects/<hash8>/` (whole dir) | — | — | inactive dirs older than **30 days** and empty dirs are pruned by `artifact_gc.prune_stale_artifacts()` |

Measured on the development machine (2026-11-12): **302.9 MB over 2 934 files**.
`--doctor` in a real project directory that also holds `chunks.db` (78 MB) and a
local model copy (960 MB) reported **4.3 GB over 31 385 files** across all layers.

## 4. Project artifacts

| Path | Owner | Purpose |
|---|---|---|
| `<project>/.mscodebase/chunks.db` | `MSCODEBASE_SQLITE_CHUNKS` storage | Text index (FTS5/BM25) used by the default search path; `--doctor` reports its chunk count |
| `<project>/.codebase_indices/`, `.codebase/`, `.mscodebase/telemetry/` | legacy | Moved into the data root on first project open (`artifact_paths.migrate_legacy_artifacts`) |
| `<project>/.codebase_models/` | `scripts/download_model.py` (download staging) | Temporary copy before the model is installed under the install root |

`experiments/**` is excluded from indexing by design, so it never grows the index.

## 5. Policies

- **Models are opt-in.** `install.py` is text-first: without `--with-models` it
performs no model download and writes no model directory. `--skip-models` and
`--no-models` are still accepted for old scripts.
- **Logs** rotate by size (2 MB, 3 files) and are pruned after 7 days
(`log_manager._MAX_LOG_BYTES`, `_MAX_LOG_FILES`, `_LOG_RETENTION_DAYS`).
- **Telemetry** snapshots are pruned after 90 days; **inactive project dirs**
after 30 days (`artifact_gc.DEFAULT_*`); empty project dirs are removed at once.
- **Repo clones** are an LRU of 5 with a 24 h TTL, plus a 500 MB post-clone size
cap (`git_url.DEFAULT_MAX_CLONE_BYTES`).
- **Shared model cache** (`data_root/models`) has no TTL: models are removed only
by `install.py --clean`.
- **Uninstall** is `install.py --clean --yes`, which removes all four layers
except the host config entry (delete the `mscodebase` entry from
`settings.json` / `opencode.json` / `.mcp.json` yourself, or run
`install.py --no-zed` and never create it).

## 6. Reading the doctor output

```
+ install_root 3.0 GB 28429 file(s) C:\Users\<user>\AppData\Local\Zed\extensions\mscodebase-intelligence
+ data_root 302.9 MB 2934 file(s) C:\Users\<user>\AppData\Local\mscodebase
+ project_chunks 78.0 MB 4 file(s) D:\work\repo\.mscodebase
...

index 7278 chunk(s) (D:\work\repo\.mscodebase\chunks.db)
total 4.3 GB over 31385 file(s)
```

`+` exists, `-` absent. `index missing` means the text index for the current
directory was never built (the first `codebase(action="index")` call builds it),
not that search is broken. `--json` prints the same data for scripts.
Loading
Loading