+This repository is the public release mirror for the Loctree engine.
-
- Scan once, query everything.
- AI-oriented static analysis for dead exports, circular imports, dependency graphs, and holographic context slices.
-
+It contains the `loctree` crate, the `loctree-ast` crate, and the internal report renderer required by the current engine build graph. This is a release mirror of a private integration monorepo; issues/PRs welcome here.
-
-
-
-
-
-
-
-
----
-
-## Install
-
-```bash
-curl -fsSL https://loct.io/install.sh | sh # CLI + loctree-mcp
-cargo install --locked loctree loctree-mcp # Cargo, reproducible
-npm install -g loctree # CLI only; published targets follow the latest npm release
-brew install loctree/cli/loct # CLI via Homebrew tap
-brew install loctree/mcp/loctree-mcp # MCP via Homebrew tap
-```
-
-Public install channels track the latest published release, which can lag behind
-the workspace version on `main`. If you're validating a specific release, check
-crates.io, npm, or GitHub Releases rather than assuming branch parity.
-
-## Quick Start
-
-Artifacts are stored in your OS cache dir by default (override via `LOCT_CACHE_DIR`).
-`loct` is the canonical CLI command. `loctree` remains available as a quiet compatibility alias.
-
-```bash
-loct # Scan project, write cached artifacts
-loct --for-ai # AI-optimized overview (health, hubs, quick wins)
-loct slice src/App.tsx --consumers # Context: file + deps + consumers
-loct find useAuth # Find symbol definitions
-loct find 'Snapshot FileAnalysis' # Cross-match: where terms meet
-loct impact src/utils/api.ts # What breaks if you change this?
-loct health # Quick summary: cycles + dead + twins
-loct dead --confidence high # Unused exports
-loct cycles # Circular imports
-loct twins # Dead parrots + duplicates + barrel chaos
-loct audit # Full codebase review
-```
-
-## What It Does
-
-loctree captures your project's real dependency graph in a single scan, then answers structural questions instantly from the snapshot. Designed for AI agents that need focused context without reading every file.
-
-**Core capabilities:**
-
-- **Holographic Slice** - extract file + dependencies + consumers in one call
-- **Cross-Match Search** - find where multiple terms co-occur (not flat grep)
-- **Dead Export Detection** - find unused exports across JS/TS, Python, Rust, Go, Dart
-- **Circular Import Detection** - Tarjan's SCC algorithm catches runtime bombs
-- **Handler Tracing** - follow Tauri commands through the entire FE/BE pipeline
-- **Impact Analysis** - see what breaks before you delete or refactor
-- **jq Queries** - query snapshot data with jq syntax (`loct '.files | length'`)
-
-## Why loctree
-
-| | grep/rg | LSP | loctree |
-|---|---------|-----|---------|
-| Knows imports vs definitions | No | Per-file | Whole graph |
-| Dead export detection | No | No | Yes (multi-lang) |
-| Cross-file impact analysis | No | Limited | Full transitive |
-| AI agent integration | No | No | MCP server + `--for-ai` |
-| Speed on 1M LOC repo | Fast (text) | Slow (indexing) | **~3s** (structural) |
-| Setup | None | Per-editor | One binary |
-
-## MCP Server
-
-loctree ships as an MCP server for seamless AI agent integration:
-
-```bash
-loctree-mcp # Start via stdio (configure in your MCP client)
-```
-
-7 tools: `repo-view`, `slice`, `find`, `impact`, `focus`, `tree`, `follow`. Each tool accepts a `project` parameter — auto-scans on first use, caches snapshots in RAM. Project-agnostic: analyze any repo without configuration.
-
-```json
-{
- "mcpServers": {
- "loctree": {
- "command": "loctree-mcp",
- "args": []
- }
- }
-}
-```
-
-Direct download users can also fetch signed release assets from the monorepo
-GitHub release page, which mirrors both the CLI and `loctree-mcp` tarballs.
-
-## Language Support
-
-| Language | Dead Export Accuracy | Notes |
-|----------|---------------------|-------|
-| **Rust** | ~0% FP | Tested on rust-lang/rust (35K files) |
-| **Go** | ~0% FP | Tested on golang/go (17K files) |
-| **TypeScript/JavaScript** | ~10-20% FP | JSX/TSX, React patterns, Flow, WeakMap |
-| **Python** | ~20% FP | Library mode, `__all__`, stdlib detection |
-| **Svelte** | <15% FP | Template analysis, .d.ts re-exports |
-| **Vue** | ~15% FP | SFC support, Composition & Options API |
-| **Dart/Flutter** | Full | pubspec.yaml detection |
-
-Auto-detects stack from `Cargo.toml`, `tsconfig.json`, `pyproject.toml`, `pubspec.yaml`, `src-tauri/`.
-
-## Holographic Slice
-
-Extract 3-layer context for any file:
-
-```bash
-loct slice src/App.tsx --consumers
-```
-
-```
-Slice for: src/App.tsx
-
-Core (1 files, 150 LOC):
- src/App.tsx (150 LOC, ts)
-
-Deps (3 files, 420 LOC):
- [d1] src/hooks/useAuth.ts (80 LOC)
- [d2] src/contexts/AuthContext.tsx (200 LOC)
- [d2] src/utils/api.ts (140 LOC)
-
-Consumers (2 files, 180 LOC):
- src/main.tsx (30 LOC)
- src/routes/index.tsx (150 LOC)
-
-Total: 6 files, 750 LOC
-```
-
-## Cross-Match Search
-
-Multi-term queries show where terms meet, not flat OR:
+## Build
```bash
-loct find 'Snapshot FileAnalysis'
-```
-
-```
-=== Cross-Match Files (9) ===
- src/snapshot.rs: Snapshot(6), FileAnalysis(4)
- src/slicer.rs: Snapshot(2), FileAnalysis(3)
- ...
-
-=== Symbol Matches (222 in cross-match files) ===
- src/snapshot.rs:20 - Snapshot [struct]
- src/types.rs:15 - FileAnalysis [struct]
- ...
-
-=== Parameter Matches (4 cross-matched) ===
- src/slicer.rs:45 - snapshot: &Snapshot in build_slice(analyses: &[FileAnalysis])
-```
-
-## jq Queries
-
-Query snapshot data directly:
-
-```bash
-loct '.dead_parrots' # Dead code findings
-loct '.files | length' # Count files
-loct '.edges[] | select(.from | contains("api"))' # Filter edges
-loct '.summary.health_score' # Health score
-```
-
-## CI Integration
-
-```bash
-loct lint --fail --sarif > results.sarif # SARIF for GitHub/GitLab
-loct findings | jq '.dead_exports.total' # Check dead export count
-loct findings --summary | jq '.health_score' # Health summary JSON
-```
-
-## Crates
-
-| Crate | Description |
-|-------|-------------|
-| [`loctree`](https://crates.io/crates/loctree) | Core analyzer + CLI (`loct`, `loctree`) |
-| [`report-leptos`](https://crates.io/crates/report-leptos) | HTML report renderer (Leptos SSR) |
-| [`loctree-mcp`](https://crates.io/crates/loctree-mcp) | MCP server for AI agents |
-
-## Development
-
-```bash
-make precheck # fmt + clippy + check (run before push)
-make install # Install loct, loctree, loctree-mcp
-make test # Run all workspace tests
-make publish # Cascade publish to crates.io
-```
-
-## Badge
-
-```markdown
-[](https://crates.io/crates/loctree)
+cargo check --workspace
```
## License
-MIT OR Apache-2.0. See [LICENSE-MIT](LICENSE-MIT) and [LICENSE-APACHE](LICENSE-APACHE).
+BUSL-1.1. See `LICENSE` and `NOTICE.md`.
----
+## Snapshot Notes
-𝚅𝚒𝚋𝚎𝚌𝚛𝚊𝚏𝚝𝚎𝚍. with AI Agents ⓒ 2025-2026 Loctree Team
+- Target repo: `Loctree/loctree`
+- Dependency mode: `local workspace snapshot`
+- Engine staging vendors report-leptos as an internal build dependency because loctree 0.13.0 still depends on it and the 0.13.0 crate line is not yet published.
diff --git a/SYNC-MANIFEST.md b/SYNC-MANIFEST.md
new file mode 100644
index 00000000..59c9156c
--- /dev/null
+++ b/SYNC-MANIFEST.md
@@ -0,0 +1,22 @@
+# Component Sync Manifest
+
+- Component: `engine`
+- Version: `0.13.0`
+- Target repo: `Loctree/loctree`
+- Source commit: `a5a4ee12d5c5`
+- Generated at: `2026-07-03T07:35:02Z`
+- Push mode: `enabled`
+- Dependency mode: `local workspace snapshot`
+
+## Included Payload
+
+- `loctree-rs` -> `loctree-rs`
+- `loctree-ast` -> `loctree-ast`
+
+## Vendored Build Payload
+
+- `reports` -> `reports`
+
+## Dependency Note
+
+Engine staging vendors report-leptos as an internal build dependency because loctree 0.13.0 still depends on it and the 0.13.0 crate line is not yet published.
diff --git a/ai-hooks/README.md b/ai-hooks/README.md
deleted file mode 100644
index 9bcce830..00000000
--- a/ai-hooks/README.md
+++ /dev/null
@@ -1,205 +0,0 @@
-# AI Hooks
-
-Integration hooks for AI coding assistants (Claude Code, Codex CLI, Gemini CLI).
-
-## Hook Packages
-
-### 🌳 Loctree - Structural Analysis (v10)
-**TRUE AUGMENTATION** - automatically adds semantic context to every grep/rg.
-
-| Pattern Type | Example | Augmentation | Time |
-|--------------|---------|--------------|------|
-| **Any symbol** | `passthrough` | `loct find` - semantic + params + dead status | ~75ms |
-| **PascalCase** | `McpToolsState` | `loct find` - definition + similar symbols | ~75ms |
-| **snake_case** | `detect_language` | `loct find` - all matches + params | ~75ms |
-| **Directory** | `src/providers/` | `focus` - all files + deps | ~56ms |
-| **File** | `toolRegistry.ts` | `slice` - deps + consumers tree | ~81ms |
-| **Tauri command** | `mcp_list_integrations` | Backend handler + Frontend calls | ~47ms |
-
-**Key change in v10:** Uses `loct find` (~75ms) instead of `query where-symbol` for ALL symbol lookups. This provides:
-- `symbol_matches`: Exact definitions with file + line
-- `param_matches`: Function parameters matching the pattern (NEW in 0.8.4)
-- `semantic_matches`: Similar symbols with similarity scores
-- `dead_status`: Whether the symbol is exported and/or dead
-
-**Works with:**
-- `Grep` tool → PostToolUse:Grep
-
-**Dual Output:**
-- `stderr` → User sees in terminal
-- `stdout` (JSON) → AI sees via `hookSpecificOutput.additionalContext`
-
-| Hook | Trigger | Function |
-|------|---------|----------|
-| `loct-grep-augment.sh` | PostToolUse:Grep | Auto-adds semantic context via `loct find` |
-| `loct-smart-suggest.sh` | PostToolUse:* | Proactive refactoring suggestions |
-
-### 🧠 Memex - Memory/RAG Augmentation
-
-**INSTITUTIONAL KNOWLEDGE** - automatically loads relevant memories from your vector DB.
-
-| Hook | Trigger | Function | Time |
-|------|---------|----------|------|
-| `memex-startup.sh` | SessionStart | Load project-specific memories | ~50ms |
-| `memex-context.sh` | PostToolUse:Grep | Augment grep with relevant memories | ~50ms |
-| `memory-on-compact.sh` | PreCompact | Save session context before compaction | ~50ms |
-
-**Requires:**
-- `rmcp-memex` server running: `rmcp-memex serve --http-port 8987`
-- Indexed memories (use `rmcp-memex index ` or MCP tools)
-
-**Environment Variables:**
-- `MEMEX_URL` - Server URL (default: `http://localhost:8987`)
-- `MEMEX_LIMIT` - Max results per query (default: `3`)
-- `MEMEX_TIMEOUT` - Request timeout in seconds (default: `3`)
-
-## Installation
-
-### Interactive (Recommended)
-```bash
-cd loctree-suite
-make ai-hooks
-```
-
-You'll be prompted to choose which CLIs to configure (Claude Code, Codex CLI, etc.)
-
-### Non-Interactive
-```bash
-# Install hooks for Claude Code
-make ai-hooks CLI=claude
-
-# Install hooks for all supported CLIs
-make ai-hooks CLI=all
-```
-
-## Requirements
-
-### Loctree hooks
-- `loct` CLI installed (`make install` in loctree-suite)
-- `jq` for JSON parsing
-
-### Memex hooks (optional)
-- `rmcp-memex` CLI installed (`cargo install rmcp-memex`)
-- Memex server running (`rmcp-memex serve --http-port 8987`)
-- `curl` and `jq` for HTTP API calls
-
-The installer will offer to install missing dependencies.
-
-## Manual Configuration
-
-If automatic settings.json update fails, add hooks manually:
-
-### Claude Code (~/.claude/settings.json)
-```json
-{
- "hooks": {
- "PostToolUse": [
- {
- "matcher": "Grep",
- "hooks": [
- {"type": "command", "command": "~/.claude/hooks/loct-grep-augment.sh"}
- ]
- }
- ]
- }
-}
-```
-
-## Environment Variables
-
-### Loctree
-- `LOCT_AUGMENT=0` - Disable loctree augmentation
-- `LOCT_MAX_LINES=40` - Max output lines
-- `LOCT_TIMEOUT=15` - Command timeout (seconds)
-
-## Loctree Command Reference
-
-### ⚡ FAST Commands (<100ms)
-
-| Command | Description | Time |
-|---------|-------------|------|
-| `loct find ` | Semantic + params + dead status | ~75ms |
-| `loct slice ` | File + deps + consumers | ~81ms |
-| `loct impact ` | What breaks if file changes | ~49ms |
-| `loct query who-imports ` | Files importing target | ~53ms |
-| `loct query where-symbol ` | Where symbol is defined (exact) | ~75ms |
-| `loct focus ` | All files in directory + deps | ~56ms |
-| `loct commands` | Tauri command bridges | ~47ms |
-| `loct health` | Quick health summary | ~372ms |
-
-> **All commands support `--json` output!**
-
-### 🔍 Analysis Commands
-
-| Command | Description |
-|---------|-------------|
-| `loct dead` | Unused exports (dead code) |
-| `loct cycles` | Circular imports |
-| `loct twins` | Duplicate symbol names |
-| `loct zombie` | Dead + orphan + shadows |
-| `loct routes` | FastAPI/Flask routes |
-
-### 🔤 Single-Letter Aliases
-
-| Alias | Command |
-|-------|---------|
-| `loct s` | slice |
-| `loct f` | find |
-| `loct i` | impact |
-| `loct h` | health |
-| `loct q` | query |
-
-## How It Works
-
-```
-┌─────────────────────────────────────────────────────────────┐
-│ Claude: Grep "detect_language" (ripgrep ~10ms) │
-│ │ │
-│ ▼ │
-│ PostToolUse:Grep hook fires │
-│ │ │
-│ ▼ │
-│ ┌────────────────┐ │
-│ │ loct-grep │ │
-│ │ augment.sh v10 │ │
-│ │ (~75ms) │ │
-│ └────────────────┘ │
-│ │ │
-│ ▼ │
-│ ┌─────────────────────────────────────────────────┐ │
-│ │ 🌳 LOCTREE CONTEXT │ │
-│ │ Symbol: classify.rs:27, twins.rs:500 │ │
-│ │ Semantic: detect_stack (0.53), detect_crowd... │ │
-│ │ Dead: exported=true, dead=false │ │
-│ └─────────────────────────────────────────────────┘ │
-│ │
-│ USER sees: stderr output in terminal │
-│ AI sees: system-reminder with full JSON context │
-└─────────────────────────────────────────────────────────────┘
-```
-
-## What's New in v10
-
-1. **`loct find` is now FAST** (~75ms vs ~14500ms in older versions)
-2. **Catch-all pattern matching** - any alphanumeric pattern ≥3 chars triggers augmentation
-3. **Parameter matching** - finds function parameters, not just exports
-4. **Semantic matching** - typo recovery, similar symbol suggestions
-5. **Dead code status** - instant feedback on whether symbol is used
-
-## Troubleshooting
-
-### Hooks not running
-1. Check settings.json syntax: `jq . ~/.claude/settings.json`
-2. Verify hook is executable: `ls -la ~/.claude/hooks/`
-3. Restart AI CLI
-
-### Loctree not finding anything
-1. Run initial scan: `loct scan` in project root
-2. Check snapshot: `loct '.metadata'` (artifacts are cached by default; set `LOCT_CACHE_DIR=.loctree` for repo-local artifacts)
-
-### No augmentation for a pattern
-- Pattern must be ≥3 chars and alphanumeric
-- `loct find` must return matches (check with `loct find --json`)
-
----
-𝚅𝚒𝚋𝚎𝚌𝚛𝚊𝚏𝚝𝚎𝚍. with AI Agents ⓒ 2025-2026 Loctree Team
diff --git a/ai-hooks/example-settings.json b/ai-hooks/example-settings.json
deleted file mode 100644
index 497a3f76..00000000
--- a/ai-hooks/example-settings.json
+++ /dev/null
@@ -1,15 +0,0 @@
-{
- "hooks": {
- "PostToolUse": [
- {
- "matcher": "Grep",
- "hooks": [
- {
- "type": "command",
- "command": "~/.claude/hooks/loct-grep-augment.sh"
- }
- ]
- }
- ]
- }
-}
diff --git a/ai-hooks/loct-grep-augment.sh b/ai-hooks/loct-grep-augment.sh
deleted file mode 100755
index f96c8d9f..00000000
--- a/ai-hooks/loct-grep-augment.sh
+++ /dev/null
@@ -1,443 +0,0 @@
-#!/bin/bash
-# ============================================================================
-# loct-grep-augment.sh v10 - SEMANTIC AUGMENTATION WITH loct find
-# ============================================================================
-# Created by M&K ⓒ 2025-2026 The Loctree Team
-#
-# PHILOSOPHY: Every grep gets loctree context. Always <100ms.
-#
-# BENCHMARK (loctree 0.8.4 - UPDATED 2026-01):
-# loct find ~75ms ✅ (semantic + params + dead status)
-# loct commands ~47ms ✅
-# loct impact ~49ms ✅
-# loct query who-imports ~53ms ✅
-# loct focus ~56ms ✅
-# loct slice ~81ms ✅
-# loct health ~372ms ⚠️ (only for health queries)
-#
-# KEY CHANGE v10: loct find is now FAST! Use it for all symbol lookups.
-# ============================================================================
-
-set -uo pipefail
-export PATH="$HOME/.cargo/bin:/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:$PATH"
-
-# Quick exit if dependencies unavailable
-command -v loct >/dev/null 2>&1 || exit 0
-command -v jq >/dev/null 2>&1 || exit 0
-
-# ============================================================================
-# OPTIONAL LOGGING (default OFF - set LOCT_HOOK_LOG_FILE to enable)
-# ============================================================================
-# Only logs metadata (pattern truncated, timing, action) - never tool_response!
-# Enable: export LOCT_HOOK_LOG_FILE="$HOME/.claude/logs/loct-grep.log"
-
-LOG_FILE="${LOCT_HOOK_LOG_FILE:-}"
-LOG_START_MS=
-
-log_meta() {
- [[ -z "$LOG_FILE" ]] && return 0
- mkdir -p "$(dirname "$LOG_FILE")" 2>/dev/null || true
- printf '%s\n' "$*" >> "$LOG_FILE" 2>/dev/null || true
-}
-
-log_start() {
- [[ -z "$LOG_FILE" ]] && return 0
- LOG_START_MS=$(($(date +%s%N 2>/dev/null || echo "$(date +%s)000000000") / 1000000))
- log_meta ""
- log_meta "==== LOCT HOOK: $(date '+%Y-%m-%d %H:%M:%S') ===="
-}
-
-log_end() {
- [[ -z "$LOG_FILE" ]] && return 0
- local action="${1:-unknown}"
- local pattern_short="${PATTERN:-?}"
- [[ ${#pattern_short} -gt 40 ]] && pattern_short="${pattern_short:0:37}..."
-
- local end_ms=$(($(date +%s%N 2>/dev/null || echo "$(date +%s)000000000") / 1000000))
- local duration_ms=$((end_ms - LOG_START_MS))
-
- log_meta "pattern: $pattern_short"
- log_meta "path: ${PATH_ARG:-.}"
- log_meta "action: $action"
- log_meta "time: ${duration_ms}ms"
- log_meta "----"
-}
-
-# Start timing (if logging enabled)
-log_start
-
-# Read hook input
-HOOK_INPUT=$(cat)
-[[ -z "$HOOK_INPUT" ]] && exit 0
-
-# ============================================================================
-# PATTERN EXTRACTION
-# ============================================================================
-
-if [[ "${1:-}" == "--bash-filter" ]]; then
- # Bash tool with rg/grep command
- COMMAND=$(echo "$HOOK_INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
- echo "$COMMAND" | grep -qE '(^|[[:space:]])(rg|ripgrep|grep)[[:space:]]' || exit 0
-
- # Extract quoted pattern first, then unquoted
- PATTERN=$(echo "$COMMAND" | grep -oE '"[^"]+"' | head -1 | tr -d '"')
- [[ -z "$PATTERN" ]] && PATTERN=$(echo "$COMMAND" | grep -oE "'[^']+'" | head -1 | tr -d "'")
- [[ -z "$PATTERN" ]] && PATTERN=$(echo "$COMMAND" | sed -nE 's/.*\b(rg|grep)\b[[:space:]]+([^[:space:]-][^[:space:]]*).*/\2/p')
-
- # Extract path (last arg if looks like path)
- PATH_ARG=$(echo "$COMMAND" | awk '{print $NF}')
- [[ ! "$PATH_ARG" =~ ^\.?/ ]] && [[ ! -e "$PATH_ARG" ]] && PATH_ARG="."
-else
- # Native Grep tool
- PATTERN=$(echo "$HOOK_INPUT" | jq -r '.tool_input.pattern // empty' 2>/dev/null)
- PATH_ARG=$(echo "$HOOK_INPUT" | jq -r '.tool_input.path // "."' 2>/dev/null)
-fi
-
-# Change to appropriate directory for loctree context
-# Priority: tool_input.path (if absolute) > session_cwd > current dir
-if [[ "$PATH_ARG" == /* ]] && [[ -d "$PATH_ARG" ]]; then
- # Absolute directory path - use it directly
- cd "$PATH_ARG"
-elif [[ "$PATH_ARG" == /* ]] && [[ -f "$PATH_ARG" ]]; then
- # Absolute file path - use its parent directory
- cd "$(dirname "$PATH_ARG")"
-else
- # Fall back to session_cwd
- SESSION_CWD=$(echo "$HOOK_INPUT" | jq -r '.session_cwd // empty' 2>/dev/null)
- [[ -n "$SESSION_CWD" ]] && [[ -d "$SESSION_CWD" ]] && cd "$SESSION_CWD"
-fi
-
-# Find repo root (prefer git root; fall back to current dir).
-# We no longer require a project-local `.loctree/` for cached artifacts.
-REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || true)
-if [[ -n "$REPO_ROOT" ]] && [[ -d "$REPO_ROOT" ]]; then
- cd "$REPO_ROOT"
-else
- REPO_ROOT=$(pwd)
-fi
-
-# Validation
-[[ -z "$PATTERN" ]] && exit 0
-[[ ${#PATTERN} -lt 3 ]] && exit 0
-# Skip heavy regex patterns
-echo "$PATTERN" | grep -qE '[\|\*\+\?\[\]\(\)\{\}\\]{3,}' && exit 0
-
-# Clean quotes
-PATTERN="${PATTERN%\"}"
-PATTERN="${PATTERN#\"}"
-PATTERN="${PATTERN%\'}"
-PATTERN="${PATTERN#\'}"
-
-# ============================================================================
-# OUTPUT HELPER
-# ============================================================================
-
-# Max payload size (32KB) to avoid bloating additionalContext
-MAX_PAYLOAD_BYTES=32768
-
-truncate_payload() {
- local text="$1"
- local max="$2"
- if [[ ${#text} -gt $max ]]; then
- printf '%s\n\n[...truncated, showing first %d bytes of %d total]' \
- "${text:0:$max}" "$max" "${#text}"
- else
- printf '%s' "$text"
- fi
-}
-
-output_json() {
- local header="$1"
- local json_content="$2"
-
- # Log metadata (if enabled) - uses header as action name
- log_end "$header"
-
- local msg="
-━━━ 🌳 LOCTREE: $header ━━━
-$json_content"
-
- # Truncate if too large (prevents client issues)
- msg="$(truncate_payload "$msg" "$MAX_PAYLOAD_BYTES")"
-
- # Human-readable for Maciej (stderr)
- echo "$msg" >&2
-
- # JSON for Claude Code (stdout - CC parses hookSpecificOutput)
- local escaped
- escaped=$(echo "$msg" | jq -Rs .)
- local output
- output=$(cat << EOF
-{
- "hookSpecificOutput": {
- "hookEventName": "PostToolUse",
- "additionalContext": $escaped
- }
-}
-EOF
-)
- # Output to stdout
- echo "$output"
-
- # Save to cache (if cache key is set)
- [[ -n "${CACHE_KEY:-}" ]] && echo "$output" > "$CACHE_KEY" 2>/dev/null
-}
-
-# ============================================================================
-# RESPONSE CACHE (dedup - same query within TTL returns cached response)
-# ============================================================================
-
-CACHE_DIR="/tmp/.loct-grep-cache"
-CACHE_TTL=60 # seconds
-
-# Compute cache key from: repo_root + git_commit + pattern + path
-compute_cache_key() {
- local repo="$1"
- local pattern="$2"
- local path="$3"
-
- # Get current git commit (short hash) or "nocommit"
- local commit
- commit=$(git -C "$repo" rev-parse --short HEAD 2>/dev/null || echo "nocommit")
-
- # Create cache dir if needed
- mkdir -p "$CACHE_DIR" 2>/dev/null || true
-
- # MD5 hash of key components
- local hash
- hash=$(printf '%s:%s:%s:%s' "$repo" "$commit" "$pattern" "$path" | md5 2>/dev/null || md5sum | cut -c1-32)
-
- echo "${CACHE_DIR}/${hash}.json"
-}
-
-# Check cache - returns 0 and outputs cached response if hit, 1 if miss
-check_cache() {
- local cache_file="$1"
-
- [[ ! -f "$cache_file" ]] && return 1
-
- # Check age
- local cache_age
- if stat -f%m "$cache_file" &>/dev/null; then
- cache_age=$(($(date +%s) - $(stat -f%m "$cache_file")))
- else
- cache_age=$(($(date +%s) - $(stat -c%Y "$cache_file")))
- fi
-
- if [[ $cache_age -lt $CACHE_TTL ]]; then
- # Cache hit - output cached response
- cat "$cache_file"
- # Debug to log only (not stderr - would pollute UI)
- log_meta "[cache] hit (${cache_age}s old)"
- return 0
- fi
-
- # Cache expired
- rm -f "$cache_file" 2>/dev/null
- return 1
-}
-
-# ============================================================================
-# FAST AUGMENTATION FUNCTIONS (<100ms each!)
-# ============================================================================
-
-# Symbol lookup via loct find (FAST in 0.8.4: ~75ms with semantic matches!)
-augment_symbol() {
- local symbol="$1"
- local result
-
- # loct find gives: symbol_matches + param_matches + semantic_matches + dead_status
- result=$(loct find "$symbol" --json 2>/dev/null)
- [[ -z "$result" ]] && return 1
-
- # Check if ANY matches found (symbol, param, or semantic)
- local has_matches
- has_matches=$(echo "$result" | jq '
- (.symbol_matches.total_matches // 0) > 0 or
- (.param_matches | length) > 0 or
- (.semantic_matches | length) > 0
- ' 2>/dev/null)
- [[ "$has_matches" != "true" ]] && return 1
-
- output_json "find $symbol" "$result"
- exit 0
-}
-
-# File context via slice
-augment_file() {
- local file="$1"
- [[ ! -f "$file" ]] && return 1
-
- local result
- result=$(loct slice "$file" --json 2>/dev/null)
- [[ -z "$result" ]] && return 1
-
- output_json "slice $file" "$result"
- exit 0
-}
-
-# File impact analysis
-augment_impact() {
- local file="$1"
- [[ ! -f "$file" ]] && return 1
-
- local result
- result=$(loct impact "$file" --json 2>/dev/null)
- [[ -z "$result" ]] && return 1
-
- output_json "impact $file" "$result"
- exit 0
-}
-
-# Who imports this file
-augment_who_imports() {
- local file="$1"
- [[ ! -f "$file" ]] && return 1
-
- local result
- result=$(loct query who-imports "$file" --json 2>/dev/null)
- [[ -z "$result" ]] && return 1
-
- output_json "who-imports $file" "$result"
- exit 0
-}
-
-# Directory overview via focus
-augment_directory() {
- local dir="$1"
- [[ ! -d "$dir" ]] && return 1
-
- local result
- result=$(loct focus "$dir" --json 2>/dev/null)
- [[ -z "$result" ]] && return 1
-
- output_json "focus $dir" "$result"
- exit 0
-}
-
-# Tauri command bridge
-augment_tauri_command() {
- local cmd="$1"
-
- local result
- result=$(loct commands --json 2>/dev/null | jq --arg cmd "$cmd" '[.[] | select(.name | contains($cmd))]' 2>/dev/null)
- [[ -z "$result" ]] || [[ "$result" == "[]" ]] && return 1
-
- output_json "commands matching $cmd" "$result"
- exit 0
-}
-
-# Health check (only for health-related queries, ~372ms)
-augment_health() {
- local result
- result=$(loct health --json 2>/dev/null)
- [[ -z "$result" ]] && return 1
-
- output_json "health" "$result"
- exit 0
-}
-
-# ============================================================================
-# CACHE CHECK - Return cached response if available (dedup)
-# ============================================================================
-
-CACHE_KEY=$(compute_cache_key "$REPO_ROOT" "$PATTERN" "$PATH_ARG")
-if check_cache "$CACHE_KEY"; then
- log_end "cache-hit"
- exit 0
-fi
-
-# ============================================================================
-# SMART ROUTING - Pattern → Best Augmentation
-# ============================================================================
-
-# Priority 1: Exact file path → slice + who-imports
-if [[ -f "$PATTERN" ]]; then
- augment_file "$PATTERN"
-fi
-
-# Priority 2: Path argument is specific file → impact analysis
-if [[ "$PATH_ARG" != "." ]] && [[ -f "$PATH_ARG" ]]; then
- augment_impact "$PATH_ARG"
-fi
-
-# Priority 3: Directory path → focus
-if [[ -d "$PATTERN" ]] || [[ "$PATTERN" == */ ]]; then
- augment_directory "${PATTERN%/}"
-fi
-if [[ "$PATH_ARG" != "." ]] && [[ -d "$PATH_ARG" ]]; then
- augment_directory "$PATH_ARG"
-fi
-
-# Priority 4: Tauri snake_case commands (mcp_list_integrations, etc.)
-if echo "$PATTERN" | grep -qE '^[a-z][a-z0-9]*(_[a-z0-9]+)+$'; then
- augment_tauri_command "$PATTERN"
-fi
-
-# Priority 5: File-like pattern (has extension) → find file, then slice
-if echo "$PATTERN" | grep -qE '\.(ts|tsx|rs|js|jsx|py|vue|svelte|css|scss)$'; then
- FOUND=$(find . -path "./.git" -prune -o -name "$PATTERN" -type f -print 2>/dev/null | head -1)
- [[ -n "$FOUND" ]] && augment_file "$FOUND"
-fi
-
-# Priority 6: Symbol patterns → FAST query where-symbol
-# PascalCase: Components, Types, Interfaces (ChatPanel, PatientRecord)
-if echo "$PATTERN" | grep -qE '^[A-Z][a-zA-Z0-9]{2,}$'; then
- augment_symbol "$PATTERN"
-fi
-
-# camelCase with uppercase: hooks, handlers (useVistaAgent, handleClick)
-if echo "$PATTERN" | grep -qE '^[a-z]+[A-Z][a-zA-Z0-9]*$'; then
- augment_symbol "$PATTERN"
-fi
-
-# React hooks: useXxx
-if echo "$PATTERN" | grep -qE '^use[A-Z][a-zA-Z0-9]+$'; then
- augment_symbol "$PATTERN"
-fi
-
-# Event handlers: handleXxx, onXxx
-if echo "$PATTERN" | grep -qE '^(handle|on)[A-Z][a-zA-Z0-9]+$'; then
- augment_symbol "$PATTERN"
-fi
-
-# snake_case identifiers (Rust, Python)
-if echo "$PATTERN" | grep -qE '^[a-z][a-z0-9]*_[a-z_0-9]+$'; then
- augment_symbol "$PATTERN"
-fi
-
-# Boolean prefixes: isActive, hasPermission, canEdit
-if echo "$PATTERN" | grep -qE '^(is|has|can|should|will)[A-Z][a-zA-Z0-9]*$'; then
- augment_symbol "$PATTERN"
-fi
-
-# SCREAMING_CASE constants
-if echo "$PATTERN" | grep -qE '^[A-Z][A-Z0-9_]+$'; then
- augment_symbol "$PATTERN"
-fi
-
-# Priority 7: Path-like patterns → try to resolve
-if [[ "$PATTERN" == *"/"* ]]; then
- # Try as file
- FOUND=$(find . -path "./.git" -prune -o -path "*$PATTERN*" -type f -print 2>/dev/null | head -1)
- [[ -n "$FOUND" ]] && augment_file "$FOUND"
-
- # Try as directory
- FOUND_DIR=$(find . -path "./.git" -prune -o -path "*$PATTERN*" -type d -print 2>/dev/null | head -1)
- [[ -n "$FOUND_DIR" ]] && augment_directory "$FOUND_DIR"
-fi
-
-# Priority 8: Health-related keywords (only case where we use slower command)
-if echo "$PATTERN" | grep -qiE 'dead|unused|orphan|stale|deprecated|circular|cycle|duplicate|twin'; then
- augment_health
-fi
-
-# Priority 9: CATCH-ALL - Any alphanumeric pattern ≥3 chars → try loct find
-# This catches patterns like "passthrough", "handler", "template" that fell through
-if echo "$PATTERN" | grep -qE '^[a-zA-Z_][a-zA-Z0-9_]{2,}$'; then
- augment_symbol "$PATTERN"
-fi
-
-# No augmentation needed for pure text/regex searches
-log_end "no-match"
-exit 0
diff --git a/ai-hooks/loct-smart-suggest.sh b/ai-hooks/loct-smart-suggest.sh
deleted file mode 100755
index 7516f915..00000000
--- a/ai-hooks/loct-smart-suggest.sh
+++ /dev/null
@@ -1,121 +0,0 @@
-#!/bin/bash
-export PATH="$HOME/.cargo/bin:/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:$PATH"
-
-# Quick exit if jq unavailable (has grep fallback but jq preferred)
-command -v jq >/dev/null 2>&1 || exit 0
-
-# ============================================================================
-# loct-smart-suggest.sh - Context-aware loct suggestions for Claude Code
-# ============================================================================
-#
-# ALTERNATIVE APPROACH: PreToolUse hook that SUGGESTS loct commands
-# instead of automatically augmenting. Use this if you prefer manual control.
-#
-# Non-blocking! Just adds helpful hints to stderr when loct would be better.
-#
-# INSTALLATION:
-# 1. Copy to ~/.claude/hooks/loct-smart-suggest.sh
-# 2. chmod +x ~/.claude/hooks/loct-smart-suggest.sh
-# 3. Add to ~/.claude/settings.json under PreToolUse (not PostToolUse)
-#
-# ============================================================================
-
-INPUT=$(cat)
-
-# Extract pattern from JSON
-PATTERN=$(echo "$INPUT" | jq -r '.pattern // .tool_input.pattern // empty' 2>/dev/null)
-if [[ -z "$PATTERN" ]]; then
- PATTERN=$(echo "$INPUT" | grep -oP '"pattern"\s*:\s*"\K[^"]+' 2>/dev/null || echo "")
-fi
-
-[[ -z "$PATTERN" ]] && exit 0
-
-# Track suggestions to avoid spam (max 3 per session)
-SUGGEST_COUNT_FILE="/tmp/.loct-suggest-count-$(date +%Y%m%d)"
-SUGGEST_COUNT=$(cat "$SUGGEST_COUNT_FILE" 2>/dev/null || echo "0")
-[[ "$SUGGEST_COUNT" -ge 3 ]] && exit 0
-
-suggest() {
- local hint="$1"
- local cmd="$2"
- echo "" >&2
- echo "┌─────────────────────────────────────────────────────────────" >&2
- echo "│ 🌳 $hint" >&2
- echo "│ → $cmd" >&2
- echo "└─────────────────────────────────────────────────────────────" >&2
- echo "" >&2
- echo $((SUGGEST_COUNT + 1)) > "$SUGGEST_COUNT_FILE"
-}
-
-# Case 1: React Component or Type (PascalCase)
-if [[ "$PATTERN" =~ ^[A-Z][a-zA-Z0-9]{2,}$ ]]; then
- suggest "Symbol search? loct finds definition + all usages" \
- "loct f $PATTERN"
- exit 0
-fi
-
-# Case 2: React Hook (useXxx)
-if [[ "$PATTERN" =~ ^use[A-Z][a-zA-Z0-9]+$ ]]; then
- suggest "Hook search? loct shows definition + import chain" \
- "loct f $PATTERN"
- exit 0
-fi
-
-# Case 3: Event Handler (handleXxx, onXxx)
-if [[ "$PATTERN" =~ ^(handle|on)[A-Z][a-zA-Z0-9]+$ ]]; then
- suggest "Handler search? loct finds definition + prop passing" \
- "loct f $PATTERN"
- exit 0
-fi
-
-# Case 4: Tauri command patterns
-if [[ "$PATTERN" =~ invoke|safeInvoke|emit\( ]]; then
- suggest "Tauri bridge? loct trace shows FE↔BE coverage" \
- "loct trace "
- exit 0
-fi
-
-# Case 5: Import/export analysis
-if [[ "$PATTERN" =~ ^import|^export|from.+import ]]; then
- suggest "Import analysis? loct has full dependency graph" \
- "loct q who-imports "
- exit 0
-fi
-
-# Case 6: Snake_case symbol (Rust/Python)
-if [[ "$PATTERN" =~ ^[a-z][a-z0-9]*_[a-z_0-9]+$ ]]; then
- suggest "Symbol search? loct finds across TS+Rust with context" \
- "loct f $PATTERN"
- exit 0
-fi
-
-# Case 7: Checking if something exists/is used
-if [[ "$PATTERN" =~ ^(is|has|can|should)[A-Z] ]]; then
- suggest "Checking usage? loct can tell if it's dead code" \
- "loct f $PATTERN"
- exit 0
-fi
-
-# Case 8: Dead/unused patterns
-if [[ "$PATTERN" =~ dead|unused|orphan|stale ]]; then
- suggest "Dead code hunt? loct has pre-indexed findings" \
- "loct health"
- exit 0
-fi
-
-# Case 9: Circular/cycle patterns
-if [[ "$PATTERN" =~ circular|cycle|loop|recursive ]]; then
- suggest "Cycle detection? loct has SCC analysis ready" \
- "loct health"
- exit 0
-fi
-
-# Case 10: Duplicate/twin patterns
-if [[ "$PATTERN" =~ duplicate|twin|copy|similar ]]; then
- suggest "Finding duplicates? loct detected exact twins" \
- "loct health"
- exit 0
-fi
-
-# No match - grep is fine
-exit 0
diff --git a/ai-hooks/memex-context.sh b/ai-hooks/memex-context.sh
deleted file mode 100755
index 226a28d2..00000000
--- a/ai-hooks/memex-context.sh
+++ /dev/null
@@ -1,80 +0,0 @@
-#!/bin/bash
-# ============================================================================
-# memex-context.sh - Project context loader via HTTP API
-# ============================================================================
-# Created by M&K ⓒ 2025-2026 VetCoders
-#
-# TRIGGER: PostToolUse (Grep, Read)
-# PURPOSE: Augment tool results with relevant memories from memex
-#
-# REQUIRES: rmcp-memex server running (rmcp-memex serve --http-port 8987)
-# BENCHMARK: ~50ms (HTTP API)
-# ============================================================================
-
-set -uo pipefail
-export PATH="$HOME/.cargo/bin:/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:$PATH"
-
-# Configuration
-MEMEX_URL="${MEMEX_URL:-http://localhost:8987}"
-MEMEX_LIMIT="${MEMEX_LIMIT:-3}"
-MEMEX_TIMEOUT="${MEMEX_TIMEOUT:-2}"
-
-# Quick exits
-command -v curl &>/dev/null || exit 0
-command -v jq &>/dev/null || exit 0
-
-# Read hook input
-HOOK_INPUT=$(cat)
-[[ -z "$HOOK_INPUT" ]] && exit 0
-
-# Extract pattern from Grep tool
-PATTERN=$(echo "$HOOK_INPUT" | jq -r '.tool_input.pattern // empty' 2>/dev/null)
-[[ -z "$PATTERN" ]] && exit 0
-[[ ${#PATTERN} -lt 3 ]] && exit 0
-
-# Skip heavy regex patterns
-echo "$PATTERN" | grep -qE '[\|\*\+\?\[\]\(\)\{\}\\]{3,}' && exit 0
-
-# Check if server is up
-if ! curl -s --max-time 1 "$MEMEX_URL/health" >/dev/null 2>&1; then
- exit 0
-fi
-
-# Search memex
-SEARCH_RESULT=$(curl -s --max-time "$MEMEX_TIMEOUT" \
- "$MEMEX_URL/cross-search?q=$(echo "$PATTERN" | jq -sRr @uri)&limit=$MEMEX_LIMIT" \
- 2>/dev/null)
-
-[[ -z "$SEARCH_RESULT" ]] && exit 0
-
-# Check if we got results
-RESULT_COUNT=$(echo "$SEARCH_RESULT" | jq -r '.total_results // 0' 2>/dev/null)
-[[ "$RESULT_COUNT" == "0" ]] && exit 0
-
-# Format output
-MEMORIES=$(echo "$SEARCH_RESULT" | jq -r '
- .results[:3] |
- to_entries |
- map("[\(.value.namespace)] \(.value.text | .[0:200] | gsub("\n"; " "))")[]
-' 2>/dev/null)
-
-[[ -z "$MEMORIES" ]] && exit 0
-
-CONTEXT="
---- MEMEX: $RESULT_COUNT memories for '$PATTERN' ---
-$MEMORIES"
-
-# Human-readable (stderr)
-echo "$CONTEXT" >&2
-
-# JSON for Claude Code (stdout)
-ESCAPED=$(echo "$CONTEXT" | jq -Rs .)
-cat << EOF
-{
- "hookSpecificOutput": {
- "hookEventName": "PostToolUse",
- "additionalContext": $ESCAPED
- }
-}
-EOF
-exit 0
diff --git a/ai-hooks/memex-startup.sh b/ai-hooks/memex-startup.sh
deleted file mode 100755
index 5e3d7a2c..00000000
--- a/ai-hooks/memex-startup.sh
+++ /dev/null
@@ -1,106 +0,0 @@
-#!/bin/bash
-# ============================================================================
-# memex-startup.sh - Project context loader at session start
-# ============================================================================
-# Created by M&K ⓒ 2025-2026 VetCoders
-#
-# TRIGGER: SessionStart hook
-# PURPOSE: Load institutional knowledge about the current project from memex
-#
-# REQUIRES: rmcp-memex server running (rmcp-memex serve --http-port 8987)
-# BENCHMARK: ~50ms (HTTP API with 1h caching)
-# ============================================================================
-
-set -uo pipefail
-export PATH="$HOME/.cargo/bin:/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:$PATH"
-
-# Configuration
-MEMEX_URL="${MEMEX_URL:-http://localhost:8987}"
-MEMEX_LIMIT="${MEMEX_LIMIT:-3}"
-MEMEX_TIMEOUT="${MEMEX_TIMEOUT:-3}"
-CACHE_TTL=3600 # 1 hour
-
-# Quick exits
-command -v curl &>/dev/null || exit 0
-command -v jq &>/dev/null || exit 0
-
-# Find repo root (git root or .loctree parent)
-REPO_ROOT=$(pwd)
-GIT_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || true)
-if [[ -n "$GIT_ROOT" ]]; then
- REPO_ROOT="$GIT_ROOT"
-else
- # Fallback: find .loctree directory
- while [[ "$REPO_ROOT" != "/" ]] && [[ ! -d "$REPO_ROOT/.loctree" ]]; do
- REPO_ROOT=$(dirname "$REPO_ROOT")
- done
- [[ ! -d "$REPO_ROOT/.loctree" ]] && REPO_ROOT=$(pwd)
-fi
-
-# Cache uses repo root (not PWD) to avoid subfolder confusion
-CACHE_FILE="/tmp/memex-startup-$(echo "$REPO_ROOT" | md5 2>/dev/null || md5sum <<< "$REPO_ROOT" | cut -c1-8).cache"
-
-# Cache check - only load once per project per hour
-if [[ -f "$CACHE_FILE" ]]; then
- if stat -f%m "$CACHE_FILE" &>/dev/null; then
- CACHE_AGE=$(($(date +%s) - $(stat -f%m "$CACHE_FILE")))
- else
- CACHE_AGE=$(($(date +%s) - $(stat -c%Y "$CACHE_FILE")))
- fi
- if [[ $CACHE_AGE -lt $CACHE_TTL ]]; then
- exit 0
- fi
-fi
-
-# Check if server is up
-if ! curl -s --max-time 1 "$MEMEX_URL/health" >/dev/null 2>&1; then
- touch "$CACHE_FILE"
- exit 0
-fi
-
-# Project detection (use already-resolved REPO_ROOT)
-PROJECT_NAME=$(basename "$REPO_ROOT")
-PROJECT_QUERY=$(echo "$PROJECT_NAME" | tr '-_' ' ')
-
-# Search memex
-SEARCH_RESULT=$(curl -s --max-time "$MEMEX_TIMEOUT" \
- "$MEMEX_URL/cross-search?q=$(echo "$PROJECT_QUERY" | jq -sRr @uri)&limit=$MEMEX_LIMIT&total_limit=$((MEMEX_LIMIT * 2))" \
- 2>/dev/null)
-
-touch "$CACHE_FILE"
-
-[[ -z "$SEARCH_RESULT" ]] && exit 0
-
-# Check if we got results
-RESULT_COUNT=$(echo "$SEARCH_RESULT" | jq -r '.total_results // 0' 2>/dev/null)
-[[ "$RESULT_COUNT" == "0" ]] && exit 0
-
-# Format output
-MEMORIES=$(echo "$SEARCH_RESULT" | jq -r '
- .results[:3] |
- to_entries |
- map("[\(.value.namespace)] \(.value.text | .[0:300] | gsub("\n"; " "))")[]
-' 2>/dev/null)
-
-[[ -z "$MEMORIES" ]] && exit 0
-
-NS_SEARCHED=$(echo "$SEARCH_RESULT" | jq -r '.namespaces_searched // 0' 2>/dev/null)
-
-CONTEXT="
---- MEMEX: $PROJECT_NAME (searched $NS_SEARCHED namespaces) ---
-$MEMORIES"
-
-# Human-readable (stderr)
-echo "$CONTEXT" >&2
-
-# JSON for Claude Code (stdout)
-ESCAPED=$(echo "$CONTEXT" | jq -Rs .)
-cat << EOF
-{
- "hookSpecificOutput": {
- "hookEventName": "SessionStart",
- "additionalContext": $ESCAPED
- }
-}
-EOF
-exit 0
diff --git a/ai-hooks/memory-on-compact.sh b/ai-hooks/memory-on-compact.sh
deleted file mode 100755
index 8655e182..00000000
--- a/ai-hooks/memory-on-compact.sh
+++ /dev/null
@@ -1,98 +0,0 @@
-#!/bin/bash
-# ============================================================================
-# memory-on-compact.sh - Save session context before compaction
-# ============================================================================
-# Created by M&K ⓒ 2025-2026 VetCoders
-#
-# TRIGGER: PreCompact hook (manual or auto)
-# PURPOSE: Persist conversation context to memex before context window compacts
-#
-# REQUIRES: rmcp-memex server running (rmcp-memex serve --http-port 8987)
-# BENCHMARK: ~50ms (HTTP API)
-# ============================================================================
-
-set -uo pipefail
-export PATH="$HOME/.cargo/bin:/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:$PATH"
-
-# Configuration
-MEMEX_URL="${MEMEX_URL:-http://localhost:8987}"
-MEMEX_TIMEOUT="${MEMEX_TIMEOUT:-5}"
-NAMESPACE="ai-sessions"
-TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
-
-# Quick exits
-command -v curl &>/dev/null || exit 0
-command -v jq &>/dev/null || exit 0
-
-# Read hook input
-input=$(cat)
-
-# Parse JSON fields
-session_id=$(echo "$input" | jq -r '.session_id // "unknown"')
-transcript_path=$(echo "$input" | jq -r '.transcript_path // ""')
-trigger=$(echo "$input" | jq -r '.trigger // "manual"')
-custom_instructions=$(echo "$input" | jq -r '.custom_instructions // ""')
-
-ID="compact-$(date +%Y%m%d-%H%M%S)-${session_id:0:8}"
-
-# Extract summary from transcript if available
-summary=""
-if [ -n "$transcript_path" ] && [ -f "$transcript_path" ]; then
- summary=$(tail -n 20 "$transcript_path" 2>/dev/null | head -c 5000)
-fi
-
-# Add custom instructions if provided
-if [ -n "$custom_instructions" ]; then
- summary="CUSTOM: $custom_instructions
-
-$summary"
-fi
-
-# Only upsert if we have content
-if [ -z "$summary" ]; then
- echo "No content to save for compact" >&2
- exit 0
-fi
-
-# Check if server is up
-if ! curl -s --max-time 1 "$MEMEX_URL/health" >/dev/null 2>&1; then
- echo "Memex server not available, skipping" >&2
- exit 0
-fi
-
-# Build JSON payload
-JSON_PAYLOAD=$(jq -n \
- --arg namespace "$NAMESPACE" \
- --arg id "$ID" \
- --arg text "$summary" \
- --arg type "compact" \
- --arg trigger "$trigger" \
- --arg timestamp "$TIMESTAMP" \
- --arg host "$(hostname)" \
- --arg session "$session_id" \
- '{
- namespace: $namespace,
- id: $id,
- text: $text,
- metadata: {
- type: $type,
- trigger: $trigger,
- timestamp: $timestamp,
- host: $host,
- session: $session
- }
- }')
-
-# Upsert to memex via HTTP
-RESPONSE=$(curl -s --max-time "$MEMEX_TIMEOUT" \
- -X POST "$MEMEX_URL/upsert" \
- -H "Content-Type: application/json" \
- -d "$JSON_PAYLOAD" 2>/dev/null)
-
-if echo "$RESPONSE" | jq -e '.success' &>/dev/null; then
- echo "Compact memory saved: $ID ($trigger)" >&2
-else
- echo "Failed to save compact memory: $RESPONSE" >&2
-fi
-
-exit 0
diff --git a/assets/Loctree.icon/Assets/loctree_logo.png b/assets/Loctree.icon/Assets/loctree_logo.png
deleted file mode 100644
index df0d34a0..00000000
Binary files a/assets/Loctree.icon/Assets/loctree_logo.png and /dev/null differ
diff --git a/assets/Loctree.icon/icon.json b/assets/Loctree.icon/icon.json
deleted file mode 100644
index 45a3105b..00000000
--- a/assets/Loctree.icon/icon.json
+++ /dev/null
@@ -1,128 +0,0 @@
-{
- "fill-specializations" : [
- {
- "value" : {
- "linear-gradient" : [
- "display-p3:0.01901,0.01917,0.01934,1.00000",
- "display-p3:0.03012,0.01695,0.04535,1.00000"
- ]
- }
- },
- {
- "appearance" : "dark",
- "value" : "system-dark"
- }
- ],
- "groups" : [
- {
- "blend-mode" : "hard-light",
- "blur-material-specializations" : [
- {
- "value" : null
- },
- {
- "appearance" : "dark",
- "value" : null
- }
- ],
- "hidden-specializations" : [
- {
- "idiom" : "square",
- "value" : false
- }
- ],
- "layers" : [
- {
- "blend-mode" : "lighten",
- "fill" : {
- "solid" : "extended-gray:1.00000,1.00000"
- },
- "glass-specializations" : [
- {
- "appearance" : "dark",
- "value" : false
- }
- ],
- "image-name-specializations" : [
- {
- "value" : "loctree_logo 2.png"
- },
- {
- "idiom" : "square",
- "value" : "loctree_logo.png"
- }
- ],
- "name" : "loctree_logo",
- "position-specializations" : [
- {
- "idiom" : "square",
- "value" : {
- "scale" : 1.5,
- "translation-in-points" : [
- 0,
- 0
- ]
- }
- }
- ]
- }
- ],
- "lighting-specializations" : [
- {
- "value" : "combined"
- },
- {
- "appearance" : "dark",
- "value" : "combined"
- }
- ],
- "opacity" : 0.9,
- "position-specializations" : [
- {
- "idiom" : "square",
- "value" : {
- "scale" : 1.25,
- "translation-in-points" : [
- 0,
- 21.9296875
- ]
- }
- }
- ],
- "shadow" : {
- "kind" : "none",
- "opacity" : 0.5
- },
- "specular-specializations" : [
- {
- "value" : false
- },
- {
- "appearance" : "dark",
- "value" : false
- }
- ],
- "translucency-specializations" : [
- {
- "value" : {
- "enabled" : false,
- "value" : 0.5
- }
- },
- {
- "appearance" : "dark",
- "value" : {
- "enabled" : false,
- "value" : 0.5
- }
- }
- ]
- }
- ],
- "supported-platforms" : {
- "circles" : [
- "watchOS"
- ],
- "squares" : "shared"
- }
-}
\ No newline at end of file
diff --git a/assets/loctree-badge.svg b/assets/loctree-badge.svg
deleted file mode 100644
index 606c9a51..00000000
--- a/assets/loctree-badge.svg
+++ /dev/null
@@ -1,21 +0,0 @@
-
diff --git a/assets/loctree-logo.png b/assets/loctree-logo.png
deleted file mode 100644
index e49f41b5..00000000
Binary files a/assets/loctree-logo.png and /dev/null differ
diff --git a/assets/loctree-logo.svg b/assets/loctree-logo.svg
deleted file mode 100644
index ccc4e58a..00000000
--- a/assets/loctree-logo.svg
+++ /dev/null
@@ -1,30 +0,0 @@
-
diff --git a/assets/loctree_logo.png b/assets/loctree_logo.png
deleted file mode 100644
index df0d34a0..00000000
Binary files a/assets/loctree_logo.png and /dev/null differ
diff --git a/build-landing.sh b/build-landing.sh
deleted file mode 100755
index 3a5b19f0..00000000
--- a/build-landing.sh
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/bin/bash
-set -e
-
-echo "=== Building Loctree Landing Page ==="
-
-cd landing
-trunk build --release
-
-echo "=== Copying to public_dist ==="
-cd ..
-rm -rf public_dist
-cp -r landing/dist public_dist
-
-echo ""
-echo "=== Build complete! ==="
-echo "Files ready in public_dist/"
-echo ""
-echo "Now click 'Publish' in Replit to deploy."
diff --git a/distribution/README.md b/distribution/README.md
deleted file mode 100644
index 547173d1..00000000
--- a/distribution/README.md
+++ /dev/null
@@ -1,27 +0,0 @@
-# Distribution Spine
-
-This directory is the single source of truth for every release channel that is
-not "cargo publish the crate and hope for the best."
-
-## Channels
-
-- `crates/`
- Rust crates.io release contract and publish notes.
-- `homebrew/`
- Formula source, tap sync notes, and helper scripts.
-- `npm/`
- Canonical npm wrapper and platform-package release flow.
-- `macos/`
- Signing, notarization, and direct-download bundle contract.
-- `linux/`
- Linux release asset contract.
-- `windows/`
- Windows release asset contract.
-
-## Principle
-
-One channel, one home.
-
-Do not scatter release state across root-level `Formula/`, ad-hoc docs, and
-half-remembered shell rituals. If a distribution path is real, it belongs in
-`distribution/`.
diff --git a/distribution/crates/README.md b/distribution/crates/README.md
deleted file mode 100644
index a69631c5..00000000
--- a/distribution/crates/README.md
+++ /dev/null
@@ -1,11 +0,0 @@
-# crates.io
-
-The crates.io release is still the canonical Rust package surface:
-
-- `loctree`
-- `report-leptos`
-- `loctree-mcp`
-
-This channel is necessary, but no longer sufficient on its own. The rest of the
-`distribution/` tree exists so the product can be installed by normal humans,
-not only Rust users.
diff --git a/distribution/homebrew/README.md b/distribution/homebrew/README.md
deleted file mode 100644
index 6a7fa6ce..00000000
--- a/distribution/homebrew/README.md
+++ /dev/null
@@ -1,38 +0,0 @@
-# Homebrew Distribution
-
-The monorepo does not ship one generic Homebrew formula anymore.
-
-Instead:
-
-- CLI formula is rendered into `Loctree/homebrew-cli`
-- MCP formula is rendered into `Loctree/homebrew-mcp`
-
-The rendering source of truth lives in:
-
-- `scripts/render-homebrew-formula.sh`
-- `.github/workflows/homebrew-release.yml`
-
-## Release Contract
-
-1. `publish.yml` builds and uploads binary assets into the thin repos:
- - `Loctree/loct`
- - `Loctree/loctree-mcp`
-2. `homebrew-release.yml` downloads those tarballs, computes SHA256 values, and
- writes the tap formulas.
-
-## Local Test Flow
-
-After a release exists, you can render formulas locally by exporting the same
-SHA variables the workflow uses and running:
-
-```bash
-scripts/render-homebrew-formula.sh loct 0.9.0 /tmp/loct.rb
-scripts/render-homebrew-formula.sh loctree-mcp 0.9.0 /tmp/loctree-mcp.rb
-```
-
-Then test with Homebrew:
-
-```bash
-brew install --build-from-source /tmp/loct.rb
-brew install --build-from-source /tmp/loctree-mcp.rb
-```
diff --git a/distribution/linux/README.md b/distribution/linux/README.md
deleted file mode 100644
index fdca26ff..00000000
--- a/distribution/linux/README.md
+++ /dev/null
@@ -1,10 +0,0 @@
-# Linux
-
-Linux release assets should stay boring and reliable:
-
-- one artifact name per supported target
-- checksum alongside each uploaded release asset
-- npm should only claim the targets that CI actually builds and smoke tests
-
-Right now the honest npm baseline is narrower than the old aspirational docs.
-That is a feature, not a bug.
diff --git a/distribution/macos/README.md b/distribution/macos/README.md
deleted file mode 100644
index 70e554b7..00000000
--- a/distribution/macos/README.md
+++ /dev/null
@@ -1,27 +0,0 @@
-# macOS
-
-This channel is for direct Loctree downloads outside Homebrew and npm.
-
-Target shape:
-
-- signed `loctree` and `loct` binaries
-- notarized archive for direct download
-- optional installer package later if we want a friendlier non-terminal path
-
-Current direction:
-
-- sign binaries with Developer ID Application
-- notarize a zipped bundle with `notarytool`
-- upload the notarized macOS asset to GitHub Releases
-- run `distribution/macos/smoke-releaseability.sh` before packaging so releases fail on non-system dylib paths such as `/opt/homebrew/...`
-
-Releaseability smoke path:
-
-```bash
-make smoke-release-macos-arm64
-```
-
-Apple references:
-
-- Notarizing macOS software before distribution
-- Signing Mac Software with Developer ID
diff --git a/distribution/macos/sign-and-notarize.sh b/distribution/macos/sign-and-notarize.sh
deleted file mode 100755
index 29d4c62a..00000000
--- a/distribution/macos/sign-and-notarize.sh
+++ /dev/null
@@ -1,58 +0,0 @@
-#!/usr/bin/env bash
-set -euo pipefail
-
-if [[ $# -lt 2 ]]; then
- echo "Usage: $0 "
- exit 1
-fi
-
-DIST_DIR="$1"
-OUTPUT_ZIP="$2"
-
-: "${MACOS_DEVELOPER_ID_APPLICATION:?Set MACOS_DEVELOPER_ID_APPLICATION}"
-
-if [[ ! -d "$DIST_DIR" ]]; then
- echo "Missing dist dir: $DIST_DIR"
- exit 1
-fi
-
-# --- Codesign ---
-for bin in loctree loct; do
- target="$DIST_DIR/$bin"
- if [[ -f "$target" ]]; then
- codesign --force --timestamp --options runtime --sign "$MACOS_DEVELOPER_ID_APPLICATION" "$target"
- fi
-done
-
-rm -f "$OUTPUT_ZIP"
-ditto -c -k --keepParent "$DIST_DIR" "$OUTPUT_ZIP"
-
-# --- Notarization (API key auth, 3 retries, 15m timeout) ---
-
-# Resolve auth: prefer API key, fallback to app-specific password
-NOTARY_AUTH=()
-if [[ -n "${APPLE_API_KEY_BASE64:-}" && -n "${APPLE_API_KEY_ID:-}" && -n "${APPLE_API_ISSUER_ID:-}" ]]; then
- KEY_PATH="$RUNNER_TEMP/AuthKey_${APPLE_API_KEY_ID}.p8"
- echo "$APPLE_API_KEY_BASE64" | base64 --decode > "$KEY_PATH"
- NOTARY_AUTH=(--key "$KEY_PATH" --key-id "$APPLE_API_KEY_ID" --issuer "$APPLE_API_ISSUER_ID")
- echo "Using API key auth (key-id: $APPLE_API_KEY_ID)"
-elif [[ -n "${APPLE_ID:-}" && -n "${APPLE_APP_SPECIFIC_PASSWORD:-}" && -n "${APPLE_TEAM_ID:-}" ]]; then
- NOTARY_AUTH=(--apple-id "$APPLE_ID" --team-id "$APPLE_TEAM_ID" --password "$APPLE_APP_SPECIFIC_PASSWORD")
- echo "Using app-specific password auth"
-else
- echo "ERROR: No notarization credentials. Set APPLE_API_KEY_* or APPLE_ID+APPLE_APP_SPECIFIC_PASSWORD"
- exit 1
-fi
-
-for attempt in 1 2 3; do
- echo "Notarization attempt $attempt/3..."
- if xcrun notarytool submit "$OUTPUT_ZIP" "${NOTARY_AUTH[@]}" --wait --timeout 15m; then
- echo "Notarized archive ready: $OUTPUT_ZIP"
- exit 0
- fi
- echo "Attempt $attempt failed, retrying in 10s..."
- sleep 10
-done
-
-echo "Notarization failed after 3 attempts"
-exit 1
diff --git a/distribution/macos/smoke-releaseability.sh b/distribution/macos/smoke-releaseability.sh
deleted file mode 100644
index 73fddf90..00000000
--- a/distribution/macos/smoke-releaseability.sh
+++ /dev/null
@@ -1,56 +0,0 @@
-#!/usr/bin/env bash
-set -euo pipefail
-
-if [[ $# -lt 1 ]]; then
- echo "Usage: $0 [...]"
- exit 1
-fi
-
-if [[ "$(uname -s)" != "Darwin" ]]; then
- echo "This smoke check only runs on macOS."
- exit 1
-fi
-
-RUN_BINARIES="${RUN_BINARIES:-1}"
-status=0
-
-for bin in "$@"; do
- if [[ ! -x "$bin" ]]; then
- echo "[smoke][error] Missing executable: $bin"
- status=1
- continue
- fi
-
- echo "[smoke] Inspecting $bin"
-
- unexpected=()
- while IFS= read -r dep; do
- [[ -z "$dep" ]] && continue
- case "$dep" in
- /System/Library/*|/usr/lib/*|@executable_path/*|@loader_path/*)
- ;;
- *)
- unexpected+=("$dep")
- ;;
- esac
- done < <(otool -L "$bin" | awk 'NR > 1 { print $1 }')
-
- if ((${#unexpected[@]})); then
- echo "[smoke][error] Non-portable runtime dependencies found in $bin:"
- printf ' - %s\n' "${unexpected[@]}"
- status=1
- else
- echo "[smoke] Runtime deps are macOS-system-safe"
- fi
-
- if [[ "$RUN_BINARIES" == "1" ]]; then
- if "$bin" --version >/dev/null; then
- echo "[smoke] Version check passed"
- else
- echo "[smoke][error] Version check failed for $bin"
- status=1
- fi
- fi
-done
-
-exit "$status"
diff --git a/distribution/npm/.github/workflows/test-install.yml b/distribution/npm/.github/workflows/test-install.yml
deleted file mode 100644
index 12292c9b..00000000
--- a/distribution/npm/.github/workflows/test-install.yml
+++ /dev/null
@@ -1,74 +0,0 @@
-name: Test Package Installation
-
-on:
- push:
- branches: [main, develop]
- pull_request:
- branches: [main, develop]
-
-jobs:
- test-install:
- name: Test on ${{ matrix.os }}
- runs-on: ${{ matrix.os }}
- strategy:
- fail-fast: false
- matrix:
- os: [ubuntu-latest, macos-latest, windows-latest]
- node-version: [14.x, 16.x, 18.x, 20.x]
-
- steps:
- - name: Checkout code
- uses: actions/checkout@v3
-
- - name: Setup Node.js ${{ matrix.node-version }}
- uses: actions/setup-node@v3
- with:
- node-version: ${{ matrix.node-version }}
-
- - name: Install package
- run: npm install
-
- - name: Verify binary exists
- run: node -e "console.log(require('./index.js').getBinaryPath())"
-
- - name: Test version command
- run: node -e "console.log(require('./index.js').execLoctreeSync(['--version']))"
-
- - name: Test help command
- run: npx loctree --help
-
- - name: Run example
- run: node example.js
-
- test-platform-packages:
- name: Test platform package ${{ matrix.package }}
- runs-on: ${{ matrix.os }}
- strategy:
- fail-fast: false
- matrix:
- include:
- - package: darwin-arm64
- os: macos-14 # M1 runner
- - package: linux-x64-gnu
- os: ubuntu-latest
- - package: win32-x64-msvc
- os: windows-latest
-
- steps:
- - name: Checkout code
- uses: actions/checkout@v3
-
- - name: Setup Node.js
- uses: actions/setup-node@v3
- with:
- node-version: 20.x
-
- - name: Test platform package install
- working-directory: platform-packages/${{ matrix.package }}
- run: |
- npm install
- node -e "require('fs').accessSync('./loctree${{ matrix.os == 'windows-latest' && '.exe' || '' }}')"
-
- - name: Test binary execution
- working-directory: platform-packages/${{ matrix.package }}
- run: ./loctree${{ matrix.os == 'windows-latest' && '.exe' || '' }} --version
diff --git a/distribution/npm/.npmignore b/distribution/npm/.npmignore
deleted file mode 100644
index 3671aac2..00000000
--- a/distribution/npm/.npmignore
+++ /dev/null
@@ -1,39 +0,0 @@
-# Source files
-*.ts
-*.md.backup
-
-# Tests
-test/
-tests/
-__tests__/
-*.test.js
-*.spec.js
-
-# Development
-.git/
-.github/
-.vscode/
-.idea/
-*.swp
-*.swo
-*~
-
-# Build artifacts
-*.log
-npm-debug.log*
-yarn-debug.log*
-yarn-error.log*
-lerna-debug.log*
-
-# Directories
-node_modules/
-coverage/
-.nyc_output/
-platform-packages/
-scripts/
-
-# Misc
-.DS_Store
-.env
-.env.local
-.env.*.local
diff --git a/distribution/npm/CREATE_PLATFORM_PACKAGES.sh b/distribution/npm/CREATE_PLATFORM_PACKAGES.sh
deleted file mode 100755
index fffffbbb..00000000
--- a/distribution/npm/CREATE_PLATFORM_PACKAGES.sh
+++ /dev/null
@@ -1,56 +0,0 @@
-#!/bin/bash
-# Script to create the currently supported platform package directories
-
-set -e
-
-VERSION="${1:-$(node -p "require('./package.json').version")}"
-
-PLATFORMS=(
- "darwin-arm64:macOS Apple Silicon (ARM64):darwin:arm64"
- "darwin-x64:macOS Intel (x64):darwin:x64"
- "linux-x64-gnu:Linux x64 (glibc):linux:x64"
- "win32-x64-msvc:Windows x64:win32:x64"
-)
-
-for platform_spec in "${PLATFORMS[@]}"; do
- IFS=: read -r platform desc os cpu <<< "$platform_spec"
-
- dir="platform-packages/$platform"
- mkdir -p "$dir"
-
- cat > "$dir/package.json" << PACKAGE_EOF
-{
- "name": "@loctree/$platform",
- "version": "$VERSION",
- "description": "loct binary for $desc",
- "keywords": ["loctree", "$os", "$cpu"],
- "license": "MIT OR Apache-2.0",
- "os": ["$os"],
- "cpu": ["$cpu"],
- "repository": {
- "type": "git",
- "url": "git+https://github.com/Loctree/loctree-ast.git"
- },
- "files": [
- "loct$([ "$os" = "win32" ] && echo ".exe" || echo "")",
- "postinstall.js"
- ],
- "scripts": {
- "postinstall": "node postinstall.js"
- }
-}
-PACKAGE_EOF
-
- # Copy postinstall script
- cp platform-packages/postinstall.js "$dir/"
-
- echo "Created $dir"
-done
-
-echo ""
-echo "All platform-specific packages created!"
-echo ""
-echo "Next steps:"
-echo "1. Run this script to refresh all supported package directories"
-echo "2. Publish each platform package"
-echo "3. Publish the main package"
diff --git a/distribution/npm/LICENSE b/distribution/npm/LICENSE
deleted file mode 100644
index 3aa9d856..00000000
--- a/distribution/npm/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-MIT License
-
-Copyright (c) 2025 Loctree Contributors
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/distribution/npm/PACKAGE_OVERVIEW.md b/distribution/npm/PACKAGE_OVERVIEW.md
deleted file mode 100644
index 7e8cc7db..00000000
--- a/distribution/npm/PACKAGE_OVERVIEW.md
+++ /dev/null
@@ -1,32 +0,0 @@
-# npm Package Overview
-
-`distribution/npm` is the canonical npm release surface for Loctree.
-
-## Shape
-
-- main package: `loctree`
-- command alias: `loct`
-- platform packages:
- - `@loctree/darwin-arm64`
- - `@loctree/darwin-x64`
- - `@loctree/linux-x64-gnu`
- - `@loctree/win32-x64-msvc`
-
-The main package depends on those platform packages through
-`optionalDependencies`. Each platform package first tries the matching GitHub
-release asset from `Loctree/loct`, then falls back to the monorepo release in
-`Loctree/loctree-ast` if the thin repo has not mirrored that asset yet.
-
-## Why this shape
-
-- one publish home under `distribution/npm`
-- no accidental root-level npm publish
-- only claim the targets CI actually builds
-
-## Release contract
-
-1. Build release assets in GitHub Actions.
-2. Sync versions with `node distribution/npm/sync-version.mjs `.
-3. Regenerate platform package manifests with `./distribution/npm/CREATE_PLATFORM_PACKAGES.sh `.
-4. Publish platform packages first.
-5. Publish the main `loctree` package last.
diff --git a/distribution/npm/PUBLISHING.md b/distribution/npm/PUBLISHING.md
deleted file mode 100644
index 32889294..00000000
--- a/distribution/npm/PUBLISHING.md
+++ /dev/null
@@ -1,105 +0,0 @@
-# Publishing Guide for the loctree npm Package
-
-The npm package is a CLI wrapper around thin release assets from
-`Loctree/loct`. The canonical publish path is the monorepo release workflow:
-
-- verify release tag and versions
-- publish thin release assets
-- refresh npm package versions
-- publish platform packages
-- publish the main `loctree` package
-
-See `.github/workflows/publish.yml` for the live source of truth.
-
-## Current Layout
-
-The npm surface follows the `optionalDependencies` pattern:
-
-1. `loctree` — main package with the JavaScript wrapper
-2. `@loctree/darwin-arm64`
-3. `@loctree/darwin-x64`
-4. `@loctree/linux-x64-gnu`
-5. `@loctree/win32-x64-msvc`
-
-The main package depends on the platform packages. Each platform package
-downloads its matching thin release asset from `Loctree/loct`, with a
-monorepo-release fallback in `Loctree/loctree-ast` while mirroring catches up.
-
-## Required Thin Assets
-
-For a release tag `vX.Y.Z`, the publish workflow expects these CLI assets:
-
-- `loct-darwin-aarch64.tar.gz`
-- `loct-darwin-x86_64.tar.gz`
-- `loct-linux-x86_64.tar.gz`
-- `loct-windows-x86_64.zip`
-
-The npm platform packages currently consume:
-
-- `loct-darwin-aarch64.tar.gz`
-- `loct-darwin-x86_64.tar.gz`
-- `loct-linux-x86_64.tar.gz`
-- `loct-windows-x86_64.zip`
-
-## Standard Publish Flow
-
-The normal operator path is a tagged release:
-
-```bash
-make version TYPE=minor TAG=1 PUSH=1
-```
-
-That triggers `.github/workflows/publish.yml`, which then:
-
-1. syncs `distribution/npm/package.json` to the release version
-2. regenerates `platform-packages/*` with `CREATE_PLATFORM_PACKAGES.sh`
-3. publishes each platform package
-4. publishes the main `loctree` npm package
-
-## Manual Fallback
-
-Use this only when you intentionally need a local/manual npm publish:
-
-```bash
-VERSION="$(node -p "require('./distribution/npm/package.json').version")"
-cd distribution/npm
-node sync-version.mjs "$VERSION"
-./CREATE_PLATFORM_PACKAGES.sh "$VERSION"
-```
-
-Publish platform packages first:
-
-```bash
-for dir in platform-packages/*/; do
- (cd "$dir" && npm publish --access public)
-done
-```
-
-Then publish the main package:
-
-```bash
-npm publish --access public
-```
-
-## Verification
-
-Sanity-check the release surface before or after publishing:
-
-```bash
-VERSION="$(node -p "require('./distribution/npm/package.json').version")"
-echo "https://github.com/Loctree/loct/releases/tag/v${VERSION}"
-
-mkdir -p /tmp/loctree-npm-smoke
-cd /tmp/loctree-npm-smoke
-npm init -y
-npm install loctree
-npx loct --version
-node -e "console.log(require('loctree').getBinaryPath())"
-```
-
-## Notes
-
-- Do not hard-code old version numbers in docs or helper commands.
-- Do not publish the main package before the platform packages.
-- The source of truth for asset filenames is `distribution/npm/platform-packages/postinstall.js`.
-- The source of truth for publish choreography is `.github/workflows/publish.yml`.
diff --git a/distribution/npm/QUICKSTART.md b/distribution/npm/QUICKSTART.md
deleted file mode 100644
index bc0744ff..00000000
--- a/distribution/npm/QUICKSTART.md
+++ /dev/null
@@ -1,78 +0,0 @@
-# npm Quick Start
-
-Fast path to publish the `loctree` npm surface after the CLI thin release
-assets already exist.
-
-## Prerequisites
-
-- npm publish access
-- CLI thin release assets published to `Loctree/loct`
-- Node.js 20+ available (matches the release workflow)
-
-## 1. Sync Versions
-
-Run from the repo root:
-
-```bash
-VERSION="$(node -p "require('./distribution/npm/package.json').version")"
-cd distribution/npm
-node sync-version.mjs "$VERSION"
-./CREATE_PLATFORM_PACKAGES.sh "$VERSION"
-```
-
-## 2. Verify Thin Assets
-
-For `v$VERSION`, the CLI release repo should already contain:
-
-- `loct-darwin-aarch64.tar.gz`
-- `loct-darwin-x86_64.tar.gz`
-- `loct-linux-x86_64.tar.gz`
-- `loct-windows-x86_64.zip`
-
-Release page:
-
-```text
-https://github.com/Loctree/loct/releases/tag/v$VERSION
-```
-
-## 3. Publish Platform Packages
-
-```bash
-for dir in platform-packages/*/; do
- (cd "$dir" && npm publish --access public)
-done
-```
-
-Wait a few seconds for npm registry propagation.
-
-## 4. Publish the Main Package
-
-```bash
-npm publish --access public
-```
-
-## 5. Smoke Test
-
-```bash
-mkdir -p /tmp/loctree-npm-smoke
-cd /tmp/loctree-npm-smoke
-npm init -y
-npm install loctree
-npx loct --version
-```
-
-## Canonical Automation
-
-The normal path is still the repo release workflow, not manual publishing:
-
-```bash
-make version TYPE=patch TAG=1 PUSH=1
-```
-
-That tag push runs `.github/workflows/publish.yml`, which refreshes versions,
-publishes platform packages, and then publishes the main package.
-
-## Need More Detail?
-
-Read [PUBLISHING.md](./PUBLISHING.md) for the full operator guide and the live
-sources of truth.
diff --git a/distribution/npm/README.md b/distribution/npm/README.md
deleted file mode 100644
index 7b661f3d..00000000
--- a/distribution/npm/README.md
+++ /dev/null
@@ -1,92 +0,0 @@
-# loctree
-
-Structural code intelligence for AI agents.
-
-This package is the canonical npm distribution surface for Loctree. It installs
-the matching platform package, which then downloads the corresponding GitHub
-release asset for your machine from the `Loctree/loct` thin release repo and
-falls back to the `Loctree/loctree-ast` monorepo release page if the thin repo
-has not mirrored that asset yet.
-
-This npm channel is CLI-only. If you also need `loctree-mcp`, install it via
-Cargo, Homebrew, or the GitHub release assets.
-
-`loct` is the canonical CLI command. `loctree` may still exist as a compatibility
-alias on some install channels, but new docs and examples use `loct`.
-
-## Supported npm targets
-
-- macOS Apple Silicon: `@loctree/darwin-arm64`
-- macOS Intel: `@loctree/darwin-x64`
-- Linux x64 glibc: `@loctree/linux-x64-gnu`
-- Windows x64: `@loctree/win32-x64-msvc`
-
-We only claim the targets CI actually builds today.
-
-## Install
-
-```bash
-npm install loctree
-# or
-pnpm add loctree
-```
-
-For global CLI usage:
-
-```bash
-npm install -g loctree
-```
-
-On Linux, the npm channel currently targets glibc builds only. Alpine/musl
-users should install via Cargo or direct release assets instead.
-
-Then run:
-
-```bash
-loct --help
-```
-
-For the MCP server:
-
-```bash
-cargo install --locked loctree-mcp
-# or
-brew install loctree/mcp/loctree-mcp
-```
-
-If you already installed Loctree globally via Homebrew, do not mix `brew` and
-`npm -g` for the same machine-level CLI. Pick one global channel or remove the
-existing binary first.
-
-## CLI examples
-
-```bash
-npx loct .
-npx loct health
-npx loct slice src/App.tsx --consumers
-npx loct report --serve --port 4173
-```
-
-## What you get
-
-- dependency-aware structural analysis
-- dead code and cycle signals
-- report generation
-- Tauri bridge analysis
-- MCP-ready artifacts for AI workflows
-
-## Troubleshooting
-
-If installation fails:
-
-1. verify the matching GitHub release assets exist
-2. ensure your package manager did not disable `optionalDependencies`
-3. fall back to `cargo install --locked loctree`
-4. install `loctree-mcp` separately if your workflow needs MCP
-
-## Links
-
-- Source: https://github.com/Loctree/loctree-ast
-- CLI releases: https://github.com/Loctree/loct/releases
-- Docs: https://docs.rs/loctree
-- Website: https://loct.io
diff --git a/distribution/npm/bin/loctree b/distribution/npm/bin/loctree
deleted file mode 100644
index 633c5a01..00000000
--- a/distribution/npm/bin/loctree
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/usr/bin/env node
-
-// This is a simple wrapper that delegates to the main index.js
-// The bin field in package.json points here for the CLI command
-
-require('../index.js');
diff --git a/distribution/npm/example.js b/distribution/npm/example.js
deleted file mode 100644
index 6e3440e0..00000000
--- a/distribution/npm/example.js
+++ /dev/null
@@ -1,46 +0,0 @@
-#!/usr/bin/env node
-
-/**
- * Example usage of loctree npm package
- */
-
-const { execLoctreeSync, execLoctree, getBinaryPath } = require('./index.js');
-
-console.log('=== loctree npm package examples (loct binary) ===\n');
-
-// Example 1: Get binary path
-console.log('1. Binary location:');
-try {
- const binaryPath = getBinaryPath();
- console.log(` ${binaryPath}\n`);
-} catch (err) {
- console.error(` Error: ${err.message}\n`);
- process.exit(1);
-}
-
-// Example 2: Get version
-console.log('2. Version check:');
-try {
- const version = execLoctreeSync(['--version']);
- console.log(` ${version.trim()}\n`);
-} catch (err) {
- console.error(` Error: ${err.message}\n`);
-}
-
-// Example 3: Show help
-console.log('3. Available commands:');
-try {
- const help = execLoctreeSync(['--help']);
- console.log(help);
-} catch (err) {
- console.error(` Error: ${err.message}\n`);
-}
-
-// Example 4: Analyze current directory (if it has source files)
-console.log('4. Analyzing current directory:');
-try {
- // This will use inherited stdio, so output goes directly to console
- execLoctree(['.', '--dead', '--confidence', 'high']);
-} catch (err) {
- console.error(` Analysis failed: ${err.message}`);
-}
diff --git a/distribution/npm/index.d.ts b/distribution/npm/index.d.ts
deleted file mode 100644
index e9084eee..00000000
--- a/distribution/npm/index.d.ts
+++ /dev/null
@@ -1,29 +0,0 @@
-/**
- * TypeScript definitions for loctree npm package
- */
-
-import { ExecFileSyncOptions } from 'child_process';
-
-/**
- * Execute loct with given arguments
- * @param args - Command line arguments to pass to loct
- * @param options - Node.js child_process execution options
- * @returns stdout from loct execution
- * @throws Error if loct binary is not found or execution fails
- */
-export function execLoctree(args?: string[], options?: ExecFileSyncOptions): Buffer | string;
-
-/**
- * Execute loct and return result as string
- * @param args - Command line arguments to pass to loct
- * @returns stdout from loct as UTF-8 string
- * @throws Error if loct binary is not found or execution fails
- */
-export function execLoctreeSync(args?: string[]): string;
-
-/**
- * Get the absolute path to the loct binary for the current platform
- * @returns Absolute path to the loct binary
- * @throws Error if platform is unsupported or binary is not found
- */
-export function getBinaryPath(): string;
diff --git a/distribution/npm/index.js b/distribution/npm/index.js
deleted file mode 100644
index c8461da9..00000000
--- a/distribution/npm/index.js
+++ /dev/null
@@ -1,91 +0,0 @@
-#!/usr/bin/env node
-
-const { execFileSync } = require('child_process');
-const { join } = require('path');
-const { existsSync } = require('fs');
-
-const {
- getPackageNameForPlatformKey,
- resolvePlatformKey,
- unsupportedPlatformMessage,
-} = require('./platform-support');
-
-function getBinaryPath() {
- const platformKey = resolvePlatformKey();
-
- if (!platformKey) {
- throw new Error(`Unsupported platform: ${process.platform}-${process.arch}`);
- }
-
- const packageName = getPackageNameForPlatformKey(platformKey);
-
- if (!packageName) {
- throw new Error(unsupportedPlatformMessage({ platformKey }));
- }
-
- const binaryName = process.platform === 'win32' ? 'loct.exe' : 'loct';
- const binaryPath = join(__dirname, 'node_modules', packageName, binaryName);
-
- if (!existsSync(binaryPath)) {
- throw new Error(
- `loct binary not found at ${binaryPath}. ` +
- `This may happen if optionalDependencies are disabled. ` +
- `Please ensure "${packageName}" is installed.`
- );
- }
-
- return binaryPath;
-}
-
-/**
- * Execute loct with given arguments
- * @param {string[]} args - Command line arguments
- * @param {object} options - Execution options
- * @returns {Buffer|string} - stdout from loct
- */
-function execLoctree(args = [], options = {}) {
- const binaryPath = getBinaryPath();
-
- const execOptions = {
- stdio: 'pipe',
- ...options,
- };
-
- try {
- return execFileSync(binaryPath, args, execOptions);
- } catch (err) {
- if (err.status !== undefined) {
- process.exit(err.status);
- }
- throw err;
- }
-}
-
-/**
- * Execute loct and return result as string
- * @param {string[]} args - Command line arguments
- * @returns {string} - stdout from loct
- */
-function execLoctreeSync(args = []) {
- const binaryPath = getBinaryPath();
-
- try {
- return execFileSync(binaryPath, args, { encoding: 'utf8' });
- } catch (err) {
- if (err.stdout) return err.stdout;
- throw err;
- }
-}
-
-// Export API
-module.exports = {
- execLoctree,
- execLoctreeSync,
- getBinaryPath,
-};
-
-// CLI execution
-if (require.main === module) {
- const args = process.argv.slice(2);
- execFileSync(getBinaryPath(), args, { stdio: 'inherit' });
-}
diff --git a/distribution/npm/install.js b/distribution/npm/install.js
deleted file mode 100644
index c5bc3710..00000000
--- a/distribution/npm/install.js
+++ /dev/null
@@ -1,58 +0,0 @@
-#!/usr/bin/env node
-
-const { existsSync } = require('fs');
-const { join } = require('path');
-const { spawnSync } = require('child_process');
-
-const {
- getPackageNameForPlatformKey,
- resolvePlatformKey,
- unsupportedPlatformMessage,
-} = require('./platform-support');
-
-function validateInstallation() {
- const platformKey = resolvePlatformKey();
-
- if (!platformKey) {
- console.error(`Unsupported platform: ${process.platform}-${process.arch}`);
- console.error('Supported platforms:');
- console.error(' - macOS Apple Silicon (ARM64)');
- console.error(' - macOS Intel (x64)');
- console.error(' - Linux x64 (glibc)');
- console.error(' - Windows x64');
- process.exit(1);
- }
-
- const packageName = getPackageNameForPlatformKey(platformKey);
-
- if (!packageName) {
- console.error(unsupportedPlatformMessage({ platformKey }));
- process.exit(1);
- }
-
- // Check if the platform-specific package was installed
- const binaryName = process.platform === 'win32' ? 'loct.exe' : 'loct';
- const binaryPath = join(__dirname, 'node_modules', packageName, binaryName);
-
- if (!existsSync(binaryPath)) {
- console.warn(`Warning: loct binary not found at ${binaryPath}`);
- console.warn('This may happen if optionalDependencies are disabled.');
- console.warn('The package may not work correctly.');
- return;
- }
-
- // Verify binary is executable and correct version
- try {
- const result = spawnSync(binaryPath, ['--version'], { encoding: 'utf8' });
- if (result.status === 0) {
- console.log(`loct binary installed successfully: ${result.stdout.trim()}`);
- } else {
- console.warn(`Warning: loct binary may not be working correctly`);
- }
- } catch (err) {
- console.warn(`Warning: Could not verify loct binary: ${err.message}`);
- }
-}
-
-// Run validation
-validateInstallation();
diff --git a/distribution/npm/package.json b/distribution/npm/package.json
deleted file mode 100644
index 226c4662..00000000
--- a/distribution/npm/package.json
+++ /dev/null
@@ -1,54 +0,0 @@
-{
- "name": "loctree",
- "version": "0.8.17",
- "description": "Structural code intelligence for AI agents. Dead exports, circular imports, dependency graphs, reports, and MCP-ready analysis.",
- "keywords": [
- "static-analysis",
- "dead-code",
- "imports",
- "exports",
- "codebase",
- "typescript",
- "javascript",
- "rust",
- "circular-dependencies",
- "dependency-graph"
- ],
- "main": "index.js",
- "types": "index.d.ts",
- "bin": {
- "loctree": "bin/loctree",
- "loct": "bin/loctree"
- },
- "files": [
- "index.js",
- "index.d.ts",
- "bin/loctree",
- "install.js",
- "platform-support.js",
- "README.md",
- "LICENSE"
- ],
- "scripts": {
- "postinstall": "node install.js"
- },
- "repository": {
- "type": "git",
- "url": "git+https://github.com/Loctree/loctree-ast.git"
- },
- "homepage": "https://loct.io",
- "bugs": {
- "url": "https://github.com/Loctree/loctree-ast/issues"
- },
- "license": "MIT OR Apache-2.0",
- "author": "Loctree ",
- "engines": {
- "node": ">=14.0.0"
- },
- "optionalDependencies": {
- "@loctree/darwin-arm64": "0.8.17",
- "@loctree/darwin-x64": "0.8.17",
- "@loctree/linux-x64-gnu": "0.8.17",
- "@loctree/win32-x64-msvc": "0.8.17"
- }
-}
diff --git a/distribution/npm/platform-packages/darwin-arm64/package.json b/distribution/npm/platform-packages/darwin-arm64/package.json
deleted file mode 100644
index 4542c1a6..00000000
--- a/distribution/npm/platform-packages/darwin-arm64/package.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
- "name": "@loctree/darwin-arm64",
- "version": "0.8.17",
- "description": "loct binary for macOS Apple Silicon (ARM64)",
- "keywords": ["loctree", "darwin", "arm64"],
- "license": "MIT OR Apache-2.0",
- "os": ["darwin"],
- "cpu": ["arm64"],
- "repository": {
- "type": "git",
- "url": "git+https://github.com/Loctree/loctree-ast.git"
- },
- "files": [
- "loct",
- "postinstall.js"
- ],
- "scripts": {
- "postinstall": "node postinstall.js"
- }
-}
diff --git a/distribution/npm/platform-packages/darwin-arm64/postinstall.js b/distribution/npm/platform-packages/darwin-arm64/postinstall.js
deleted file mode 100644
index f37ab319..00000000
--- a/distribution/npm/platform-packages/darwin-arm64/postinstall.js
+++ /dev/null
@@ -1,164 +0,0 @@
-#!/usr/bin/env node
-
-/**
- * Postinstall script for platform-specific packages.
- * Downloads the current release asset from GitHub releases and extracts it in place.
- */
-
-const https = require('https');
-const { createWriteStream, chmodSync, existsSync, unlinkSync } = require('fs');
-const { join } = require('path');
-const { pipeline } = require('stream');
-const { promisify } = require('util');
-const { execSync } = require('child_process');
-
-const streamPipeline = promisify(pipeline);
-
-// Prefer the thin release repo, but fall back to the monorepo release page
-// while publish choreography is still catching up.
-const RELEASE_REPOS = Object.freeze([
- {
- repo: 'Loctree/loct',
- label: 'thin release repo',
- },
- {
- repo: 'Loctree/loctree-ast',
- label: 'monorepo release fallback',
- },
-]);
-const VERSION = require('./package.json').version;
-
-// Platform-specific release assets currently shipped by CI
-const BINARY_MAPPINGS = {
- '@loctree/darwin-arm64': {
- file: 'loct-darwin-aarch64.tar.gz',
- target: 'loct',
- },
- '@loctree/darwin-x64': {
- file: 'loct-darwin-x86_64.tar.gz',
- target: 'loct',
- },
- '@loctree/linux-x64-gnu': {
- file: 'loct-linux-x86_64.tar.gz',
- target: 'loct',
- },
- '@loctree/win32-x64-msvc': {
- file: 'loct-windows-x86_64.zip',
- target: 'loct.exe',
- },
-};
-
-async function downloadFile(url, destPath) {
- return new Promise((resolve, reject) => {
- https.get(url, {
- headers: { 'User-Agent': 'loct-npm-installer' },
- followRedirect: true,
- }, (response) => {
- // Handle redirects
- if (response.statusCode === 301 || response.statusCode === 302) {
- return downloadFile(response.headers.location, destPath).then(resolve).catch(reject);
- }
-
- if (response.statusCode !== 200) {
- reject(new Error(`Failed to download: HTTP ${response.statusCode}`));
- return;
- }
-
- const fileStream = createWriteStream(destPath);
- streamPipeline(response, fileStream)
- .then(resolve)
- .catch(reject);
- }).on('error', reject);
- });
-}
-
-function buildDownloadTargets(version, file) {
- return RELEASE_REPOS.map(({ repo, label }) => ({
- label,
- url: `https://github.com/${repo}/releases/download/v${version}/${file}`,
- }));
-}
-
-async function downloadReleaseAsset(downloadTargets, destPath) {
- let lastError = null;
-
- for (const target of downloadTargets) {
- if (existsSync(destPath)) {
- unlinkSync(destPath);
- }
-
- console.log(`Downloading loct release asset from ${target.url} (${target.label})...`);
-
- try {
- await downloadFile(target.url, destPath);
- return target;
- } catch (error) {
- lastError = error;
- console.warn(`Download failed from ${target.label}: ${error.message}`);
- }
- }
-
- throw lastError || new Error('No download targets available');
-}
-
-async function install() {
- const packageName = require('./package.json').name;
- const mapping = BINARY_MAPPINGS[packageName];
-
- if (!mapping) {
- console.error(`Unknown package: ${packageName}`);
- process.exit(1);
- }
-
- const { file, target } = mapping;
- const downloadTargets = buildDownloadTargets(VERSION, file);
- const targetPath = join(__dirname, target);
- const archivePath = join(__dirname, file);
-
- // Skip if already exists
- if (existsSync(targetPath)) {
- console.log(`Binary already exists at ${targetPath}`);
- return;
- }
-
- try {
- const downloadedFrom = await downloadReleaseAsset(downloadTargets, archivePath);
-
- if (file.endsWith('.tar.gz')) {
- execSync(`tar -xzf "${archivePath}" -C "${__dirname}"`, { stdio: 'inherit' });
- } else if (file.endsWith('.zip')) {
- if (process.platform === 'win32') {
- execSync(
- `powershell -Command "Expand-Archive -Path '${archivePath}' -DestinationPath '${__dirname}' -Force"`,
- { stdio: 'inherit' }
- );
- } else {
- execSync(`unzip -o "${archivePath}" -d "${__dirname}"`, { stdio: 'inherit' });
- }
- }
-
- if (existsSync(archivePath)) {
- unlinkSync(archivePath);
- }
-
- // Make executable (Unix-like systems)
- if (process.platform !== 'win32') {
- chmodSync(targetPath, 0o755);
- }
-
- console.log(`Successfully installed loct binary to ${targetPath} via ${downloadedFrom.label}`);
- } catch (error) {
- console.error(`Failed to download loct binary: ${error.message}`);
- console.error('Attempted URLs:');
- downloadTargets.forEach((target) => console.error(`- ${target.url}`));
- console.error('');
- console.error('Possible solutions:');
- console.error('1. Check your internet connection');
- console.error('2. Verify the matching release assets exist on GitHub');
- console.error('3. Install loct manually from the thin release repo: https://github.com/Loctree/loct/releases');
- console.error('4. If the thin repo is still missing the asset, try the monorepo fallback: https://github.com/Loctree/loctree-ast/releases');
- process.exit(1);
- }
-}
-
-install();
diff --git a/distribution/npm/platform-packages/darwin-x64/package.json b/distribution/npm/platform-packages/darwin-x64/package.json
deleted file mode 100644
index 4a9818df..00000000
--- a/distribution/npm/platform-packages/darwin-x64/package.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
- "name": "@loctree/darwin-x64",
- "version": "0.8.17",
- "description": "loct binary for macOS Intel (x64)",
- "keywords": ["loctree", "darwin", "x64"],
- "license": "MIT OR Apache-2.0",
- "os": ["darwin"],
- "cpu": ["x64"],
- "repository": {
- "type": "git",
- "url": "git+https://github.com/Loctree/loctree-ast.git"
- },
- "files": [
- "loct",
- "postinstall.js"
- ],
- "scripts": {
- "postinstall": "node postinstall.js"
- }
-}
diff --git a/distribution/npm/platform-packages/darwin-x64/postinstall.js b/distribution/npm/platform-packages/darwin-x64/postinstall.js
deleted file mode 100644
index f37ab319..00000000
--- a/distribution/npm/platform-packages/darwin-x64/postinstall.js
+++ /dev/null
@@ -1,164 +0,0 @@
-#!/usr/bin/env node
-
-/**
- * Postinstall script for platform-specific packages.
- * Downloads the current release asset from GitHub releases and extracts it in place.
- */
-
-const https = require('https');
-const { createWriteStream, chmodSync, existsSync, unlinkSync } = require('fs');
-const { join } = require('path');
-const { pipeline } = require('stream');
-const { promisify } = require('util');
-const { execSync } = require('child_process');
-
-const streamPipeline = promisify(pipeline);
-
-// Prefer the thin release repo, but fall back to the monorepo release page
-// while publish choreography is still catching up.
-const RELEASE_REPOS = Object.freeze([
- {
- repo: 'Loctree/loct',
- label: 'thin release repo',
- },
- {
- repo: 'Loctree/loctree-ast',
- label: 'monorepo release fallback',
- },
-]);
-const VERSION = require('./package.json').version;
-
-// Platform-specific release assets currently shipped by CI
-const BINARY_MAPPINGS = {
- '@loctree/darwin-arm64': {
- file: 'loct-darwin-aarch64.tar.gz',
- target: 'loct',
- },
- '@loctree/darwin-x64': {
- file: 'loct-darwin-x86_64.tar.gz',
- target: 'loct',
- },
- '@loctree/linux-x64-gnu': {
- file: 'loct-linux-x86_64.tar.gz',
- target: 'loct',
- },
- '@loctree/win32-x64-msvc': {
- file: 'loct-windows-x86_64.zip',
- target: 'loct.exe',
- },
-};
-
-async function downloadFile(url, destPath) {
- return new Promise((resolve, reject) => {
- https.get(url, {
- headers: { 'User-Agent': 'loct-npm-installer' },
- followRedirect: true,
- }, (response) => {
- // Handle redirects
- if (response.statusCode === 301 || response.statusCode === 302) {
- return downloadFile(response.headers.location, destPath).then(resolve).catch(reject);
- }
-
- if (response.statusCode !== 200) {
- reject(new Error(`Failed to download: HTTP ${response.statusCode}`));
- return;
- }
-
- const fileStream = createWriteStream(destPath);
- streamPipeline(response, fileStream)
- .then(resolve)
- .catch(reject);
- }).on('error', reject);
- });
-}
-
-function buildDownloadTargets(version, file) {
- return RELEASE_REPOS.map(({ repo, label }) => ({
- label,
- url: `https://github.com/${repo}/releases/download/v${version}/${file}`,
- }));
-}
-
-async function downloadReleaseAsset(downloadTargets, destPath) {
- let lastError = null;
-
- for (const target of downloadTargets) {
- if (existsSync(destPath)) {
- unlinkSync(destPath);
- }
-
- console.log(`Downloading loct release asset from ${target.url} (${target.label})...`);
-
- try {
- await downloadFile(target.url, destPath);
- return target;
- } catch (error) {
- lastError = error;
- console.warn(`Download failed from ${target.label}: ${error.message}`);
- }
- }
-
- throw lastError || new Error('No download targets available');
-}
-
-async function install() {
- const packageName = require('./package.json').name;
- const mapping = BINARY_MAPPINGS[packageName];
-
- if (!mapping) {
- console.error(`Unknown package: ${packageName}`);
- process.exit(1);
- }
-
- const { file, target } = mapping;
- const downloadTargets = buildDownloadTargets(VERSION, file);
- const targetPath = join(__dirname, target);
- const archivePath = join(__dirname, file);
-
- // Skip if already exists
- if (existsSync(targetPath)) {
- console.log(`Binary already exists at ${targetPath}`);
- return;
- }
-
- try {
- const downloadedFrom = await downloadReleaseAsset(downloadTargets, archivePath);
-
- if (file.endsWith('.tar.gz')) {
- execSync(`tar -xzf "${archivePath}" -C "${__dirname}"`, { stdio: 'inherit' });
- } else if (file.endsWith('.zip')) {
- if (process.platform === 'win32') {
- execSync(
- `powershell -Command "Expand-Archive -Path '${archivePath}' -DestinationPath '${__dirname}' -Force"`,
- { stdio: 'inherit' }
- );
- } else {
- execSync(`unzip -o "${archivePath}" -d "${__dirname}"`, { stdio: 'inherit' });
- }
- }
-
- if (existsSync(archivePath)) {
- unlinkSync(archivePath);
- }
-
- // Make executable (Unix-like systems)
- if (process.platform !== 'win32') {
- chmodSync(targetPath, 0o755);
- }
-
- console.log(`Successfully installed loct binary to ${targetPath} via ${downloadedFrom.label}`);
- } catch (error) {
- console.error(`Failed to download loct binary: ${error.message}`);
- console.error('Attempted URLs:');
- downloadTargets.forEach((target) => console.error(`- ${target.url}`));
- console.error('');
- console.error('Possible solutions:');
- console.error('1. Check your internet connection');
- console.error('2. Verify the matching release assets exist on GitHub');
- console.error('3. Install loct manually from the thin release repo: https://github.com/Loctree/loct/releases');
- console.error('4. If the thin repo is still missing the asset, try the monorepo fallback: https://github.com/Loctree/loctree-ast/releases');
- process.exit(1);
- }
-}
-
-install();
diff --git a/distribution/npm/platform-packages/linux-x64-gnu/package.json b/distribution/npm/platform-packages/linux-x64-gnu/package.json
deleted file mode 100644
index 25a4cee8..00000000
--- a/distribution/npm/platform-packages/linux-x64-gnu/package.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
- "name": "@loctree/linux-x64-gnu",
- "version": "0.8.17",
- "description": "loct binary for Linux x64 (glibc)",
- "keywords": ["loctree", "linux", "x64"],
- "license": "MIT OR Apache-2.0",
- "os": ["linux"],
- "cpu": ["x64"],
- "repository": {
- "type": "git",
- "url": "git+https://github.com/Loctree/loctree-ast.git"
- },
- "files": [
- "loct",
- "postinstall.js"
- ],
- "scripts": {
- "postinstall": "node postinstall.js"
- }
-}
diff --git a/distribution/npm/platform-packages/linux-x64-gnu/postinstall.js b/distribution/npm/platform-packages/linux-x64-gnu/postinstall.js
deleted file mode 100644
index f37ab319..00000000
--- a/distribution/npm/platform-packages/linux-x64-gnu/postinstall.js
+++ /dev/null
@@ -1,164 +0,0 @@
-#!/usr/bin/env node
-
-/**
- * Postinstall script for platform-specific packages.
- * Downloads the current release asset from GitHub releases and extracts it in place.
- */
-
-const https = require('https');
-const { createWriteStream, chmodSync, existsSync, unlinkSync } = require('fs');
-const { join } = require('path');
-const { pipeline } = require('stream');
-const { promisify } = require('util');
-const { execSync } = require('child_process');
-
-const streamPipeline = promisify(pipeline);
-
-// Prefer the thin release repo, but fall back to the monorepo release page
-// while publish choreography is still catching up.
-const RELEASE_REPOS = Object.freeze([
- {
- repo: 'Loctree/loct',
- label: 'thin release repo',
- },
- {
- repo: 'Loctree/loctree-ast',
- label: 'monorepo release fallback',
- },
-]);
-const VERSION = require('./package.json').version;
-
-// Platform-specific release assets currently shipped by CI
-const BINARY_MAPPINGS = {
- '@loctree/darwin-arm64': {
- file: 'loct-darwin-aarch64.tar.gz',
- target: 'loct',
- },
- '@loctree/darwin-x64': {
- file: 'loct-darwin-x86_64.tar.gz',
- target: 'loct',
- },
- '@loctree/linux-x64-gnu': {
- file: 'loct-linux-x86_64.tar.gz',
- target: 'loct',
- },
- '@loctree/win32-x64-msvc': {
- file: 'loct-windows-x86_64.zip',
- target: 'loct.exe',
- },
-};
-
-async function downloadFile(url, destPath) {
- return new Promise((resolve, reject) => {
- https.get(url, {
- headers: { 'User-Agent': 'loct-npm-installer' },
- followRedirect: true,
- }, (response) => {
- // Handle redirects
- if (response.statusCode === 301 || response.statusCode === 302) {
- return downloadFile(response.headers.location, destPath).then(resolve).catch(reject);
- }
-
- if (response.statusCode !== 200) {
- reject(new Error(`Failed to download: HTTP ${response.statusCode}`));
- return;
- }
-
- const fileStream = createWriteStream(destPath);
- streamPipeline(response, fileStream)
- .then(resolve)
- .catch(reject);
- }).on('error', reject);
- });
-}
-
-function buildDownloadTargets(version, file) {
- return RELEASE_REPOS.map(({ repo, label }) => ({
- label,
- url: `https://github.com/${repo}/releases/download/v${version}/${file}`,
- }));
-}
-
-async function downloadReleaseAsset(downloadTargets, destPath) {
- let lastError = null;
-
- for (const target of downloadTargets) {
- if (existsSync(destPath)) {
- unlinkSync(destPath);
- }
-
- console.log(`Downloading loct release asset from ${target.url} (${target.label})...`);
-
- try {
- await downloadFile(target.url, destPath);
- return target;
- } catch (error) {
- lastError = error;
- console.warn(`Download failed from ${target.label}: ${error.message}`);
- }
- }
-
- throw lastError || new Error('No download targets available');
-}
-
-async function install() {
- const packageName = require('./package.json').name;
- const mapping = BINARY_MAPPINGS[packageName];
-
- if (!mapping) {
- console.error(`Unknown package: ${packageName}`);
- process.exit(1);
- }
-
- const { file, target } = mapping;
- const downloadTargets = buildDownloadTargets(VERSION, file);
- const targetPath = join(__dirname, target);
- const archivePath = join(__dirname, file);
-
- // Skip if already exists
- if (existsSync(targetPath)) {
- console.log(`Binary already exists at ${targetPath}`);
- return;
- }
-
- try {
- const downloadedFrom = await downloadReleaseAsset(downloadTargets, archivePath);
-
- if (file.endsWith('.tar.gz')) {
- execSync(`tar -xzf "${archivePath}" -C "${__dirname}"`, { stdio: 'inherit' });
- } else if (file.endsWith('.zip')) {
- if (process.platform === 'win32') {
- execSync(
- `powershell -Command "Expand-Archive -Path '${archivePath}' -DestinationPath '${__dirname}' -Force"`,
- { stdio: 'inherit' }
- );
- } else {
- execSync(`unzip -o "${archivePath}" -d "${__dirname}"`, { stdio: 'inherit' });
- }
- }
-
- if (existsSync(archivePath)) {
- unlinkSync(archivePath);
- }
-
- // Make executable (Unix-like systems)
- if (process.platform !== 'win32') {
- chmodSync(targetPath, 0o755);
- }
-
- console.log(`Successfully installed loct binary to ${targetPath} via ${downloadedFrom.label}`);
- } catch (error) {
- console.error(`Failed to download loct binary: ${error.message}`);
- console.error('Attempted URLs:');
- downloadTargets.forEach((target) => console.error(`- ${target.url}`));
- console.error('');
- console.error('Possible solutions:');
- console.error('1. Check your internet connection');
- console.error('2. Verify the matching release assets exist on GitHub');
- console.error('3. Install loct manually from the thin release repo: https://github.com/Loctree/loct/releases');
- console.error('4. If the thin repo is still missing the asset, try the monorepo fallback: https://github.com/Loctree/loctree-ast/releases');
- process.exit(1);
- }
-}
-
-install();
diff --git a/distribution/npm/platform-packages/postinstall.js b/distribution/npm/platform-packages/postinstall.js
deleted file mode 100644
index f37ab319..00000000
--- a/distribution/npm/platform-packages/postinstall.js
+++ /dev/null
@@ -1,164 +0,0 @@
-#!/usr/bin/env node
-
-/**
- * Postinstall script for platform-specific packages.
- * Downloads the current release asset from GitHub releases and extracts it in place.
- */
-
-const https = require('https');
-const { createWriteStream, chmodSync, existsSync, unlinkSync } = require('fs');
-const { join } = require('path');
-const { pipeline } = require('stream');
-const { promisify } = require('util');
-const { execSync } = require('child_process');
-
-const streamPipeline = promisify(pipeline);
-
-// Prefer the thin release repo, but fall back to the monorepo release page
-// while publish choreography is still catching up.
-const RELEASE_REPOS = Object.freeze([
- {
- repo: 'Loctree/loct',
- label: 'thin release repo',
- },
- {
- repo: 'Loctree/loctree-ast',
- label: 'monorepo release fallback',
- },
-]);
-const VERSION = require('./package.json').version;
-
-// Platform-specific release assets currently shipped by CI
-const BINARY_MAPPINGS = {
- '@loctree/darwin-arm64': {
- file: 'loct-darwin-aarch64.tar.gz',
- target: 'loct',
- },
- '@loctree/darwin-x64': {
- file: 'loct-darwin-x86_64.tar.gz',
- target: 'loct',
- },
- '@loctree/linux-x64-gnu': {
- file: 'loct-linux-x86_64.tar.gz',
- target: 'loct',
- },
- '@loctree/win32-x64-msvc': {
- file: 'loct-windows-x86_64.zip',
- target: 'loct.exe',
- },
-};
-
-async function downloadFile(url, destPath) {
- return new Promise((resolve, reject) => {
- https.get(url, {
- headers: { 'User-Agent': 'loct-npm-installer' },
- followRedirect: true,
- }, (response) => {
- // Handle redirects
- if (response.statusCode === 301 || response.statusCode === 302) {
- return downloadFile(response.headers.location, destPath).then(resolve).catch(reject);
- }
-
- if (response.statusCode !== 200) {
- reject(new Error(`Failed to download: HTTP ${response.statusCode}`));
- return;
- }
-
- const fileStream = createWriteStream(destPath);
- streamPipeline(response, fileStream)
- .then(resolve)
- .catch(reject);
- }).on('error', reject);
- });
-}
-
-function buildDownloadTargets(version, file) {
- return RELEASE_REPOS.map(({ repo, label }) => ({
- label,
- url: `https://github.com/${repo}/releases/download/v${version}/${file}`,
- }));
-}
-
-async function downloadReleaseAsset(downloadTargets, destPath) {
- let lastError = null;
-
- for (const target of downloadTargets) {
- if (existsSync(destPath)) {
- unlinkSync(destPath);
- }
-
- console.log(`Downloading loct release asset from ${target.url} (${target.label})...`);
-
- try {
- await downloadFile(target.url, destPath);
- return target;
- } catch (error) {
- lastError = error;
- console.warn(`Download failed from ${target.label}: ${error.message}`);
- }
- }
-
- throw lastError || new Error('No download targets available');
-}
-
-async function install() {
- const packageName = require('./package.json').name;
- const mapping = BINARY_MAPPINGS[packageName];
-
- if (!mapping) {
- console.error(`Unknown package: ${packageName}`);
- process.exit(1);
- }
-
- const { file, target } = mapping;
- const downloadTargets = buildDownloadTargets(VERSION, file);
- const targetPath = join(__dirname, target);
- const archivePath = join(__dirname, file);
-
- // Skip if already exists
- if (existsSync(targetPath)) {
- console.log(`Binary already exists at ${targetPath}`);
- return;
- }
-
- try {
- const downloadedFrom = await downloadReleaseAsset(downloadTargets, archivePath);
-
- if (file.endsWith('.tar.gz')) {
- execSync(`tar -xzf "${archivePath}" -C "${__dirname}"`, { stdio: 'inherit' });
- } else if (file.endsWith('.zip')) {
- if (process.platform === 'win32') {
- execSync(
- `powershell -Command "Expand-Archive -Path '${archivePath}' -DestinationPath '${__dirname}' -Force"`,
- { stdio: 'inherit' }
- );
- } else {
- execSync(`unzip -o "${archivePath}" -d "${__dirname}"`, { stdio: 'inherit' });
- }
- }
-
- if (existsSync(archivePath)) {
- unlinkSync(archivePath);
- }
-
- // Make executable (Unix-like systems)
- if (process.platform !== 'win32') {
- chmodSync(targetPath, 0o755);
- }
-
- console.log(`Successfully installed loct binary to ${targetPath} via ${downloadedFrom.label}`);
- } catch (error) {
- console.error(`Failed to download loct binary: ${error.message}`);
- console.error('Attempted URLs:');
- downloadTargets.forEach((target) => console.error(`- ${target.url}`));
- console.error('');
- console.error('Possible solutions:');
- console.error('1. Check your internet connection');
- console.error('2. Verify the matching release assets exist on GitHub');
- console.error('3. Install loct manually from the thin release repo: https://github.com/Loctree/loct/releases');
- console.error('4. If the thin repo is still missing the asset, try the monorepo fallback: https://github.com/Loctree/loctree-ast/releases');
- process.exit(1);
- }
-}
-
-install();
diff --git a/distribution/npm/platform-packages/win32-x64-msvc/package.json b/distribution/npm/platform-packages/win32-x64-msvc/package.json
deleted file mode 100644
index b0b35439..00000000
--- a/distribution/npm/platform-packages/win32-x64-msvc/package.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
- "name": "@loctree/win32-x64-msvc",
- "version": "0.8.17",
- "description": "loct binary for Windows x64",
- "keywords": ["loctree", "win32", "x64"],
- "license": "MIT OR Apache-2.0",
- "os": ["win32"],
- "cpu": ["x64"],
- "repository": {
- "type": "git",
- "url": "git+https://github.com/Loctree/loctree-ast.git"
- },
- "files": [
- "loct.exe",
- "postinstall.js"
- ],
- "scripts": {
- "postinstall": "node postinstall.js"
- }
-}
diff --git a/distribution/npm/platform-packages/win32-x64-msvc/postinstall.js b/distribution/npm/platform-packages/win32-x64-msvc/postinstall.js
deleted file mode 100644
index f37ab319..00000000
--- a/distribution/npm/platform-packages/win32-x64-msvc/postinstall.js
+++ /dev/null
@@ -1,164 +0,0 @@
-#!/usr/bin/env node
-
-/**
- * Postinstall script for platform-specific packages.
- * Downloads the current release asset from GitHub releases and extracts it in place.
- */
-
-const https = require('https');
-const { createWriteStream, chmodSync, existsSync, unlinkSync } = require('fs');
-const { join } = require('path');
-const { pipeline } = require('stream');
-const { promisify } = require('util');
-const { execSync } = require('child_process');
-
-const streamPipeline = promisify(pipeline);
-
-// Prefer the thin release repo, but fall back to the monorepo release page
-// while publish choreography is still catching up.
-const RELEASE_REPOS = Object.freeze([
- {
- repo: 'Loctree/loct',
- label: 'thin release repo',
- },
- {
- repo: 'Loctree/loctree-ast',
- label: 'monorepo release fallback',
- },
-]);
-const VERSION = require('./package.json').version;
-
-// Platform-specific release assets currently shipped by CI
-const BINARY_MAPPINGS = {
- '@loctree/darwin-arm64': {
- file: 'loct-darwin-aarch64.tar.gz',
- target: 'loct',
- },
- '@loctree/darwin-x64': {
- file: 'loct-darwin-x86_64.tar.gz',
- target: 'loct',
- },
- '@loctree/linux-x64-gnu': {
- file: 'loct-linux-x86_64.tar.gz',
- target: 'loct',
- },
- '@loctree/win32-x64-msvc': {
- file: 'loct-windows-x86_64.zip',
- target: 'loct.exe',
- },
-};
-
-async function downloadFile(url, destPath) {
- return new Promise((resolve, reject) => {
- https.get(url, {
- headers: { 'User-Agent': 'loct-npm-installer' },
- followRedirect: true,
- }, (response) => {
- // Handle redirects
- if (response.statusCode === 301 || response.statusCode === 302) {
- return downloadFile(response.headers.location, destPath).then(resolve).catch(reject);
- }
-
- if (response.statusCode !== 200) {
- reject(new Error(`Failed to download: HTTP ${response.statusCode}`));
- return;
- }
-
- const fileStream = createWriteStream(destPath);
- streamPipeline(response, fileStream)
- .then(resolve)
- .catch(reject);
- }).on('error', reject);
- });
-}
-
-function buildDownloadTargets(version, file) {
- return RELEASE_REPOS.map(({ repo, label }) => ({
- label,
- url: `https://github.com/${repo}/releases/download/v${version}/${file}`,
- }));
-}
-
-async function downloadReleaseAsset(downloadTargets, destPath) {
- let lastError = null;
-
- for (const target of downloadTargets) {
- if (existsSync(destPath)) {
- unlinkSync(destPath);
- }
-
- console.log(`Downloading loct release asset from ${target.url} (${target.label})...`);
-
- try {
- await downloadFile(target.url, destPath);
- return target;
- } catch (error) {
- lastError = error;
- console.warn(`Download failed from ${target.label}: ${error.message}`);
- }
- }
-
- throw lastError || new Error('No download targets available');
-}
-
-async function install() {
- const packageName = require('./package.json').name;
- const mapping = BINARY_MAPPINGS[packageName];
-
- if (!mapping) {
- console.error(`Unknown package: ${packageName}`);
- process.exit(1);
- }
-
- const { file, target } = mapping;
- const downloadTargets = buildDownloadTargets(VERSION, file);
- const targetPath = join(__dirname, target);
- const archivePath = join(__dirname, file);
-
- // Skip if already exists
- if (existsSync(targetPath)) {
- console.log(`Binary already exists at ${targetPath}`);
- return;
- }
-
- try {
- const downloadedFrom = await downloadReleaseAsset(downloadTargets, archivePath);
-
- if (file.endsWith('.tar.gz')) {
- execSync(`tar -xzf "${archivePath}" -C "${__dirname}"`, { stdio: 'inherit' });
- } else if (file.endsWith('.zip')) {
- if (process.platform === 'win32') {
- execSync(
- `powershell -Command "Expand-Archive -Path '${archivePath}' -DestinationPath '${__dirname}' -Force"`,
- { stdio: 'inherit' }
- );
- } else {
- execSync(`unzip -o "${archivePath}" -d "${__dirname}"`, { stdio: 'inherit' });
- }
- }
-
- if (existsSync(archivePath)) {
- unlinkSync(archivePath);
- }
-
- // Make executable (Unix-like systems)
- if (process.platform !== 'win32') {
- chmodSync(targetPath, 0o755);
- }
-
- console.log(`Successfully installed loct binary to ${targetPath} via ${downloadedFrom.label}`);
- } catch (error) {
- console.error(`Failed to download loct binary: ${error.message}`);
- console.error('Attempted URLs:');
- downloadTargets.forEach((target) => console.error(`- ${target.url}`));
- console.error('');
- console.error('Possible solutions:');
- console.error('1. Check your internet connection');
- console.error('2. Verify the matching release assets exist on GitHub');
- console.error('3. Install loct manually from the thin release repo: https://github.com/Loctree/loct/releases');
- console.error('4. If the thin repo is still missing the asset, try the monorepo fallback: https://github.com/Loctree/loctree-ast/releases');
- process.exit(1);
- }
-}
-
-install();
diff --git a/distribution/npm/platform-support.js b/distribution/npm/platform-support.js
deleted file mode 100644
index 63742719..00000000
--- a/distribution/npm/platform-support.js
+++ /dev/null
@@ -1,112 +0,0 @@
-const SUPPORTED_NPM_TARGETS = Object.freeze([
- {
- key: 'darwin-arm64',
- packageName: '@loctree/darwin-arm64',
- label: 'macOS Apple Silicon (ARM64)',
- },
- {
- key: 'darwin-x64',
- packageName: '@loctree/darwin-x64',
- label: 'macOS Intel (x64)',
- },
- {
- key: 'linux-x64-gnu',
- packageName: '@loctree/linux-x64-gnu',
- label: 'Linux x64 (glibc)',
- },
- {
- key: 'win32-x64-msvc',
- packageName: '@loctree/win32-x64-msvc',
- label: 'Windows x64',
- },
-]);
-
-const PLATFORM_PACKAGES = Object.freeze(
- Object.fromEntries(
- SUPPORTED_NPM_TARGETS.map((target) => [target.key, target.packageName]),
- ),
-);
-
-function normalizeArch(arch) {
- const archMap = {
- x64: 'x64',
- arm64: 'arm64',
- aarch64: 'arm64',
- };
-
- return archMap[arch] || arch;
-}
-
-function isMuslLibc(spawnSyncImpl) {
- const spawnSync = spawnSyncImpl || require('child_process').spawnSync;
- try {
- const lddVersion = spawnSync('ldd', ['--version'], { encoding: 'utf8' });
- return Boolean(lddVersion.stderr && lddVersion.stderr.includes('musl'));
- } catch (_err) {
- return false;
- }
-}
-
-function resolvePlatformKey(options = {}) {
- const platform = options.platform || process.platform;
- const arch = options.arch || process.arch;
- const normalizedArch = normalizeArch(arch);
-
- if (platform === 'linux') {
- const libcVariant = options.libcVariant || (isMuslLibc(options.spawnSync) ? 'musl' : 'gnu');
- return `${platform}-${normalizedArch}-${libcVariant}`;
- }
-
- if (platform === 'win32') {
- return `${platform}-${normalizedArch}-msvc`;
- }
-
- if (platform === 'darwin') {
- return `${platform}-${normalizedArch}`;
- }
-
- return null;
-}
-
-function getPackageNameForPlatformKey(platformKey) {
- return PLATFORM_PACKAGES[platformKey] || null;
-}
-
-function supportedTargetSummary() {
- return SUPPORTED_NPM_TARGETS.map((target) => target.label).join(', ');
-}
-
-function unsupportedPlatformMessage(options = {}) {
- const platform = options.platform || process.platform;
- const arch = options.arch || process.arch;
- const platformKey = options.platformKey || resolvePlatformKey({ platform, arch });
- const subject = platformKey || `${platform}-${normalizeArch(arch)}`;
-
- const lines = [
- `No npm package is published for platform: ${subject}.`,
- `Supported npm targets: ${supportedTargetSummary()}.`,
- ];
-
- if (subject === 'linux-x64-musl') {
- lines.push(
- 'Linux musl/Alpine is not packaged on npm yet. Use `cargo install --locked loctree`, a direct release asset, or another supported install channel.',
- );
- } else {
- lines.push(
- 'Use `cargo install --locked loctree`, a direct release asset, or another supported install channel instead.',
- );
- }
-
- return lines.join(' ');
-}
-
-module.exports = {
- SUPPORTED_NPM_TARGETS,
- PLATFORM_PACKAGES,
- getPackageNameForPlatformKey,
- isMuslLibc,
- normalizeArch,
- resolvePlatformKey,
- supportedTargetSummary,
- unsupportedPlatformMessage,
-};
diff --git a/distribution/npm/scripts/publish-all.sh b/distribution/npm/scripts/publish-all.sh
deleted file mode 100755
index 64d0cc66..00000000
--- a/distribution/npm/scripts/publish-all.sh
+++ /dev/null
@@ -1,136 +0,0 @@
-#!/bin/bash
-# Automated publishing script for loctree npm packages
-
-set -e
-
-VERSION=${1:-$(node -p "require('../package.json').version")}
-DRY_RUN=${DRY_RUN:-false}
-
-echo "=== loctree npm Publishing Script ==="
-echo "Version: $VERSION"
-echo "Dry run: $DRY_RUN"
-echo ""
-
-# Colors for output
-RED='\033[0;31m'
-GREEN='\033[0;32m'
-YELLOW='\033[1;33m'
-NC='\033[0m' # No Color
-
-# Check if we're logged in to npm
-if ! npm whoami &> /dev/null; then
- echo -e "${RED}Error: Not logged in to npm${NC}"
- echo "Run: npm login"
- exit 1
-fi
-
-NPM_USER=$(npm whoami)
-echo -e "${GREEN}Logged in as: $NPM_USER${NC}"
-echo ""
-
-# Function to publish a package
-publish_package() {
- local package_dir=$1
- local package_name=$2
-
- echo -e "${YELLOW}Publishing $package_name...${NC}"
-
- cd "$package_dir"
-
- if [ "$DRY_RUN" = true ]; then
- echo " [DRY RUN] Would publish: $package_name"
- npm pack --dry-run
- else
- npm publish --access public
- echo -e "${GREEN} ✓ Published $package_name${NC}"
- fi
-
- cd - > /dev/null
- echo ""
-}
-
-# Step 1: Verify GitHub releases
-echo "Step 1: Verifying GitHub releases..."
-RELEASE_URL="https://github.com/Loctree/loct/releases/tag/v$VERSION"
-
-if command -v curl &> /dev/null; then
- if curl -s -o /dev/null -w "%{http_code}" "$RELEASE_URL" | grep -q "200"; then
- echo -e "${GREEN} ✓ Release v$VERSION exists${NC}"
- else
- echo -e "${RED} ✗ Release v$VERSION not found at $RELEASE_URL${NC}"
- echo " Create the release first, then try again"
- exit 1
- fi
-else
- echo -e "${YELLOW} ⚠ curl not found, skipping release verification${NC}"
-fi
-echo ""
-
-# Step 2: Create platform packages
-echo "Step 2: Creating platform packages..."
-if [ -x ./CREATE_PLATFORM_PACKAGES.sh ]; then
- ./CREATE_PLATFORM_PACKAGES.sh "$VERSION"
-else
- echo -e "${YELLOW} ⚠ CREATE_PLATFORM_PACKAGES.sh not found or not executable${NC}"
-fi
-echo ""
-
-# Step 3: Publish platform packages
-echo "Step 3: Publishing platform packages..."
-
-PLATFORMS=(
- "darwin-arm64:@loctree/darwin-arm64"
- "darwin-x64:@loctree/darwin-x64"
- "linux-x64-gnu:@loctree/linux-x64-gnu"
- "win32-x64-msvc:@loctree/win32-x64-msvc"
-)
-
-for platform_spec in "${PLATFORMS[@]}"; do
- IFS=: read -r platform_dir package_name <<< "$platform_spec"
- publish_package "platform-packages/$platform_dir" "$package_name"
-done
-
-# Step 4: Wait for packages to propagate
-if [ "$DRY_RUN" = false ]; then
- echo "Step 4: Waiting for packages to propagate..."
- echo " Sleeping for 30 seconds to ensure npm registry is updated..."
- sleep 30
- echo ""
-fi
-
-# Step 5: Publish main package
-echo "Step 5: Publishing main package..."
-publish_package "." "loctree"
-
-# Step 6: Verify installation
-if [ "$DRY_RUN" = false ]; then
- echo "Step 6: Verifying installation..."
-
- TEST_DIR=$(mktemp -d)
- cd "$TEST_DIR"
-
- echo " Testing in: $TEST_DIR"
- npm init -y > /dev/null
- npm install loctree
-
- if npx loct --version; then
- echo -e "${GREEN} ✓ Installation verified successfully${NC}"
- else
- echo -e "${RED} ✗ Installation verification failed${NC}"
- exit 1
- fi
-
- cd - > /dev/null
- rm -rf "$TEST_DIR"
-fi
-
-echo ""
-echo -e "${GREEN}=== Publishing Complete! ===${NC}"
-echo ""
-echo "Next steps:"
-echo "1. Test installation on different platforms"
-echo "2. Update documentation if needed"
-echo "3. Announce the release"
-echo ""
-echo "Test installation with:"
-echo " npm install loctree@$VERSION"
diff --git a/distribution/npm/sync-version.mjs b/distribution/npm/sync-version.mjs
deleted file mode 100644
index dda520cd..00000000
--- a/distribution/npm/sync-version.mjs
+++ /dev/null
@@ -1,35 +0,0 @@
-import fs from "node:fs";
-import path from "node:path";
-import { fileURLToPath } from "node:url";
-
-const version = process.argv[2];
-
-if (!version) {
- console.error("Usage: node distribution/npm/sync-version.mjs ");
- process.exit(1);
-}
-
-const scriptDir = path.dirname(fileURLToPath(import.meta.url));
-const root = scriptDir;
-const mainPackagePath = path.join(root, "package.json");
-const mainPackage = JSON.parse(fs.readFileSync(mainPackagePath, "utf8"));
-
-mainPackage.version = version;
-for (const dep of Object.keys(mainPackage.optionalDependencies ?? {})) {
- mainPackage.optionalDependencies[dep] = version;
-}
-fs.writeFileSync(mainPackagePath, `${JSON.stringify(mainPackage, null, 2)}\n`);
-
-const platformRoot = path.join(root, "platform-packages");
-if (fs.existsSync(platformRoot)) {
- for (const entry of fs.readdirSync(platformRoot, { withFileTypes: true })) {
- if (!entry.isDirectory()) continue;
- const pkgPath = path.join(platformRoot, entry.name, "package.json");
- if (!fs.existsSync(pkgPath)) continue;
- const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
- pkg.version = version;
- fs.writeFileSync(pkgPath, `${JSON.stringify(pkg, null, 2)}\n`);
- }
-}
-
-console.log(`distribution/npm synced to ${version}`);
diff --git a/distribution/npm/test/platform-support.test.js b/distribution/npm/test/platform-support.test.js
deleted file mode 100644
index 5b8aad95..00000000
--- a/distribution/npm/test/platform-support.test.js
+++ /dev/null
@@ -1,120 +0,0 @@
-const test = require('node:test');
-const assert = require('node:assert/strict');
-const fs = require('node:fs');
-const os = require('node:os');
-const path = require('node:path');
-
-const packageJson = require('../package.json');
-const {
- SUPPORTED_NPM_TARGETS,
- getPackageNameForPlatformKey,
- resolvePlatformKey,
- unsupportedPlatformMessage,
-} = require('../platform-support');
-const { execLoctree, execLoctreeSync, getBinaryPath } = require('../index');
-
-test('darwin x64 resolves to a published npm package', () => {
- const platformKey = resolvePlatformKey({ platform: 'darwin', arch: 'x64' });
- assert.equal(platformKey, 'darwin-x64');
- assert.equal(getPackageNameForPlatformKey(platformKey), '@loctree/darwin-x64');
-});
-
-test('musl platforms return an actionable unsupported-platform message', () => {
- const message = unsupportedPlatformMessage({
- platform: 'linux',
- arch: 'x64',
- platformKey: 'linux-x64-musl',
- });
-
- assert.match(message, /Linux musl\/Alpine is not packaged on npm yet/);
- assert.match(message, /cargo install --locked loctree/);
-});
-
-test('main npm package optionalDependencies match supported targets', () => {
- const supportedPackages = SUPPORTED_NPM_TARGETS.map((target) => target.packageName).sort();
- const optionalDependencies = Object.keys(packageJson.optionalDependencies).sort();
-
- assert.deepEqual(optionalDependencies, supportedPackages);
-});
-
-test('platform postinstall scripts fall back from thin repo to monorepo release assets', () => {
- const repoRoot = path.resolve(__dirname, '..');
- const templatePath = path.join(repoRoot, 'platform-packages', 'postinstall.js');
- const templateSource = fs.readFileSync(templatePath, 'utf8');
-
- assert.match(templateSource, /Loctree\/loct/);
- assert.match(templateSource, /Loctree\/loctree-ast/);
- assert.match(templateSource, /Attempted URLs:/);
-
- for (const target of SUPPORTED_NPM_TARGETS) {
- const packageDir = target.packageName.replace('@loctree/', '');
- const packagePath = path.join(repoRoot, 'platform-packages', packageDir, 'postinstall.js');
- const packageSource = fs.readFileSync(packagePath, 'utf8');
-
- assert.equal(packageSource, templateSource, `${packageDir} postinstall.js drifted from template`);
- }
-});
-
-test('npm API captures stdout for programmatic calls', async (t) => {
- const platformKey = resolvePlatformKey({
- platform: process.platform,
- arch: process.arch,
- libcVariant: 'gnu',
- });
- const packageName = getPackageNameForPlatformKey(platformKey);
-
- if (!packageName) {
- t.skip(`Current platform is not supported by the npm package: ${process.platform}-${process.arch}`);
- return;
- }
-
- const repoRoot = path.resolve(__dirname, '..');
- const binaryName = process.platform === 'win32' ? 'loct.exe' : 'loct';
- const binaryDir = path.join(repoRoot, 'node_modules', packageName);
- const binaryPath = path.join(binaryDir, binaryName);
- const hadOriginalBinary = fs.existsSync(binaryPath);
- const originalBinary = hadOriginalBinary ? fs.readFileSync(binaryPath) : null;
-
- fs.mkdirSync(binaryDir, { recursive: true });
-
- if (process.platform === 'win32') {
- fs.writeFileSync(
- binaryPath,
- '@echo off\r\nif "%~1"=="--version" (echo loct test-version) else (echo %*)\r\n',
- 'utf8',
- );
- } else {
- fs.writeFileSync(
- binaryPath,
- '#!/usr/bin/env node\n' +
- 'if (process.argv[2] === "--version") {\n' +
- ' process.stdout.write("loct test-version\\n");\n' +
- '} else {\n' +
- ' process.stdout.write(process.argv.slice(2).join(" "));\n' +
- '}\n',
- 'utf8',
- );
- fs.chmodSync(binaryPath, 0o755);
- }
-
- t.after(() => {
- if (hadOriginalBinary && originalBinary) {
- fs.writeFileSync(binaryPath, originalBinary);
- if (process.platform !== 'win32') {
- fs.chmodSync(binaryPath, 0o755);
- }
- return;
- }
-
- fs.rmSync(path.join(repoRoot, 'node_modules'), { recursive: true, force: true });
- });
-
- assert.equal(getBinaryPath(), binaryPath);
-
- const stdout = execLoctree(['alpha', 'beta']);
- assert.equal(Buffer.isBuffer(stdout), true);
- assert.equal(stdout.toString('utf8'), 'alpha beta');
-
- const version = execLoctreeSync(['--version']);
- assert.equal(version.trim(), 'loct test-version');
-});
diff --git a/distribution/windows/README.md b/distribution/windows/README.md
deleted file mode 100644
index 5086afd8..00000000
--- a/distribution/windows/README.md
+++ /dev/null
@@ -1,9 +0,0 @@
-# Windows
-
-Windows distribution is release-asset first:
-
-- zipped `loctree.exe` and `loct.exe`
-- npm wrapper only for targets we actually build in CI
-
-If we add winget later, it should join this tree rather than becoming another
-root-level ritual.
diff --git a/docs/01_homebrew_release.md b/docs/01_homebrew_release.md
deleted file mode 100644
index 02ea6f67..00000000
--- a/docs/01_homebrew_release.md
+++ /dev/null
@@ -1,79 +0,0 @@
-# Homebrew Release Architecture
-
-Loctree no longer treats `homebrew-core` as the primary install path.
-
-The shipping architecture is now:
-
-- source + CI + versioning: `Loctree/loctree-ast`
-- CLI binary releases: `Loctree/loct`
-- MCP binary releases: `Loctree/loctree-mcp`
-- CLI tap: `Loctree/homebrew-cli`
-- MCP tap: `Loctree/homebrew-mcp`
-
-## User-Facing Commands
-
-```bash
-brew install loctree/cli/loct
-brew install loctree/mcp/loctree-mcp
-```
-
-## Why This Shape
-
-- The monorepo stays focused on code and CI instead of serving as a public asset bucket.
-- CLI and MCP now have separate binary channels, which keeps install paths honest.
-- Homebrew formulas can target exactly one product each.
-- Release automation becomes deterministic: build once in the monorepo, distribute outward.
-
-## Release Sequence
-
-The human trigger remains the same:
-
-```bash
-make version TYPE=minor TAG=1 PUSH=1
-```
-
-That tag push triggers:
-
-1. crate publishing in `Loctree/loctree-ast`
-2. binary builds for CLI and MCP
-3. asset upload to `Loctree/loct` and `Loctree/loctree-mcp`
-4. npm publish from `distribution/npm`
-5. monorepo release publication
-6. Homebrew tap sync into `Loctree/homebrew-cli` and `Loctree/homebrew-mcp`
-
-## Homebrew Formula Source of Truth
-
-The formulas are rendered by:
-
-```bash
-scripts/render-homebrew-formula.sh
-```
-
-The workflow computes release SHA256 checksums from the thin repos and writes the
-resulting files directly into the tap repos. The tap repos should not maintain
-hand-edited version drift.
-
-## First Release Bootstrap
-
-Before the first release on this layout, create these GitHub repositories:
-
-- `Loctree/loct`
-- `Loctree/loctree-mcp`
-- `Loctree/homebrew-cli`
-- `Loctree/homebrew-mcp`
-
-Also configure `HOMEBREW_GITHUB_API_TOKEN` in `Loctree/loctree-ast` with write access
-to all four repositories.
-
-## Supported Homebrew Targets
-
-- macOS Apple Silicon
-- macOS Intel
-- Linux x86_64
-
-## Operational Notes
-
-- The monorepo release is an orchestration/changelog release, not the main binary channel.
-- npm should prefer CLI assets from `Loctree/loct`; the monorepo release stays a
- temporary fallback while mirror lag catches up.
-- If a tap sync fails, fix the thin release assets first, then re-run `homebrew-release.yml`.
diff --git a/docs/02_query_mode.md b/docs/02_query_mode.md
deleted file mode 100644
index 2cbdbedc..00000000
--- a/docs/02_query_mode.md
+++ /dev/null
@@ -1,636 +0,0 @@
-# Query Mode - jq-like Codebase Queries
-
-`loct` provides a jq-like interface for querying loctree snapshots. Instead of parsing JSON manually, use familiar filter syntax to extract insights from your codebase analysis.
-
-## Quick Start
-
-### What is Query Mode?
-
-Query mode lets you interrogate loctree snapshots using jq-style filters. Unlike raw jq, `loct` automatically discovers the latest snapshot and understands the codebase schema.
-
-```bash
-# Basic filter - get snapshot metadata
-loct '.metadata'
-
-# Get all file paths
-loct '.files[].path'
-
-# Count dead exports
-loct '.files | map(.exports | map(select(.dead == true))) | flatten | length'
-```
-
-### How it Differs from jq
-
-| Feature | jq | loct query |
-|---------|-----|------------|
-| Snapshot discovery | Manual path | Auto-discovers the latest snapshot from cache (see `LOCT_CACHE_DIR`) |
-| Schema awareness | None | Validates against snapshot schema |
-| Preset queries | None | `@imports`, `@exports`, `@dead`, etc. |
-| Error messages | Generic JSON errors | Codebase-specific hints |
-
-## Usage
-
-```
-loct [OPTIONS]
-loct [OPTIONS] @ [ARGS]
-```
-
-### Arguments
-
-- `` - jq-compatible filter expression
-- `@` - Named preset query (see Preset Queries)
-
-### Examples
-
-```bash
-# Raw filter
-loct '.metadata.languages'
-
-# Preset query
-loct @imports src/utils/auth.ts
-
-# Preset with options
-loct @dead --confidence high
-```
-
-## Filter Syntax
-
-Query mode uses jq filter syntax. For comprehensive jq documentation, see [jq Manual](https://jqlang.github.io/jq/manual/).
-
-### Common Patterns
-
-#### Object Access
-```bash
-# Single field
-loct '.metadata'
-
-# Nested field
-loct '.metadata.git_branch'
-
-# Optional field (no error if missing)
-loct '.metadata.git_repo?'
-```
-
-#### Array Operations
-```bash
-# All elements
-loct '.files[]'
-
-# First element
-loct '.files[0]'
-
-# Slice
-loct '.files[0:10]'
-
-# Length
-loct '.files | length'
-```
-
-#### Filtering
-```bash
-# Select by condition
-loct '.files[] | select(.loc > 500)'
-
-# Select by path pattern
-loct '.files[] | select(.path | contains("components"))'
-
-# Multiple conditions
-loct '.files[] | select(.loc > 100 and .exports | length > 5)'
-```
-
-#### Transformation
-```bash
-# Extract specific fields
-loct '.files[] | {path, loc, language}'
-
-# Map over array
-loct '.files | map(.path)'
-
-# Flatten nested arrays
-loct '.files | map(.exports) | flatten'
-```
-
-#### Aggregation
-```bash
-# Count
-loct '.files | length'
-
-# Sum
-loct '[.files[].loc] | add'
-
-# Group by
-loct '.files | group_by(.language)'
-
-# Sort
-loct '.files | sort_by(.loc) | reverse | .[0:10]'
-```
-
-## Options
-
-### Output Format
-
-| Option | Description |
-|--------|-------------|
-| `-r, --raw-output` | Output strings without JSON quotes |
-| `-c, --compact` | Compact JSON output (single line) |
-
-```bash
-# Get paths as raw strings (one per line)
-loct -r '.files[].path'
-
-# Compact JSON for piping
-loct -c '.metadata' | other-tool
-```
-
-### Variables
-
-| Option | Description |
-|--------|-------------|
-| `--arg NAME VALUE` | Bind `$NAME` to string `VALUE` |
-| `--argjson NAME JSON` | Bind `$NAME` to parsed JSON |
-
-```bash
-# Filter by variable
-loct --arg file "auth.ts" '.files[] | select(.path | endswith($file))'
-
-# Numeric threshold
-loct --argjson threshold 500 '.files[] | select(.loc > $threshold)'
-```
-
-### Snapshot Selection
-
-| Option | Description |
-|--------|-------------|
-| `--snapshot PATH` | Use specific snapshot file instead of auto-discovery |
-
-```bash
-# Use specific snapshot
-loct --snapshot /path/to/snapshot.json '.metadata'
-
-# Compare two snapshots
-diff <(loct --snapshot old.json '.files | length') \
- <(loct --snapshot new.json '.files | length')
-```
-
-### Exit Status
-
-| Option | Description |
-|--------|-------------|
-| `-e, --exit-status` | Set exit code based on result |
-
-```bash
-# Exit 1 if no dead exports found (for CI)
-loct -e '.files | map(.exports) | flatten | map(select(.dead)) | length > 0'
-```
-
-## Preset Queries
-
-Presets are optimized queries for common operations. They handle edge cases and provide better output formatting.
-
-### @imports - Find Importers
-
-Find all files that import a given file (follows re-export chains).
-
-```bash
-loct @imports
-```
-
-**Examples:**
-```bash
-# Who imports this component?
-loct @imports src/components/Button.tsx
-
-# Raw output for scripting
-loct @imports src/utils/auth.ts -r
-
-# JSON for AI agents
-loct @imports src/hooks/usePatient.ts --json
-```
-
-**Output:**
-```json
-{
- "target": "src/components/Button.tsx",
- "importers": [
- { "file": "src/App.tsx", "line": 5, "via": "import" },
- { "file": "src/pages/Home.tsx", "line": 12, "via": "reexport" }
- ],
- "count": 2
-}
-```
-
-### @exports - List Exports
-
-List all symbols exported by a file.
-
-```bash
-loct @exports
-```
-
-**Examples:**
-```bash
-# What does this file export?
-loct @exports src/utils/helpers.ts
-
-# Just the names
-loct @exports src/api/index.ts -r | sort
-```
-
-**Output:**
-```json
-{
- "file": "src/utils/helpers.ts",
- "exports": [
- { "name": "formatDate", "kind": "function", "line": 10, "dead": false },
- { "name": "parseId", "kind": "function", "line": 25, "dead": true }
- ],
- "count": 2
-}
-```
-
-### @dead - Unused Exports
-
-Find exports with no importers (dead code candidates).
-
-```bash
-loct @dead [OPTIONS]
-```
-
-**Options:**
-- `--confidence ` - Filter by confidence: `high`, `normal` (default), `low`
-- `--path ` - Filter by file path pattern
-- `--limit ` - Limit results (default: 20)
-
-**Examples:**
-```bash
-# All dead exports
-loct @dead
-
-# High confidence only (safer to remove)
-loct @dead --confidence high
-
-# Dead exports in specific directory
-loct @dead --path "components/"
-
-# JSON output with full details
-loct @dead --json
-```
-
-**Output:**
-```json
-{
- "dead_exports": [
- {
- "file": "src/utils/legacy.ts",
- "name": "oldHelper",
- "line": 42,
- "confidence": "high",
- "reason": "No imports found, not in entry point"
- }
- ],
- "count": 1
-}
-```
-
-### @cycles - Circular Imports
-
-Find circular import chains.
-
-```bash
-loct @cycles [OPTIONS]
-```
-
-**Options:**
-- `--path ` - Filter cycles involving this path
-- `--min-length ` - Minimum cycle length to report
-
-**Examples:**
-```bash
-# All cycles
-loct @cycles
-
-# Cycles involving auth
-loct @cycles --path "auth"
-
-# Only complex cycles (3+ files)
-loct @cycles --min-length 3
-```
-
-**Output:**
-```json
-{
- "cycles": [
- {
- "files": ["src/a.ts", "src/b.ts", "src/c.ts"],
- "length": 3,
- "severity": "warning"
- }
- ],
- "count": 1
-}
-```
-
-### @who-imports - Transitive Importers
-
-Find all files that depend on a file (transitive closure).
-
-```bash
-loct @who-imports
-```
-
-**Examples:**
-```bash
-# Blast radius of a change
-loct @who-imports src/core/types.ts
-
-# Count affected files
-loct @who-imports src/api/client.ts | jq '.count'
-```
-
-### @where-symbol - Symbol Lookup
-
-Find where a symbol is defined.
-
-```bash
-loct @where-symbol
-```
-
-**Examples:**
-```bash
-# Find definition of a function
-loct @where-symbol useAuth
-
-# Find all files exporting a name
-loct @where-symbol Button --all
-```
-
-### @barrels - Barrel File Analysis
-
-Analyze barrel files (index.ts re-exports).
-
-```bash
-loct @barrels [OPTIONS]
-```
-
-**Options:**
-- `--deep` - Show deep re-export chains
-- `--missing` - Show directories without barrels
-
-**Examples:**
-```bash
-# List all barrels
-loct @barrels
-
-# Find barrel chains
-loct @barrels --deep
-```
-
-### @commands - Tauri Command Bridges
-
-List Tauri FE/BE command mappings.
-
-```bash
-loct @commands [OPTIONS]
-```
-
-**Options:**
-- `--missing` - Only show missing handlers
-- `--unused` - Only show unused handlers
-- `--name ` - Filter by command name
-
-**Examples:**
-```bash
-# All commands
-loct @commands
-
-# Missing handlers (FE calls without BE impl)
-loct @commands --missing
-
-# Filter by name
-loct @commands --name "auth"
-```
-
-### @events - Event Bridge Analysis
-
-List event emit/listen pairs.
-
-```bash
-loct @events [OPTIONS]
-```
-
-**Options:**
-- `--orphan` - Show events without listeners
-- `--ghost` - Show listeners without emitters
-
-**Examples:**
-```bash
-# All events
-loct @events
-
-# Orphan events (emitted but never handled)
-loct @events --orphan
-```
-
-## Examples
-
-### Common Workflows
-
-#### Find All Files Importing a Component
-
-```bash
-# Using preset
-loct @imports src/components/Button.tsx
-
-# Using raw filter
-loct '.edges[] | select(.to | endswith("Button.tsx")) | .from'
-```
-
-#### Count Dead Exports by Directory
-
-```bash
-loct '.files | group_by(.path | split("/")[1]) |
- map({
- dir: .[0].path | split("/")[1],
- dead: [.[].exports[] | select(.dead)] | length
- }) |
- sort_by(.dead) | reverse'
-```
-
-#### Find Circular Dependencies Involving a File
-
-```bash
-# Preset
-loct @cycles --path "auth"
-
-# Raw filter
-loct '.cycles[] | select(any(. | contains("auth")))'
-```
-
-#### Get Blast Radius of a File
-
-```bash
-# How many files would be affected by changing this?
-loct @who-imports src/core/types.ts -c | jq '.count'
-
-# List affected files
-loct @who-imports src/api/client.ts -r
-```
-
-#### Export Data for External Tools
-
-```bash
-# CSV of large files
-loct -r '.files[] | select(.loc > 500) | [.path, .loc, .language] | @csv'
-
-# TSV for spreadsheet
-loct -r '.files[] | [.path, .loc] | @tsv' > files.tsv
-
-# Markdown table
-loct '.files | sort_by(.loc) | reverse | .[0:10] |
- ["| File | LOC |", "|------|-----|"] +
- map("| \(.path) | \(.loc) |") | .[]' -r
-```
-
-#### CI Integration
-
-```bash
-# Fail if new dead exports
-loct -e '@dead --confidence high | .count == 0'
-
-# Fail if cycles exist
-loct -e '@cycles | .count == 0'
-
-# Check specific file isn't orphaned
-loct -e '@imports src/utils/helper.ts | .count > 0'
-```
-
-## Snapshot Structure Reference
-
-The snapshot JSON has the following structure:
-
-```json
-{
- "metadata": {
- "schema_version": "0.5.0-rc",
- "generated_at": "2025-01-15T10:30:00Z",
- "roots": ["src", "lib"],
- "languages": ["typescript", "rust"],
- "file_count": 150,
- "total_loc": 25000,
- "scan_duration_ms": 1234,
- "git_repo": "my-app",
- "git_branch": "main",
- "git_commit": "abc1234"
- },
- "files": [
- {
- "path": "src/main.ts",
- "language": "typescript",
- "loc": 150,
- "exports": [
- {
- "name": "main",
- "kind": "function",
- "export_type": "named",
- "line": 10,
- "dead": false
- }
- ],
- "imports": ["./utils", "./config"],
- "tauri_commands": [...],
- "event_emits": [...],
- "event_listens": [...]
- }
- ],
- "edges": [
- {
- "from": "src/app.ts",
- "to": "src/utils.ts",
- "label": "import"
- }
- ],
- "export_index": {
- "Button": ["src/components/Button.tsx"],
- "useAuth": ["src/hooks/useAuth.ts", "src/legacy/auth.ts"]
- },
- "command_bridges": [
- {
- "name": "get_user",
- "frontend_calls": [["src/api.ts", 42]],
- "backend_handler": ["src-tauri/commands.rs", 100],
- "has_handler": true,
- "is_called": true
- }
- ],
- "event_bridges": [
- {
- "name": "user_updated",
- "emits": [["src/user.rs", 50, "emit"]],
- "listens": [["src/App.tsx", 30]]
- }
- ],
- "barrels": [
- {
- "path": "src/components/index.ts",
- "module_id": "src/components",
- "reexport_count": 15,
- "targets": ["src/components/Button.tsx", "..."]
- }
- ]
-}
-```
-
-### Key Fields
-
-| Path | Type | Description |
-|------|------|-------------|
-| `.metadata` | object | Scan metadata (version, git info, stats) |
-| `.files` | array | All analyzed files with exports/imports |
-| `.files[].exports` | array | Symbols exported by the file |
-| `.files[].exports[].dead` | bool | Whether export has no importers |
-| `.edges` | array | Import graph edges (from -> to) |
-| `.export_index` | object | Symbol name -> files mapping |
-| `.command_bridges` | array | Tauri FE/BE command mappings |
-| `.event_bridges` | array | Event emit/listen pairs |
-| `.barrels` | array | Detected barrel files (index.ts) |
-
-## Tips and Tricks
-
-### Combine with Other Tools
-
-```bash
-# Pipe to rg for text search in results
-loct '.files[].path' -r | rg "component"
-
-# Use fzf for interactive selection
-loct '.files[].path' -r | fzf | xargs loct @imports
-
-# Generate AI context
-loct @dead --json | claude "Review these dead exports"
-```
-
-### Performance
-
-```bash
-# Use --snapshot for repeated queries (avoids re-discovery)
-SNAP=$(loct '.metadata.git_scan_id' -r)
-loct --snapshot "/path/to/snapshot.json" '.files | length'
-loct --snapshot "/path/to/snapshot.json" '@dead'
-```
-
-### Debugging
-
-```bash
-# See raw snapshot structure
-loct '.' | head -100
-
-# Check schema version
-loct '.metadata.schema_version'
-
-# Validate snapshot exists
-loct '.metadata' || echo "No snapshot found - run 'loct scan' first"
-```
-
----
-
-Developed by The Loctree Team ⓒ 2025-2026.
diff --git a/docs/03_runtime_apis.md b/docs/03_runtime_apis.md
deleted file mode 100644
index b65a0171..00000000
--- a/docs/03_runtime_apis.md
+++ /dev/null
@@ -1,117 +0,0 @@
-# Runtime API Detection (P1-03)
-
-## Problem
-Node.js ES Module loader hooks and other runtime-invoked APIs are flagged as dead code because they're never statically imported. They're invoked by the runtime environment.
-
-## Solution
-Loctree 0.7.x automatically detects runtime-invoked exports and excludes them from dead code detection.
-
-## Supported Runtime APIs
-
-### Node.js
-- **ES Module loader hooks** (`resolve`, `load`, `globalPreload`, `initialize`)
- - Files: `**/loader.{js,mjs,cjs}`, `**/loaders/*.{js,mjs,cjs}`, `lib/internal/modules/esm/*.js`
- - Usage: `node --experimental-loader=./loader.mjs app.js`
-
-- **Test runner hooks** (`before`, `after`, `beforeEach`, `afterEach`)
- - Files: `**/*.test.{js,mjs,cjs,ts,mts,cts}`
- - Usage: `node --test test-runner.test.js`
-
-### Web APIs
-- **Web Workers** (`onmessage`, `onmessageerror`, `onerror`)
- - Files: `**/*.worker.{js,ts}`
-
-- **Service Workers** (`install`, `activate`, `fetch`, `message`, `sync`, `push`)
- - Files: `**/service-worker.{js,ts}`, `**/sw.{js,ts}`
-
-### Build Tools
-- **Vite plugins** (`config`, `configResolved`, `buildStart`, `buildEnd`)
- - Files: `**/vite.config.{js,ts}`
-
-- **Webpack plugins** (`apply`)
- - Files: `**/webpack.config.{js,ts}`
-
-### Frameworks
-- **Next.js middleware** (`middleware`, `config`)
- - Files: `**/middleware.{js,ts}`
-
-- **Astro** (`getStaticPaths`, `prerender`)
- - Files: `**/*.astro`
-
-## Custom Runtime APIs
-
-Add custom patterns in `.loctree/config.toml`:
-
-```toml
-[[runtime_apis]]
-framework = "Remix"
-exports = ["loader", "action", "meta", "links", "headers"]
-file_patterns = ["**/routes/*.{jsx,tsx}", "**/routes/**/*.{jsx,tsx}"]
-
-[[runtime_apis]]
-framework = "SvelteKit"
-exports = ["load", "actions"]
-file_patterns = ["**/+page.{js,ts}", "**/+layout.{js,ts}", "**/+server.{js,ts}"]
-```
-
-## CLI Flags
-
-### `--include-runtime`
-Include runtime-invoked exports in dead code detection.
-
-Useful for auditing whether your loader hooks/middleware are actually being used.
-
-```bash
-loct dead --include-runtime
-```
-
-Without this flag (default), runtime APIs are automatically excluded from dead detection.
-
-## Example
-
-### Before P1-03 (False Positives)
-```bash
-$ loct dead --path lib/internal/modules/esm
-
-Dead exports (7 false positives):
- hooks.js:15 - resolve (never imported)
- hooks.js:30 - load (never imported)
- hooks.js:45 - globalPreload (never imported)
- hooks.js:58 - initialize (never imported)
-```
-
-### After P1-03 (Zero False Positives)
-```bash
-$ loct dead --path lib/internal/modules/esm
-
-No dead exports found.
-
-Runtime-invoked APIs (excluded by default):
- hooks.js:15 - resolve (Node.js ES Module loader hook)
- hooks.js:30 - load (Node.js ES Module loader hook)
- hooks.js:45 - globalPreload (Node.js ES Module loader hook)
- hooks.js:58 - initialize (Node.js ES Module loader hook)
-
-Use --include-runtime to check if these hooks are actually being used.
-```
-
-## Impact
-- **Before**: 7 false positives on Node.js codebase
-- **After**: 0 false positives
-- **Accuracy**: 100% reduction in false positive rate for runtime APIs
-
-## Test Fixtures
-See `tools/fixtures/nodejs-loader/` for working examples:
-- `loader.mjs` - ES Module loader hooks
-- `test-runner.test.js` - Test runner hooks
-- `.loctree/config.toml` - Custom runtime API configuration
-
-## Implementation
-- Registry: `loctree_rs/src/analyzer/dead_parrots/runtime_apis.rs`
-- Detection: `loctree_rs/src/analyzer/dead_parrots/mod.rs:650-658`
-- Config: `loctree_rs/src/config.rs:23`
-- Tests: `loctree_rs/src/analyzer/dead_parrots/mod.rs:1934-2077`
-
----
-
-𝚅𝚒𝚋𝚎𝚌𝚛𝚊𝚏𝚝𝚎𝚍. with AI Agents ⓒ 2025-2026 Loctree Team
diff --git a/docs/README.md b/docs/README.md
deleted file mode 100644
index 06201f7b..00000000
--- a/docs/README.md
+++ /dev/null
@@ -1,330 +0,0 @@
-# loctree Documentation
-
-AI-oriented codebase analyzer for detecting dead code, circular imports, and generating dependency graphs.
-
-**Workspace version:** 0.8.17
-**CLI command:** `loct` (with `loctree` kept as a compatibility alias)
-
----
-
-## Quick Links
-
-- [Getting Started](getting-started.md)
-- [CLI Commands](cli/commands.md)
-- [CLI Options](cli/options.md)
-- [Perception over Memory](../PERCEPTION.md)
-- [Perception ADR](perception/adr.md)
-- [Agent Context KPIs](perception/kpis.md)
-- [Perception Research](perception/research.md)
-- [Loctree Map + Vision](research/loctree-codebase-map-and-perception-first-vision-2026-02-17.md)
-- [IDE Integration](#ide-integration)
-- [AI Agent Integration](#ai-agent-integration)
-- [CI/CD Integration](integrations/ci-cd.md)
-- [Use Cases](use-cases/README.md)
-- [Advanced Topics](#advanced)
-
----
-
-## Getting Started
-
-### Installation
-
-```bash
-# Fastest public path: CLI + MCP server
-curl -fsSL https://loct.io/install.sh | sh
-
-# From crates.io (reproducible lockfile build)
-cargo install --locked loctree loctree-mcp
-
-# CLI-only npm channel
-npm install -g loctree
-
-# From source
-git clone https://github.com/Loctree/loctree-ast.git
-cd loctree-ast
-make install
-```
-
-Public install channels follow the latest published release, which can lag
-behind the workspace version shown in this branch. Verify the exact published
-version on crates.io, npm, or GitHub Releases when you're testing a release
-surface.
-
-### First Scan
-
-```bash
-cd your-project
-loct # Auto-detects stack, writes cached artifacts (see LOCT_CACHE_DIR)
-loct report --serve # Interactive HTML report
-loct --for-ai # AI-optimized hierarchical output
-```
-
-### Essential Commands
-
-```bash
-loct slice # Extract context for AI (deps + consumers)
-loct health # Quick summary: cycles + dead + twins
-loct dead --confidence high # Find unused exports
-loct cycles # Detect circular imports
-loct twins # Semantic duplicates analysis
-```
-
----
-
-## Core Concepts
-
-### Snapshot-Based Analysis
-
-loctree operates on snapshots stored in the artifacts dir (cache dir by default; override via `LOCT_CACHE_DIR`):
-
-- **snapshot.json** - Complete graph data (imports, exports, LOC per file)
-- **findings.json** - All detected issues (dead code, cycles, duplicates)
-- **agent.json** - AI-optimized context bundle
-- **manifest.json** - Index for tooling and AI agents
-
-Scan once with `loct`, then query multiple times without re-parsing.
-
-### Findings Categories
-
-| Finding | Description | Command |
-|---------|-------------|---------|
-| **Dead Parrots** | Exports with 0 imports | `loct dead` |
-| **Cycles** | Circular import chains | `loct cycles` |
-| **Twins** | Semantic duplicates | `loct twins` |
-| **Orphans** | Files with no imports/exports | `loct audit` |
-| **Shadows** | Duplicate symbol definitions | `loct audit` |
-| **Crowds** | Files with excessive connections | `loct audit` |
-
-### Artifacts
-
-All outputs are stored as artifacts in the artifacts dir (cache dir by default; override via `LOCT_CACHE_DIR`):
-
-```bash
-loct # Creates snapshot + findings
-loct report # Generates report.html
-loct '.metadata' # Query snapshot.json directly
-```
-
----
-
-## IDE Integration
-
-> **Available in [loctree-suite](https://github.com/Loctree/loctree-suite)**
-
-Full LSP support for real-time dead code detection, cycle warnings, and code navigation is available through the language server included in loctree-suite.
-
-| Editor | Documentation | Status |
-|--------|---------------|--------|
-| VSCode | [ide/vscode.md](ide/vscode.md) | Ready (suite) |
-| Neovim | [ide/neovim.md](ide/neovim.md) | Ready (suite) |
-| Any LSP client | [ide/lsp-protocol.md](ide/lsp-protocol.md) | Ready (suite) |
-
-### Features
-
-- **Diagnostics** - Dead exports, cycles, twins as warnings
-- **Hover** - Import counts, consumer files
-- **Go to Definition** - Resolve re-export chains
-- **References** - Find all importers
-- **Code Actions** - Quick fixes for dead code
-
----
-
-## AI Agent Integration
-
-### Context Architecture (Default)
-
-For agentic workflows in this repo, the default strategy is **context-over-memory**:
-
-- [Perception over Memory](../PERCEPTION.md)
-- [ADR](perception/adr.md)
-- [KPI definitions](perception/kpis.md)
-- [Research synthesis](perception/research.md)
-
-Guardrail sequence before non-trivial edits:
-`repo-view -> focus -> slice -> impact -> find -> follow`
-
-### MCP Server
-
-loctree provides an MCP (Model Context Protocol) server for AI agents.
-
-**Full documentation:** [integrations/mcp-server.md](integrations/mcp-server.md)
-
-**Location:** `loctree-mcp/`
-**Status:** Production-ready
-
-#### Setup
-
-Add to your MCP config (e.g., Claude Desktop):
-
-```json
-{
- "mcpServers": {
- "loctree": {
- "command": "loctree-mcp",
- "args": []
- }
- }
-}
-```
-
-#### Available Tools
-
-- `repo-view` - Repository overview: files, LOC, languages, health, top hubs
-- `slice` - File context: dependencies + consumers in one call
-- `find` - Symbol search with regex and multi-query support
-- `impact` - Blast radius: direct + transitive consumers
-- `focus` - Module deep-dive: files, internal edges, external deps
-- `tree` - Directory structure with LOC counts
-- `follow` - Pursue signals: dead exports, cycles, twins, hotspots
-
-#### Use Cases
-
-- **Context extraction** - Get relevant code for AI conversations
-- **Duplicate detection** - Find existing components before creating new ones
-- **Impact analysis** - Understand downstream effects of changes
-- **Handler tracing** - Follow Tauri command pipelines
-
-### AI-Optimized Output
-
-```bash
-loct --for-ai # Hierarchical JSON with quick wins
-loct slice --json # Context bundle for AI agents
-```
-
-Output includes:
-- Health score
-- Quick wins (prioritized actions)
-- Hub files (high-connectivity nodes)
-- Dependency chains
-
----
-
-## Advanced
-
-### Architecture
-
-**Core components:**
-- `loctree_rs/` - Main analyzer (Rust)
-- `loctree-mcp/` - MCP server for AI agents
-- `reports/` - HTML report renderer (Leptos SSR)
-- Editor integrations and the LSP server are maintained in [loctree-suite](https://github.com/Loctree/loctree-suite)
-
-**Analysis flow:**
-1. Auto-detect stack (Rust/TS/Python/Dart)
-2. Parse imports/exports (language-specific)
-3. Build dependency graph
-4. Run detectors (dead code, cycles, twins)
-5. Generate artifacts (snapshot, findings, reports)
-
-### Multi-Language Support
-
-| Language | Support | Parser |
-|----------|---------|--------|
-| Rust | Exceptional | Tree-sitter |
-| TypeScript/JavaScript | Full | OXC |
-| Python | Full | Custom |
-| Go | Perfect | Tree-sitter |
-| Dart/Flutter | Full | Tree-sitter |
-| Svelte/Vue | Full | SFC + OXC |
-
-### Query Mode
-
-jq-compatible queries on snapshot data:
-
-```bash
-loct '.metadata' # Extract metadata
-loct '.files | length' # Count files
-loct '.edges[] | select(.from | contains("api"))' # Filter edges
-loct -r '.summary.health_score' # Raw output (no quotes)
-loct -c '.dead_parrots' # Compact JSON
-```
-
-**Options:**
-- `-r, --raw` - Raw output (no JSON quotes)
-- `-c, --compact` - Compact one-line JSON
-- `-e, --exit-status` - Exit 1 if result is false/null
-- `--arg ` - Bind string variable
-- `--argjson ` - Bind JSON variable
-
-### Tauri Integration
-
-Full command pipeline validation:
-
-```bash
-loct commands # Missing/unregistered/unused handlers
-loct trace # Follow FE invoke → BE handler
-loct coverage --handlers # Test coverage for handlers
-```
-
-**Detects:**
-- Missing handlers (frontend invokes non-existent backend)
-- Unregistered handlers (`#[tauri::command]` not in `generate_handler![]`)
-- Unused handlers (backend defined but never called)
-- React.lazy() dynamic imports
-
-### Library Mode
-
-For libraries/frameworks with public APIs:
-
-```bash
-loct --library-mode
-```
-
-**Features:**
-- Auto-detects npm `exports` field
-- Respects Python `__all__` declarations
-- Ignores example/demo directories
-- Excludes public APIs from dead code detection
-
-**Customization:**
-```toml
-# .loctree/config.toml
-library_mode = true
-library_example_globs = ["examples/*", "demos/*", "playground/*"]
-```
-
-### CI Integration
-
-Full documentation: [integrations/ci-cd.md](integrations/ci-cd.md)
-
-```bash
-# Fail build on critical issues
-loct lint --fail
-
-# SARIF output for GitHub/GitLab
-loct lint --sarif > results.sarif
-
-# JSON output for custom processing
-loct health --json
-loct coverage --json
-```
-
-Supports: GitHub Actions, GitLab CI, CircleCI, pre-commit hooks.
-
-### Watch Mode
-
-```bash
-loct watch # Auto-refresh on file changes
-loct watch --serve # Live reload HTML report
-```
-
-### Contributing
-
-See [CONTRIBUTING.md](../CONTRIBUTING.md) for:
-- Development setup
-- Testing guidelines
-- Adding language support
-- Release process
-
----
-
-## Additional Resources
-
-- **Changelog:** [CHANGELOG.md](../CHANGELOG.md)
-- **Main README:** [../README.md](../README.md)
-- **Crates.io:** [loctree](https://crates.io/crates/loctree)
-- **Repository:** [github.com/Loctree/loctree-ast](https://github.com/Loctree/loctree-ast)
-
----
-
-𝚅𝚒𝚋𝚎𝚌𝚛𝚊𝚏𝚝𝚎𝚍. with AI Agents ⓒ 2025-2026 Loctree Team
diff --git a/docs/benchmarks/01_v070_comparative_analysis.md b/docs/benchmarks/01_v070_comparative_analysis.md
deleted file mode 100644
index df035317..00000000
--- a/docs/benchmarks/01_v070_comparative_analysis.md
+++ /dev/null
@@ -1,224 +0,0 @@
-# Loctree 0.7.0 Comparative Analysis
-
-> Benchmark date: 2025-12-16
-> Version: loctree 0.7.0-dev
-> Platform: macOS Darwin 25.2.0 (Apple Silicon)
-
----
-
-## Executive Summary
-
-| Metric | Vista (large) | Loctree (medium) |
-|--------|---------------|------------------|
-| Files analyzed | 1,359 | 213 |
-| Lines of code | 254,361 | 97,621 |
-| Scan time | **24.3s** | **3.0s** |
-| Health score | 78/100 | 80/100 |
-| Throughput | 10,468 LOC/s | 32,540 LOC/s |
-
----
-
-## Test Projects
-
-### Vista (Production App)
-- **Type**: Tauri desktop app (TypeScript + Rust)
-- **Size**: 12GB repository, 1,359 source files
-- **Languages**: TypeScript, TSX, Rust, CSS
-- **Complexity**: Real-world PIMS veterinary application
-
-### Loctree (Self-analysis)
-- **Type**: Rust CLI tool with multiple crates
-- **Size**: 45GB repository (includes target/), 213 source files
-- **Languages**: Rust, TypeScript, Python
-- **Complexity**: Multi-language analyzer dogfooding itself
-
----
-
-## Performance Benchmarks
-
-### Full Scan (--fresh)
-
-| Project | Wall time | User time | System time | CPU % |
-|---------|-----------|-----------|-------------|-------|
-| Vista | 24.317s | 19.75s | 3.52s | 95% |
-| Loctree | 3.006s | 1.74s | 0.95s | 89% |
-
-### Throughput Analysis
-
-```
-Vista: 254,361 LOC / 24.3s = 10,468 LOC/second
-Loctree: 97,621 LOC / 3.0s = 32,540 LOC/second
-```
-
-Smaller projects have better cache locality and less I/O overhead.
-
----
-
-## Code Health Analysis
-
-### Vista Results
-
-```json
-{
- "files": 1359,
- "loc": 254361,
- "health_score": 78,
- "dead_parrots": 0,
- "shadow_exports": 0,
- "duplicate_groups": 160,
- "cycles": {
- "breaking": 2,
- "structural": 0,
- "diamond": 1
- }
-}
-```
-
-**Interpretation**:
-- Health score 78/100 - good overall health
-- 2 breaking cycles - need attention
-- 160 duplicate symbol groups - some consolidation opportunity
-- No dead exports detected (clean codebase)
-
-### Loctree Results
-
-```json
-{
- "files": 213,
- "loc": 97621,
- "health_score": 80,
- "dead_parrots": 4,
- "shadow_exports": 0,
- "duplicate_groups": 68,
- "cycles": {
- "breaking": 0,
- "structural": 0,
- "diamond": 1
- }
-}
-```
-
-**Interpretation**:
-- Health score 80/100 - slightly better than Vista
-- 4 dead exports in reports/wasm (acceptable for WASM bindings)
-- No breaking cycles - clean dependency graph
-- 68 duplicate groups (common names across crates)
-
----
-
-## Artifact Generation
-
-### New in 0.7.0
-
-| Artifact | Vista | Loctree | Purpose |
-|----------|-------|---------|---------|
-| findings.json | 67 KB | 31 KB | Consolidated issues |
-| manifest.json | ~1 KB | ~1 KB | AI/tooling index |
-| snapshot.json | ~2 MB | ~500 KB | Full graph data |
-| report.html | ~150 KB | ~80 KB | Human-readable report |
-| report.sarif | ~50 KB | ~20 KB | IDE integration |
-
----
-
-## Command Performance
-
-### Alias Resolution (0.7.0 feature)
-
-| Command | Alias | Time |
-|---------|-------|------|
-| `loct slice` | `loct s` | <50ms |
-| `loct find` | `loct f` | <50ms |
-| `loct health` | `loct h` | <100ms |
-| `loct dead` | `loct d` | <100ms |
-| `loct doctor` | - | ~500ms |
-
-### Output Modes (0.7.0 feature)
-
-| Flag | Output | Use case |
-|------|--------|----------|
-| `--summary` | JSON to stdout | CI/scripts |
-| `--findings` | JSON to stdout | AI agents |
-| `--for-ai` | agent.json to stdout | Context loading |
-
----
-
-## Comparison: 0.6.x vs 0.7.0
-
-### Mental Model
-
-| Aspect | 0.6.x | 0.7.0 |
-|--------|-------|-------|
-| Commands | 20+ separate | SCAN → QUERY → OUTPUT |
-| Learning curve | Steep | Gentle |
-| AI agent success | ~40% | ~90% (estimated) |
-| Piping support | Partial | Full (stdout modes) |
-
-### New Features in 0.7.0
-
-1. **Artifact-first architecture**
- - findings.json consolidates all issues
- - manifest.json guides AI agents
- - Predictable output locations
-
-2. **Deprecation layer**
- - Old commands still work
- - Clear migration messages
- - No breaking changes (yet)
-
-3. **Short aliases**
- - `s`, `f`, `d`, `c`, `t`, `h`, `i`, `q`
- - Faster interactive use
-
-4. **Doctor command**
- - Unified diagnostics
- - Auto-fixable vs needs-review
- - Suppression suggestions
-
----
-
-## Recommendations
-
-### For Large Codebases (>100k LOC)
-
-- Use `--fresh` sparingly (cache is effective)
-- Use `--summary` for quick checks
-- Consider `.loctignore` for vendor directories
-
-### For AI Agents
-
-```bash
-# Step 1: Read the index
-cat .loctree/manifest.json
-
-# Step 2: Get issues
-loct --findings | jq '.dead_parrots'
-
-# Step 3: Context for specific file
-loct slice src/problematic-file.ts
-```
-
-### For CI/CD
-
-```bash
-# Health check with threshold
-loct --summary | jq -e '.health_score >= 70'
-
-# Fail on breaking cycles
-loct --summary | jq -e '.cycles.breaking == 0'
-```
-
----
-
-## Conclusion
-
-Loctree 0.7.0 delivers:
-- **3x simpler mental model** (SCAN → QUERY → OUTPUT)
-- **Consistent performance** (~10-30k LOC/second)
-- **AI-ready artifacts** (manifest.json, findings.json)
-- **Backward compatibility** with deprecation warnings
-
-Ready for production use on codebases up to 500k+ LOC.
-
----
-
-𝚅𝚒𝚋𝚎𝚌𝚛𝚊𝚏𝚝𝚎𝚍. with AI Agents ⓒ 2025-2026 Loctree Team
diff --git a/docs/ci/README.md b/docs/ci/README.md
deleted file mode 100644
index 115f4e9d..00000000
--- a/docs/ci/README.md
+++ /dev/null
@@ -1,104 +0,0 @@
-# Loctree CI/CD Integration
-
-> Artifact-first structural analysis for your CI pipeline
-
-## Quick Start
-
-Add this badge to your README:
-
-```markdown
-[](https://github.com/Loctree/loctree-ast)
-```
-
-Result: [](https://github.com/Loctree/loctree-ast)
-
-## GitHub Actions Workflow
-
-### Minimal (Python/JS/TS projects)
-
-```yaml
-name: Loctree
-on: [push, pull_request]
-
-jobs:
- analyze:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
- - uses: dtolnay/rust-toolchain@stable
- - run: cargo install loctree --locked
- # Write artifacts into the workspace (easy to upload/jq in CI)
- - run: LOCT_CACHE_DIR=.loctree loct auto
- - run: |
- HEALTH=$(jq -r '.summary.health_score' .loctree/agent.json)
- echo "Health: $HEALTH/100"
- [ "$HEALTH" -lt 50 ] && exit 1 || exit 0
-```
-
-### Full (with SARIF + PR comments)
-
-See [examples/ci/loctree-ci-v2.yml](../examples/ci/loctree-ci-v2.yml)
-
-## Key Commands for CI
-
-| Command | Purpose | Exit Code |
-|---------|---------|-----------|
-| `loct auto` | Full scan → artifacts dir (cache by default; set `LOCT_CACHE_DIR=.loctree` in CI) | Always 0 |
-| `loct lint --fail` | Structural lint | 1 if issues |
-| `loct dead --confidence high` | Dead exports | Always 0 |
-| `loct cycles` | Circular imports | Always 0 |
-| `loct health --json` | Quick summary | Always 0 |
-
-## Artifacts Generated
-
-By default, artifacts go to the OS cache dir. In CI, set `LOCT_CACHE_DIR=.loctree` to write artifacts into the workspace:
-
-```
-.loctree/
-├── snapshot.json # Full dependency graph (jq-queryable)
-├── findings.json # All issues (dead, cycles, twins...)
-├── agent.json # AI-optimized bundle with health_score
-└── manifest.json # Index for tooling
-```
-
-## Health Score
-
-The `agent.json` contains a `health_score` (0-100):
-
-```bash
-# Extract with jq
-HEALTH=$(jq -r '.summary.health_score' .loctree/agent.json)
-```
-
-### Score Interpretation
-
-| Score | Status | Meaning |
-|-------|--------|---------|
-| 80-100 | 🟢 | Excellent structural health |
-| 50-79 | 🟡 | Some issues, review recommended |
-| 0-49 | 🔴 | Critical issues, fix before merge |
-
-## SARIF Integration
-
-Generate SARIF for GitHub Code Scanning:
-
-```yaml
-- run: loct lint --sarif > loctree.sarif
-- uses: github/codeql-action/upload-sarif@v3
- with:
- sarif_file: loctree.sarif
- category: loctree
-```
-
-## Environment Variables
-
-| Variable | Default | Description |
-|----------|---------|-------------|
-| `HEALTH_THRESHOLD` | 50 | Minimum health score to pass |
-| `FAIL_ON_FINDINGS` | false | Exit 1 if any findings |
-| `MAX_DEAD_EXPORTS` | ∞ | Max dead exports allowed |
-| `MAX_CYCLES` | 0 | Max circular imports allowed |
-
----
-
-𝚅𝚒𝚋𝚎𝚌𝚛𝚊𝚏𝚝𝚎𝚍. with AI Agents ⓒ 2025-2026 Loctree Team
diff --git a/docs/cli/commands.md b/docs/cli/commands.md
deleted file mode 100644
index 93e6aecc..00000000
--- a/docs/cli/commands.md
+++ /dev/null
@@ -1,1072 +0,0 @@
-# loctree CLI Command Reference
-
-Complete reference for all loctree commands. For global options and environment variables, see [options.md](./options.md).
-
-## Philosophy
-
-**Scan once, query everything.** Run `loct` to create cached artifacts (cache dir by default; override via `LOCT_CACHE_DIR`), then use subcommands to query them.
-
----
-
-## Table of Contents
-
-- [Quick Start](#quick-start)
-- [Instant Commands (<100ms)](#instant-commands-100ms)
-- [Analysis Commands](#analysis-commands)
-- [Framework-Specific Commands](#framework-specific-commands)
-- [Management Commands](#management-commands)
-- [Core Workflow Commands](#core-workflow-commands)
-- [JQ Query Mode](#jq-query-mode)
-- [Aliases](#aliases)
-- [Artifacts](#artifacts)
-
----
-
-## Quick Start
-
-| Command | Description | Speed |
-|---------|-------------|-------|
-| `loct` | Auto-scan and analyze current directory | ~2s |
-| `loct health` | Quick health check (cycles + dead + twins) | <100ms |
-| `loct slice ` | Extract file + dependencies for AI context | <100ms |
-| `loct dead` | Find unused exports / dead code | <100ms |
-
----
-
-## Instant Commands (<100ms)
-
-These commands query pre-built artifacts and return results in milliseconds.
-
-### `focus` - Directory Context
-
-Extract holographic context for a directory (like `slice` but for directories).
-
-```bash
-loct focus [OPTIONS]
-```
-
-**Options:**
-- `--consumers`, `-c` - Include files that import from this directory
-- `--depth ` - Maximum depth for external dependency traversal
-- `--root ` - Project root (default: current directory)
-
-**Examples:**
-```bash
-loct focus src/features/patients/ # Focus on patients feature
-loct focus src/components/ --consumers # Include external consumers
-loct focus lib/utils/ --depth 1 # Limit external dep depth
-loct focus src/api/ --json # JSON output for AI tools
-```
-
-**Output:**
-- Core files (all files in the directory)
-- Internal edges (imports within the directory)
-- External deps (files outside the directory that are imported)
-- Consumers (files outside that import from the directory)
-
----
-
-### `hotspots` - Import Frequency Heatmap
-
-Show import frequency heatmap - which files are core vs peripheral.
-
-```bash
-loct hotspots [OPTIONS]
-```
-
-**Options:**
-- `--min ` - Minimum import count to show (default: 1)
-- `--limit ` - Maximum files to show (default: 50)
-- `--leaves` - Show only leaf nodes (0 importers)
-- `--coupling` - Include out-degree (files that import many others)
-- `--root ` - Project root
-
-**Examples:**
-```bash
-loct hotspots # Show top 50 most-imported files
-loct hotspots --limit 20 # Top 20 only
-loct hotspots --leaves # Find leaf nodes (entry points / dead)
-loct hotspots --coupling # Show both in-degree and out-degree
-loct hotspots --min 5 # Only files with 5+ importers
-```
-
-**Output Categories:**
-- **CORE** (10+ importers) - Critical infrastructure
-- **SHARED** (3-9 importers) - Shared utilities
-- **PERIPHERAL** (1-2 importers) - Feature-specific
-- **LEAF** (0 importers) - Entry points or potentially dead code
-
----
-
-### `commands` - Tauri FE↔BE Handler Bridges
-
-Show Tauri command bridges between frontend and backend.
-
-```bash
-loct commands [OPTIONS] [PATHS...]
-```
-
-**Options:**
-- `--name ` - Filter to commands matching pattern
-- `--missing-only` - Show only missing handlers
-- `--unused-only` - Show only unused handlers
-- `--limit ` - Maximum results to show
-
-**Examples:**
-```bash
-loct commands # Full coverage report
-loct commands --missing-only # Only missing handlers
-loct commands --json --missing # JSON for CI
-```
-
-**Detects:**
-- Missing handlers: FE calls `invoke('cmd')` but no BE `#[tauri::command]`
-- Unused handlers: BE has `#[tauri::command]` but FE never calls it
-- Matched handlers: Both FE and BE exist (healthy)
-
----
-
-### `events` - Event Flow Analysis
-
-Show event emit/listen flow and issues.
-
-```bash
-loct events [OPTIONS] [PATHS...]
-```
-
-**Options:**
-- `--ghost` - Show ghost events (emitted but not handled)
-- `--orphan` - Show orphan handlers (handlers without emitters)
-- `--races` - Show potential race conditions
-- `--fe-sync` - Show only FE<->FE sync events (window sync pattern)
-
-**Examples:**
-```bash
-loct events # Full event analysis
-loct events --ghost # Only ghost events
-loct events --races # Race condition detection
-```
-
----
-
-### `coverage` - Test Coverage Gaps
-
-Analyze test coverage gaps (structural coverage, not line coverage).
-
-```bash
-loct coverage [OPTIONS] [PATHS...]
-```
-
-**Options:**
-- `--handlers-only` - Only show handler gaps (skip events/exports)
-- `--events-only` - Only show event gaps (skip handlers/exports)
-- `--min-severity ` - Filter by minimum severity: critical, high, medium, low
-
-**Examples:**
-```bash
-loct coverage # Show all coverage gaps
-loct coverage --handlers-only # Focus on untested handlers
-loct coverage --min-severity high # Only critical/high issues
-```
-
-**Severity Levels:**
-- **CRITICAL:** Handlers without any test (used in production!)
-- **HIGH:** Events emitted but never tested
-- **MEDIUM:** Exports without test imports
-- **LOW:** Tests that import unused code
-
----
-
-### `health` - Quick Health Check
-
-One-shot summary of all structural issues.
-
-```bash
-loct health [OPTIONS] [PATHS...]
-```
-
-**Options:**
-- `--include-tests` - Include test files in analysis (default: false)
-
-**Examples:**
-```bash
-loct health # Quick health summary
-loct health --include-tests # Include test files
-loct health src/ # Analyze specific directory
-loct health --json # Machine-readable output
-```
-
-**Output:**
-- Cycles: Circular import count (hard vs structural)
-- Dead: Unused exports (high confidence count)
-- Twins: Duplicate symbol names across files
-
----
-
-### `slice` - File Context Extraction
-
-Extract holographic context for a file (file + all its dependencies).
-
-```bash
-loct slice [OPTIONS]
-```
-
-**Options:**
-- `--consumers`, `-c` - Include reverse dependencies (files that import this)
-- `--depth ` - Maximum dependency depth to traverse
-- `--root ` - Project root for resolving imports
-- `--rescan` - Force snapshot update (includes new/uncommitted files)
-
-**Examples:**
-```bash
-loct slice src/main.rs # File + its dependencies
-loct slice src/utils.ts --consumers # Include reverse deps
-loct slice lib/api.ts --depth 2 # Limit to 2 levels
-loct slice src/app.tsx --json # JSON output for AI tools
-loct slice src/new-file.ts --rescan # Slice a newly created file
-```
-
-**Note:** Shows what the file USES, not what USES it. For reverse dependencies, use `--consumers` or `loct query who-imports`.
-
----
-
-### `impact` - Change Impact Analysis
-
-Analyze impact of modifying or removing a file.
-
-```bash
-loct impact [OPTIONS]
-```
-
-**Options:**
-- `--depth ` - Limit traversal depth (default: unlimited)
-- `--root ` - Project root
-
-**Examples:**
-```bash
-loct impact src/utils.ts # Full impact analysis
-loct impact src/api.ts --depth 2 # Limit to 2 levels deep
-loct impact lib/helpers.ts --json # JSON output
-```
-
-**Difference from `query who-imports`:**
-- `who-imports`: Finds direct importers only
-- `impact`: Finds ALL affected files (direct + transitive)
-
----
-
-### `query` - Graph Queries
-
-Query the import graph and symbol index for specific relationships.
-
-```bash
-loct query
-```
-
-**Query Kinds:**
-
-| Kind | Description | Example |
-|------|-------------|---------|
-| `who-imports ` | Find all files that import the file | `loct query who-imports src/utils.ts` |
-| `where-symbol ` | Find where a symbol is defined/exported | `loct query where-symbol PatientRecord` |
-| `component-of ` | Show which component/module contains the file | `loct query component-of src/ui/Button.tsx` |
-
-**Examples:**
-```bash
-loct query who-imports src/utils.ts # What imports utils.ts?
-loct query where-symbol PatientRecord # Where is it defined?
-loct query component-of src/ui/Button.tsx # What owns Button?
-```
-
----
-
-## Analysis Commands
-
-Commands that perform deeper analysis on the codebase.
-
-### `dead` - Unused Export Detection
-
-Detect unused exports / dead code.
-
-```bash
-loct dead [OPTIONS] [PATHS...]
-```
-
-**Options:**
-- `--confidence ` - `normal` or `high` (default: normal)
-- `--top ` - Limit results to top N (default: 20)
-- `--full`, `--all` - Show all results (ignore --top limit)
-- `--path ` - Filter by file path pattern (regex)
-- `--with-tests` - Include test files
-- `--with-helpers` - Include helper files
-- `--with-shadows` - Detect shadow exports (same symbol, multiple files)
-- `--with-ambient` - Include ambient declarations (declare global/module/namespace)
-- `--with-dynamic` - Include dynamically generated symbols (exec/eval/compile)
-
-**Examples:**
-```bash
-loct dead # Standard dead code analysis
-loct dead --confidence high # Only high-confidence findings
-loct dead --with-tests # Include test files
-loct dead --with-shadows # Detect shadow exports
-loct dead --full # Show all results
-```
-
----
-
-### `cycles` - Circular Import Detection
-
-Detect circular import chains.
-
-```bash
-loct cycles [OPTIONS] [PATHS...]
-```
-
-**Options:**
-- `--path ` - Filter to files matching pattern
-- `--breaking-only` - Only show cycles that would break compilation
-- `--explain` - Show detailed explanation for each cycle
-- `--legacy-format` - Use legacy output format
-
-**Examples:**
-```bash
-loct cycles # Detect all cycles
-loct cycles src/ # Only analyze src/
-loct cycles --json # JSON output for CI
-loct cycles --explain # Detailed explanations
-```
-
-**Why Cycles Matter:**
-- Runtime initialization errors
-- Build/bundling failures
-- Flaky test behavior
-
----
-
-### `twins` - Duplicate Symbol Detection
-
-Find dead parrots (0 imports) and duplicate exports.
-
-```bash
-loct twins [OPTIONS] [PATH]
-```
-
-**Options:**
-- `--path ` - Root directory to analyze
-- `--dead-only` - Show only dead parrots (0 imports)
-- `--include-tests` - Include test files (excluded by default)
-- `--include-suppressed` - Show suppressed findings too
-- `--ignore-conventions` - Ignore framework conventions when detecting twins
-
-**Examples:**
-```bash
-loct twins # Full analysis
-loct twins --dead-only # Only exports with 0 imports
-loct twins src/ # Analyze specific directory
-loct twins --include-tests # Include test files
-```
-
-**Detects:**
-- **Dead Parrots:** Exports with 0 imports anywhere in the codebase
-- **Exact Twins:** Same symbol name exported from multiple files
-- **Barrel Chaos:** Re-export anti-patterns (missing index.ts, deep re-export chains)
-
----
-
-### `zombie` - Comprehensive Dead Code Analysis
-
-Find all zombie code (dead exports + orphan files + shadows).
-
-```bash
-loct zombie [OPTIONS] [PATHS...]
-```
-
-**Options:**
-- `--include-tests` - Include test files in zombie detection (default: false)
-
-**Examples:**
-```bash
-loct zombie # Find all zombie code
-loct zombie --include-tests # Include test files
-loct zombie src/ # Analyze specific directory
-```
-
-**Combines:**
-- **Dead Exports:** Symbols with 0 imports
-- **Orphan Files:** Files with 0 importers (not entry points)
-- **Shadow Exports:** Same symbol exported by multiple files where some have 0 imports
-
----
-
-### `audit` - Full Codebase Audit
-
-Comprehensive analysis combining all structural checks.
-
-```bash
-loct audit [OPTIONS] [PATHS...]
-```
-
-**Options:**
-- `--include-tests` - Include test files in analysis (default: false)
-- `--todos` - Output as actionable todo checklist
-- `--limit ` - Maximum items per category (default: 20)
-
-**Examples:**
-```bash
-loct audit # Full audit of current directory
-loct audit --include-tests # Include test files
-loct audit src/ # Audit specific directory
-loct audit --todos # Actionable checklist format
-```
-
-**Includes:**
-- Cycles (circular imports)
-- Dead exports (unused code)
-- Twins (duplicate symbols)
-- Orphan files (0 importers)
-- Shadow exports (consolidation candidates)
-- Crowds (similar dependency patterns)
-
----
-
-### `crowd` - Functional Clustering
-
-Detect functional crowds (similar files clustering).
-
-```bash
-loct crowd [PATTERN] [OPTIONS]
-```
-
-**Options:**
-- `--pattern ` - Pattern to detect crowd around
-- `--auto-detect` - Detect all crowds automatically
-- `--min-size ` - Minimum crowd size to report (default: 2)
-- `--limit ` - Maximum crowds to show in auto-detect mode (default: 10)
-- `--include-tests` - Include test files in crowd detection (default: false)
-
-**Examples:**
-```bash
-loct crowd cache # Find cache-related clusters
-loct crowd session # Find session-related clusters
-loct crowd --auto-detect # Auto-detect all crowds
-```
-
----
-
-### `tagmap` - Unified Keyword Search
-
-Unified search around a keyword - aggregates files, crowds, and dead code.
-
-```bash
-loct tagmap [OPTIONS]
-```
-
-**Options:**
-- `--include-tests` - Include test files in analysis
-- `--limit ` - Maximum results per section (default: 20)
-
-**Examples:**
-```bash
-loct tagmap patient # Everything about 'patient' feature
-loct tagmap auth # Auth-related files, crowds, dead code
-loct tagmap message --json # JSON output for AI processing
-loct tagmap api --limit 10 # Limit results
-```
-
-**Aggregates:**
-1. **FILES:** All files with keyword in path or name
-2. **CROWD:** Functional clustering around the keyword
-3. **DEAD:** Dead exports related to the keyword
-
----
-
-### `sniff` - Code Smell Aggregate
-
-Sniff for code smells (twins + dead parrots + crowds).
-
-```bash
-loct sniff [OPTIONS]
-```
-
-**Options:**
-- `--path ` - Root directory to analyze
-- `--dead-only` - Show only dead parrots
-- `--twins-only` - Show only twins
-- `--crowds-only` - Show only crowds
-- `--include-tests` - Include test files in analysis (default: false)
-- `--min-crowd-size ` - Minimum crowd size to report (default: 2)
-
-**Examples:**
-```bash
-loct sniff # Full code smell analysis
-loct sniff --dead-only # Only dead parrots
-loct sniff --twins-only # Only duplicate names
-loct sniff --crowds-only # Only similar file clusters
-```
-
-**Aggregates:**
-- **TWINS:** Same symbol exported from multiple files
-- **DEAD PARROTS:** Exports with 0 imports
-- **CROWDS:** Files clustering around similar functionality
-
----
-
-### `doctor` - Interactive Diagnostics
-
-Interactive diagnostics with actionable recommendations.
-
-```bash
-loct doctor [OPTIONS] [PATHS...]
-```
-
-**Options:**
-- `--include-tests` - Include test files in analysis (default: false)
-- `--apply-suppressions` - Auto-add suggested patterns to .loctignore
-
-**Examples:**
-```bash
-loct doctor # Interactive diagnostics
-loct doctor --apply-suppressions # Auto-add .loctignore patterns
-loct doctor src/ # Analyze specific directory
-```
-
-**Categorizes Findings:**
-1. **Auto-fixable:** Issues with clear automated solutions
-2. **Needs Review:** Potential issues requiring human judgment
-3. **Suggested Suppressions:** Patterns to add to .loctignore
-
----
-
-## Framework-Specific Commands
-
-Commands designed for specific frameworks and tools.
-
-### `trace` - Tauri Handler Tracing
-
-Trace a Tauri/IPC handler end-to-end.
-
-```bash
-loct trace [ROOTS...]
-```
-
-**Examples:**
-```bash
-loct trace toggle_assistant
-loct trace standard_command apps/desktop
-```
-
-**Investigates:**
-- Backend definition (file, line, exposed name)
-- Frontend `invoke()` calls and plain mentions
-- Registration status in `generate_handler![]`
-- Verdict + suggestion to fix
-
----
-
-### `routes` - Backend Route Listing
-
-List backend/web routes (FastAPI/Flask).
-
-```bash
-loct routes [OPTIONS] [PATHS...]
-```
-
-**Options:**
-- `--framework ` - Filter by framework label (fastapi, flask)
-- `--path ` - Filter by route path substring
-
-**Examples:**
-```bash
-loct routes # List all routes
-loct routes --framework fastapi # Only FastAPI routes
-loct routes --path /patients # Filter by path
-```
-
-**Detects:**
-- **FastAPI:** `@app.get/post/put/delete/patch`, `@router.*`, `@api_router.*`
-- **Flask:** `@app.route`, `@blueprint.route`, `.route(...)`
-
----
-
-### `dist` - Bundle Analysis
-
-Analyze bundle distribution using source maps.
-
-```bash
-loct dist --source-map --src
-```
-
-**Options:**
-- `--source-map ` - Path to source map file (e.g., dist/main.js.map)
-- `--src ` - Source directory to scan (e.g., src/)
-
-**Examples:**
-```bash
-loct dist --source-map dist/main.js.map --src src/
-loct dist --source-map build/app.js.map --src app/src/
-```
-
-**Compares:**
-- Source code exports
-- Bundled JavaScript (via source maps)
-- Finds exports completely tree-shaken out by bundler
-
----
-
-### `layoutmap` - CSS Layout Analysis
-
-Analyze CSS layout properties (z-index, position, display).
-
-```bash
-loct layoutmap [OPTIONS]
-```
-
-**Options:**
-- `--zindex-only` - Show only z-index values
-- `--sticky-only` - Show only sticky/fixed position elements
-- `--grid-only` - Show only grid/flex layouts
-- `--min-zindex ` - Filter z-index values >= N
-- `--exclude ` - Exclude paths matching glob (can be repeated)
-- `--root ` - Project root
-
-**Examples:**
-```bash
-loct layoutmap # Full CSS layout analysis
-loct layoutmap --zindex-only # Only z-index hierarchy
-loct layoutmap --sticky-only # Only sticky/fixed elements
-loct layoutmap --min-zindex 100 # High z-index values (likely overlays)
-loct layoutmap --exclude .obsidian --exclude prototype # Skip dirs
-```
-
-**Extracts:**
-- **Z-INDEX:** All z-index values sorted by value (identifies layering conflicts)
-- **POSITION:** Sticky/fixed positioned elements
-- **DISPLAY:** Grid/flex layouts and their locations
-
----
-
-## Management Commands
-
-Commands for managing loctree analysis and configuration.
-
-### `doctor` - Interactive Diagnostics
-
-See [Analysis Commands](#doctor---interactive-diagnostics) section.
-
----
-
-### `suppress` - False Positive Management
-
-Manage false positive suppressions.
-
-```bash
-loct suppress [OPTIONS]
-loct suppress --list
-loct suppress --clear
-```
-
-**Types:**
-- `twins` - Exact twin (same symbol in multiple files)
-- `dead_parrot` - Dead parrot (export with 0 imports)
-- `dead_export` - Dead export (unused export)
-- `circular` - Circular import
-
-**Options:**
-- `--file ` - Only suppress in specific file (default: all files)
-- `--reason ` - Document why this is a false positive
-- `--list` - Show all current suppressions
-- `--clear` - Remove all suppressions
-- `--remove` - Remove a specific suppression
-
-**Examples:**
-```bash
-loct suppress twins Message # Suppress 'Message' twin everywhere
-loct suppress twins Message --file src/types.ts # Only in specific file
-loct suppress dead_parrot unusedHelper --reason 'Used via dynamic import'
-loct suppress --list # View all suppressions
-loct suppress --clear # Reset suppressions
-```
-
-**Storage:**
-- Suppressions are stored in `.loctree/suppressions.toml`
-- Commit this file to share suppressions with your team
-
----
-
-### `diff` - Snapshot Comparison
-
-Compare snapshots between branches/commits.
-
-```bash
-loct diff --since [--to ] [OPTIONS]
-```
-
-**Options:**
-- `--since ` - Base snapshot to compare from (required)
-- `--to ` - Target snapshot (default: current working tree)
-- `--auto-scan-base` - Auto-create git worktree and scan target branch
-- `--problems-only` - Show only regressions (new dead code, new cycles)
-- `--jsonl` - Output as JSONL (one line per change)
-
-**Examples:**
-```bash
-loct diff --since main # Compare main to working tree
-loct diff --since HEAD~1 # Compare to previous commit
-loct diff --since main --auto-scan-base # Auto-scan main branch
-loct diff --since v1.0.0 --to v2.0.0 # Compare two tags
-```
-
-**Shows:**
-- New/removed files and symbols
-- Import graph changes
-- New dead code introduced (regressions)
-- New circular dependencies
-
----
-
-### `memex` - AI Memory Indexing
-
-Index analysis into AI memory (vector database).
-
-```bash
-loct memex [OPTIONS]
-```
-
-**Options:**
-- `--report-path ` - Path to .loctree directory or analysis.json file
-- `--project-id ` - Unique project identifier (e.g., "github.com/org/repo")
-- `--namespace ` - Namespace for the memory index (default: "loctree")
-- `--db-path ` - Path to LanceDB storage directory
-
-**Examples:**
-```bash
-loct memex # Index current project
-loct memex --project-id github.com/org/repo # Set project ID
-loct memex --namespace myproject # Custom namespace
-```
-
----
-
-## Core Workflow Commands
-
-Commands for basic analysis and scanning.
-
-### `auto` - Full Auto-Scan (Default)
-
-Full auto-scan with stack detection (default command).
-
-```bash
-loct auto [OPTIONS] [PATHS...]
-loct [OPTIONS] [PATHS...] # 'auto' is the default command
-```
-
-**Options:**
-- `--full-scan` - Force full rescan (ignore cache)
-- `--scan-all` - Scan all files including hidden/ignored
-- `--for-agent-feed` - Output optimized format for AI agents (JSONL stream)
-- `--agent-json` - Emit a single agent bundle JSON
-
-**Examples:**
-```bash
-loct # Auto-scan current directory
-loct auto # Explicit auto command
-loct auto --full-scan # Force full rescan
-loct auto src/ lib/ # Scan specific directories
-loct --for-agent-feed # AI-optimized output (JSONL stream)
-loct --agent-json # One-shot agent bundle JSON
-```
-
-**Performs:**
-- Detects project type and language stack automatically
-- Builds dependency graph and import relationships
-- Analyzes code structure and exports
-- Identifies potential issues (dead code, cycles, etc.)
-
----
-
-### `scan` - Build Snapshot
-
-Build/update snapshot for current HEAD.
-
-```bash
-loct scan [OPTIONS] [PATHS...]
-```
-
-**Options:**
-- `--full-scan` - Force full rescan, ignore cached data
-- `--scan-all` - Include hidden and ignored files
-- `--watch` - Watch for changes and re-scan automatically
-
-**Examples:**
-```bash
-loct scan # Scan current directory
-loct scan --full-scan # Force complete rescan
-loct scan src/ lib/ # Scan specific directories
-loct scan --scan-all # Include all files (even hidden)
-loct scan --watch # Watch mode with live refresh
-```
-
-**Note:** Unlike `auto`, it only builds the snapshot without extra analysis.
-
----
-
-### `tree` - Directory Tree with LOC
-
-Display LOC tree / structural overview.
-
-```bash
-loct tree [OPTIONS] [PATHS...]
-```
-
-**Options:**
-- `--depth `, `-L ` - Maximum depth (default: unlimited)
-- `--summary [N]` - Show top N largest items (default: 5)
-- `--top [N]` - Only show top N largest items (default: 50)
-- `--loc ` - Only show items with LOC >= N
-- `--min-loc ` - Alias for --loc
-- `--show-hidden`, `-H` - Include hidden files/directories
-- `--find-artifacts` - Highlight build/generated artifacts
-- `--show-ignored` - Show gitignored files
-
-**Examples:**
-```bash
-loct tree # Full tree
-loct tree --depth 3 # Limit depth
-loct tree --summary 10 # Top 10 largest
-loct tree --loc 100 # LOC threshold
-loct tree src/ --show-hidden # Include dotfiles
-```
-
----
-
-### `find` - Symbol/File Search
-
-Semantic search for symbols by name pattern.
-
-```bash
-loct find [QUERY] [OPTIONS]
-```
-
-**Options:**
-- `--symbol ` - Search for symbols matching regex
-- `--file ` - Search for files matching regex
-- `--similar ` - Find symbols with similar names (fuzzy)
-- `--dead` - Only show dead/unused symbols
-- `--exported` - Only show exported symbols
-- `--lang ` - Filter by language (ts, rs, js, py, etc.)
-- `--limit ` - Maximum results to show
-
-**Examples:**
-```bash
-loct find Patient # Find symbols containing "Patient"
-loct find --symbol ".*Config$" # Regex: symbols ending with Config
-loct find --file "utils" # Files containing "utils" in path
-loct find --dead --exported # Dead exported symbols
-```
-
-**Note:** NOT impact analysis - for dependency impact, use `loct impact`. NOT dead code detection - use `loct dead` or `loct twins`.
-
----
-
-### `lint` - Structural Linting
-
-Structural lint and policy checks.
-
-```bash
-loct lint [OPTIONS] [PATHS...]
-```
-
-**Options:**
-- `--entrypoints` - Check entrypoint coverage
-- `--sarif` - Output in SARIF format for CI integration
-- `--tauri` - Enable Tauri-specific checks
-- `--fail` - Exit non-zero on issues (CI mode)
-
-**Examples:**
-```bash
-loct lint # Standard linting
-loct lint --fail --sarif # CI mode with SARIF output
-loct lint --tauri # Tauri-specific checks
-```
-
----
-
-### `report` - Generate Reports
-
-Generate HTML/JSON reports.
-
-```bash
-loct report [OPTIONS] [PATHS...]
-```
-
-**Options:**
-- `--format ` - Output format (html, json)
-- `--output ` - Output file path
-- `--serve` - Start a local server to view the report
-- `--port ` - Server port (default: varies)
-- `--editor ` - Editor integration (code, cursor, windsurf, jetbrains)
-
-**Examples:**
-```bash
-loct report --output report.html # Generate HTML report
-loct report --serve --port 4173 # Serve report locally
-loct report --editor code # VSCode integration
-```
-
----
-
-### `info` - Snapshot Metadata
-
-Show snapshot metadata and project info.
-
-```bash
-loct info [OPTIONS]
-```
-
-**Options:**
-- `--root ` - Root directory to check
-
-**Examples:**
-```bash
-loct info # Show snapshot metadata
-loct info --root src/ # Check specific directory
-```
-
-**Displays:**
-- Snapshot metadata
-- Detected stack
-- Analysis summary
-
----
-
-### `help` - Command Help
-
-Show help for commands.
-
-```bash
-loct help [COMMAND]
-loct --help
-loct --help-full
-loct --help-legacy
-```
-
-**Examples:**
-```bash
-loct help # Main help
-loct help slice # Help for slice command
-loct --help-full # All 27 commands
-loct --help-legacy # Legacy flag migration guide
-```
-
----
-
-### `version` - Version Info
-
-Show version information.
-
-```bash
-loct version
-loct --version
-```
-
----
-
-## JQ Query Mode
-
-Query snapshot with jq-style filters. Requires jaq dependencies (enabled by default in CLI build).
-
-```bash
-loct '' [OPTIONS]
-```
-
-**Options:**
-- `-r`, `--raw-output` - Output raw strings, not JSON
-- `-c`, `--compact-output` - Compact JSON output (no pretty-printing)
-- `-e`, `--exit-status` - Set exit code based on output (0 if truthy)
-- `--arg ` - Pass string variable to filter
-- `--argjson ` - Pass JSON variable to filter
-- `--snapshot ` - Use specific snapshot file instead of latest
-
-**Filter Syntax:**
-- `.metadata` - Extract metadata field
-- `.files[]` - Iterate over files array
-- `.files[0]` - Get first file
-- `.[\"key\"]` - Access key with special characters
-
-**Examples:**
-```bash
-loct '.metadata' # Extract metadata
-loct '.files | length' # Count files
-loct '.files[] | .path' # List file paths
-loct '.metadata.total_loc' -r # Raw number output
-loct '.files[] | select(.lang == "ts")' -c
-loct '.files[] | select(.loc > 500)' -c
-loct '.dead_parrots[]' # List dead exports
-loct '.cycles[]' # List circular imports
-```
-
----
-
-## Aliases
-
-Quick shortcuts for common commands:
-
-| Alias | Equivalent | Description |
-|-------|------------|-------------|
-| `loct s ` | `loct slice ` | Extract file context |
-| `loct f ` | `loct find ` | Search symbols/files |
-| `loct h` | `loct health` | Health summary |
-
----
-
-## Artifacts
-
-loctree creates these artifacts in the artifacts dir (cache dir by default; override via `LOCT_CACHE_DIR`):
-
-| Artifact | Description | Use Case |
-|----------|-------------|----------|
-| `snapshot.json` | Full dependency graph | jq-queryable, complete project state |
-| `findings.json` | All issues (dead, cycles, twins...) | CI integration, automated checks |
-| `agent.json` | AI-optimized bundle with health_score | AI agent consumption |
-| `manifest.json` | Index for tooling | Tooling integration |
-
-**Query artifacts:**
-```bash
-loct manifests --json # View manifest (stdout)
-loct '.metadata' # Extract metadata from latest snapshot
-loct '.files | length' # Count files using jq mode
-```
-
----
-
-## Examples
-
-### Quick Analysis
-```bash
-loct # Scan repo, create artifacts
-loct health # Quick health check
-loct hotspots # Find hub files (47ms!)
-```
-
-### Deep Analysis
-```bash
-loct focus src/features/ # Directory context (67ms!)
-loct coverage # Test gaps (49ms!)
-loct audit # Full audit
-```
-
-### AI Integration
-```bash
-loct slice src/main.rs --json | claude
-loct --for-ai > context.json
-```
-
-### CI Integration
-```bash
-loct lint --fail --sarif > loctree.sarif
-loct health --json | jq '.summary.health_score'
-```
-
----
-
-𝚅𝚒𝚋𝚎𝚌𝚛𝚊𝚏𝚝𝚎𝚍. with AI Agents ⓒ 2025-2026 Loctree Team
diff --git a/docs/cli/options.md b/docs/cli/options.md
deleted file mode 100644
index f1b909fb..00000000
--- a/docs/cli/options.md
+++ /dev/null
@@ -1,614 +0,0 @@
-# loctree CLI Global Options
-
-Global options and environment variables for loctree CLI.
-
----
-
-## Table of Contents
-
-- [Global Options](#global-options)
-- [Output Options](#output-options)
-- [Scan Behavior Options](#scan-behavior-options)
-- [Filter Options](#filter-options)
-- [Environment Variables](#environment-variables)
-- [Color Mode](#color-mode)
-- [Examples](#examples)
-
----
-
-## Global Options
-
-These options can be used with any loctree command.
-
-| Option | Description | Default |
-|--------|-------------|---------|
-| `--help`, `-h` | Show help for command | - |
-| `--version` | Show version information | - |
-| `--quiet` | Suppress non-essential output | Off |
-| `--verbose` | Show detailed progress | Off |
-
-**Examples:**
-```bash
-loct --help # Main help
-loct slice --help # Help for slice command
-loct --version # Show version
-loct scan --verbose # Detailed progress
-loct dead --quiet # Minimal output
-```
-
----
-
-## Output Options
-
-Control output format and content.
-
-### `--json`
-
-Output as JSON (stdout only). Works with most commands.
-
-```bash
-loct health --json
-loct slice src/main.rs --json
-loct dead --json
-```
-
-**Output:**
-```json
-{
- "summary": {
- "cycles": 3,
- "dead_exports": 12,
- "twins": 2,
- "health_score": 85
- }
-}
-```
-
----
-
-### `findings`
-
-Emit the canonical findings JSON to stdout. Use this in new scripts instead of
-the legacy bare `loct --findings` shortcut.
-
-```bash
-loct findings
-loct findings > findings.json
-```
-
-**Use Case:**
-- CI integration
-- Automated checks
-- Custom processing
-
----
-
-### `findings --summary`
-
-Emit the compact summary JSON for CI/status checks. `--summary` remains valid on
-`loct tree`, but for findings output the modern path is `loct findings --summary`.
-
-```bash
-loct findings --summary
-loct findings --summary | jq '.health_score'
-loct tree --summary 10
-```
-
-**Output:**
-```
-{
- "health_score": 85,
- "dead_exports": 12,
- "cycles": 3,
- "twins": 2
-}
-```
-
----
-
-### `--for-ai`
-
-Output AI context bundle (JSONL stream). Optimized for AI agents.
-
-```bash
-loct --for-ai
-loct --for-ai > context.jsonl
-```
-
-**Alias:** `loct --for-agent-feed`
-
-**Output Format:** JSONL (one JSON object per line)
-
----
-
-### `--agent-json`
-
-Emit single-shot agent JSON bundle (vs JSONL stream). Saved to the artifacts dir (cache by default; override via `LOCT_CACHE_DIR`).
-
-```bash
-loct --agent-json
-loct agent # Shortcut command
-```
-
-**Bundle Contains:**
-- Handlers (Tauri commands)
-- Duplicates (exact twins)
-- Dead exports
-- Dynamic imports
-- Cycles
-- Top files (by LOC)
-- Health score
-
----
-
-## Scan Behavior Options
-
-Control how loctree scans and caches data.
-
-### `--fresh`
-
-Force rescan even if snapshot exists. Ignores mtime cache.
-
-```bash
-loct --fresh
-loct auto --fresh
-loct scan --fresh
-```
-
-**Use When:**
-- Snapshot is stale
-- Files changed without mtime update
-- Testing after code changes
-
----
-
-### `--no-scan`
-
-Fail if no snapshot exists (don't auto-scan). Query-only mode.
-
-```bash
-loct slice src/main.rs --no-scan
-loct health --no-scan
-```
-
-**Use When:**
-- CI where scan happened in previous step
-- You want to ensure you're using cached data
-- Testing against existing snapshot
-
----
-
-### `--fail-stale`
-
-Fail if snapshot is stale (CI mode). Ensures snapshot is up-to-date.
-
-```bash
-loct health --fail-stale
-loct lint --fail-stale --sarif
-```
-
-**Use When:**
-- CI pipeline
-- Ensuring fresh analysis
-- Pre-commit hooks
-
-**Exit Codes:**
-- `0` - Snapshot is fresh
-- `1` - Snapshot is stale
-
----
-
-### `--full-scan`
-
-Force full rescan ignoring mtime cache. Part of `auto` and `scan` commands.
-
-```bash
-loct auto --full-scan
-loct scan --full-scan
-```
-
-**Difference from `--fresh`:**
-- `--fresh`: Global option, forces rescan for any command
-- `--full-scan`: Scan option, ignores mtime optimization
-
----
-
-### `--scan-all`
-
-Include normally-ignored directories (node_modules, target, .venv).
-
-```bash
-loct scan --scan-all
-loct auto --scan-all
-```
-
-**Use When:**
-- Analyzing vendored code
-- Debugging missing imports
-- Full codebase inspection
-
-**Default Ignored:**
-- `node_modules/`
-- `target/`
-- `.venv/`
-- `dist/`
-- `build/`
-- `.git/`
-
----
-
-## Filter Options
-
-Options for filtering and suppressing output.
-
-### `--no-duplicates`
-
-Suppress duplicate export sections in CLI output. Reduces noise.
-
-```bash
-loct auto --no-duplicates
-loct commands --no-duplicates
-loct events --no-duplicates
-loct lint --no-duplicates
-```
-
-**Affects:**
-- `auto` command
-- `commands` command
-- `events` command
-- `lint` command
-
----
-
-### `--no-dynamic-imports`
-
-Hide dynamic import sections in CLI output. Reduces noise.
-
-```bash
-loct auto --no-dynamic-imports
-loct events --no-dynamic-imports
-loct lint --no-dynamic-imports
-```
-
-**Affects:**
-- `auto` command
-- `events` command
-- `lint` command
-
----
-
-### `--py-root `
-
-Additional Python package root for imports. Helps resolve Python imports.
-
-```bash
-loct scan --py-root /path/to/python/packages
-loct auto --py-root ./external-libs
-```
-
-**Use When:**
-- Using external Python packages
-- Custom Python package layout
-- Monorepo with multiple Python roots
-
-**Example:**
-```bash
-# Resolve imports from both src/ and external-libs/
-loct scan --py-root ./external-libs
-```
-
----
-
-## Environment Variables
-
-### `LOCT_COLOR`
-
-Control color output. Overrides `--color` flag.
-
-**Values:**
-- `auto` - Auto-detect TTY support (default)
-- `always` - Force color output
-- `never` - Disable color output
-
-**Example:**
-```bash
-export LOCT_COLOR=never
-loct health # No color output
-
-LOCT_COLOR=always loct health | less -R # Force color in pipe
-```
-
----
-
-### `LOCT_CACHE_DIR`
-
-Override default cache directory.
-
-Default: platform user cache directory (`~/Library/Caches/loctree` on macOS, `~/.cache/loctree` on Linux).
-
-Tip: set `LOCT_CACHE_DIR=.loctree` to restore legacy project-local artifacts.
-
-**Example:**
-```bash
-export LOCT_CACHE_DIR=/tmp/loctree-cache
-loct scan
-```
-
----
-
-### `LOCT_LOG_LEVEL`
-
-Set logging verbosity. Useful for debugging.
-
-**Values:**
-- `error` - Only errors
-- `warn` - Warnings and errors
-- `info` - Informational messages (default)
-- `debug` - Detailed debug output
-- `trace` - Very detailed trace output
-
-**Example:**
-```bash
-export LOCT_LOG_LEVEL=debug
-loct scan --verbose
-```
-
----
-
-## Color Mode
-
-Control color output with `--color` flag.
-
-```bash
-loct --color
-```
-
-**Modes:**
-
-| Mode | Description | Use Case |
-|------|-------------|----------|
-| `auto` | Auto-detect TTY support | Default, smart detection |
-| `always` | Force color output | Piping to `less -R`, HTML logs |
-| `never` | Disable color output | CI logs, plain text files |
-
-**Examples:**
-```bash
-loct health --color auto # Auto-detect (default)
-loct health --color always # Force color
-loct health --color never # No color
-loct health --color always | less -R # Color in less
-```
-
-**Auto-detection:**
-- Checks if stdout is a TTY
-- Checks `TERM` environment variable
-- Checks `NO_COLOR` environment variable
-
----
-
-## Examples
-
-### CI Integration
-
-```bash
-# Fail if snapshot is stale, output SARIF
-loct lint --fail-stale --sarif --fail > loctree.sarif
-
-# JSON output for processing
-loct health --json | jq '.summary.health_score'
-
-# Ensure fresh scan, fail on issues
-loct --fresh audit --json > audit.json
-```
-
----
-
-### AI Agent Integration
-
-```bash
-# Single-shot agent bundle
-loct --agent-json > agent.json
-
-# JSONL stream for incremental processing
-loct --for-ai > context.jsonl
-
-# Slice with JSON for AI consumption
-loct slice src/main.rs --json | claude
-```
-
----
-
-### Development Workflow
-
-```bash
-# Quick health check
-loct h # Alias for --summary
-
-# Verbose scan with full rescan
-loct scan --verbose --full-scan
-
-# Quiet mode for scripts
-loct dead --quiet --json > dead.json
-
-# Watch mode for continuous analysis
-loct scan --watch
-```
-
----
-
-### Debugging
-
-```bash
-# Enable debug logging
-export LOCT_LOG_LEVEL=debug
-loct scan --verbose
-
-# Force color in pipe
-loct health --color always | tee health.log
-
-# Use custom cache directory
-export LOCT_CACHE_DIR=/tmp/loctree
-loct scan
-```
-
----
-
-### Python Projects
-
-```bash
-# Add custom Python root
-loct scan --py-root ./external-libs
-
-# Multiple Python roots (run separate scans)
-loct scan --py-root ./lib1
-loct scan --py-root ./lib2
-
-# Include virtualenv in scan
-loct scan --scan-all # Scans .venv/ too
-```
-
----
-
-## Option Precedence
-
-When options conflict, precedence is:
-
-1. Command-line flags (highest)
-2. Environment variables
-3. Configuration files (if any)
-4. Defaults (lowest)
-
-**Example:**
-```bash
-# Environment variable
-export LOCT_COLOR=never
-
-# Command-line flag overrides
-loct health --color always # Uses 'always', not 'never'
-```
-
----
-
-## Best Practices
-
-### For CI
-
-```bash
-# Use fail flags and JSON output
-loct lint --fail-stale --fail --sarif > loctree.sarif
-loct health --fail-stale --json > health.json
-
-# Disable color in CI logs
-loct --color never health
-# Or set environment variable
-export LOCT_COLOR=never
-```
-
----
-
-### For Local Development
-
-```bash
-# Use watch mode for continuous feedback
-loct scan --watch
-
-# Quick health checks
-loct h # Alias for --summary
-
-# Verbose for debugging
-loct scan --verbose --full-scan
-```
-
----
-
-### For AI Integration
-
-```bash
-# Agent bundle for one-shot context
-loct agent > agent.json
-
-# JSONL stream for incremental processing
-loct --for-ai > context.jsonl
-
-# JSON output for specific commands
-loct slice src/main.rs --json
-loct dead --json
-loct health --json
-```
-
----
-
-## Common Patterns
-
-### Fresh Analysis
-
-```bash
-# Force fresh scan and analysis
-loct --fresh health
-loct --fresh audit
-loct scan --full-scan
-```
-
----
-
-### Query Only (No Scan)
-
-```bash
-# Fail if no snapshot, don't auto-scan
-loct slice src/main.rs --no-scan
-loct health --no-scan
-loct dead --no-scan
-```
-
----
-
-### Quiet Mode for Scripts
-
-```bash
-# Minimal output, JSON for parsing
-loct dead --quiet --json > dead.json
-loct health --quiet --json | jq '.summary'
-```
-
----
-
-### Verbose Debugging
-
-```bash
-# Detailed progress and logging
-export LOCT_LOG_LEVEL=debug
-loct scan --verbose --full-scan
-
-# Trace-level logging
-export LOCT_LOG_LEVEL=trace
-loct auto --verbose
-```
-
----
-
-## Summary Table
-
-| Option | Short | Type | Default | Commands |
-|--------|-------|------|---------|----------|
-| `--help` | `-h` | Flag | - | All |
-| `--version` | - | Flag | - | All |
-| `--json` | - | Flag | Off | Most |
-| `--quiet` | - | Flag | Off | All |
-| `--verbose` | - | Flag | Off | All |
-| `--color ` | - | Value | `auto` | All |
-| `--fresh` | - | Flag | Off | All |
-| `--no-scan` | - | Flag | Off | Query commands |
-| `--fail-stale` | - | Flag | Off | All |
-| `--findings` | - | Flag | Legacy | bare `loct` only (compat alias for `findings`) |
-| `--summary` | - | Flag | Legacy | bare `loct` compat alias for `findings --summary`; also `tree` |
-| `--for-ai` | - | Flag | Off | `auto` |
-| `--agent-json` | - | Flag | Off | `auto` |
-| `--py-root ` | - | Value | - | `scan`, `auto` |
-| `--full-scan` | - | Flag | Off | `scan`, `auto` |
-| `--scan-all` | - | Flag | Off | `scan`, `auto` |
-| `--no-duplicates` | - | Flag | Off | `auto`, `commands`, `events`, `lint` |
-| `--no-dynamic-imports` | - | Flag | Off | `auto`, `events`, `lint` |
-
----
-
-𝚅𝚒𝚋𝚎𝚌𝚛𝚊𝚏𝚝𝚎𝚍. with AI Agents ⓒ 2025-2026 Loctree Team
diff --git a/docs/design/01_query_mode_test_plan.md b/docs/design/01_query_mode_test_plan.md
deleted file mode 100644
index eb5a9bcf..00000000
--- a/docs/design/01_query_mode_test_plan.md
+++ /dev/null
@@ -1,614 +0,0 @@
-# Loctree Query Mode - Comprehensive Test Plan
-
-**Feature**: jq-style snapshot queries
-**Command**: `loct `, `loct @preset `, `loct query `
-**Author**: AI Agent Design Document
-**Date**: 2025-12-11
-**Status**: Design Phase
-
----
-
-## Overview
-
-Query mode enables jq-style filtering on loctree snapshots without re-scanning.
-This document defines test cases for implementation.
-
-### Command Syntax
-
-```bash
-# Filter syntax (jq-compatible)
-loct '.metadata' # Simple field access
-loct '.metadata.git_branch' # Nested access
-loct '.edges[]' # Array iteration
-loct '.edges | length' # Pipe to function
-loct '.edges[] | select(.to == "foo")' # Filter with select
-
-# Preset queries (shorthand)
-loct @imports src/foo.ts # Files that import foo.ts
-loct @exports src/foo.ts # Symbols exported by foo.ts
-loct @dead # Dead exports list
-loct @consumers src/foo.ts # Files that consume foo.ts
-
-# Output flags
-loct '.metadata.git_branch' -r # Raw output (no quotes)
-loct '.edges' -c # Compact JSON
-loct '.edges | length' -e # Exit code based on result
-
-# Explicit snapshot path
-loct '.metadata' --snapshot .loctree/snapshot.json
-```
-
----
-
-## 1. Filter Detection Tests
-
-These tests verify the CLI correctly identifies filter expressions vs subcommands.
-
-### 1.1 Dot-prefix filter detection
-
-| Test ID | Input | Expected | Validates |
-|---------|-------|----------|-----------|
-| FD-001 | `loct '.metadata'` | Recognized as filter | Dot-prefix triggers filter mode |
-| FD-002 | `loct '.metadata.git_branch'` | Recognized as filter | Nested dot-prefix works |
-| FD-003 | `loct '.'` | Recognized as filter | Root selector works |
-| FD-004 | `loct '.files[0]'` | Recognized as filter | Array index with dot-prefix |
-| FD-005 | `loct '.edges[]'` | Recognized as filter | Array iteration with dot-prefix |
-
-### 1.2 Bracket-prefix filter detection
-
-| Test ID | Input | Expected | Validates |
-|---------|-------|----------|-----------|
-| FD-010 | `loct '[.metadata]'` | Recognized as filter | Bracket wrapping |
-| FD-011 | `loct '[ .files[] ]'` | Recognized as filter | Bracket with spaces |
-| FD-012 | `loct '[.edges[] | .from]'` | Recognized as filter | Complex bracket expression |
-
-### 1.3 Subcommand disambiguation
-
-| Test ID | Input | Expected | Validates |
-|---------|-------|----------|-----------|
-| FD-020 | `loct scan` | Recognized as subcommand | Known subcommand not treated as filter |
-| FD-021 | `loct tree` | Recognized as subcommand | Another known subcommand |
-| FD-022 | `loct dead` | Recognized as subcommand | Subcommand without args |
-| FD-023 | `loct info` | Recognized as subcommand | Single-word subcommand |
-| FD-024 | `loct query .metadata` | Explicit query subcommand | Explicit query mode |
-
-### 1.4 Preset detection
-
-| Test ID | Input | Expected | Validates |
-|---------|-------|----------|-----------|
-| FD-030 | `loct @imports foo.ts` | Recognized as preset | At-prefix triggers preset |
-| FD-031 | `loct @exports foo.ts` | Recognized as preset | Known preset name |
-| FD-032 | `loct @dead` | Recognized as preset | Preset without args |
-| FD-033 | `loct @consumers foo.ts` | Recognized as preset | Consumer preset |
-| FD-034 | `loct @unknown` | Error: unknown preset | Invalid preset rejected |
-
-### 1.5 Edge cases in detection
-
-| Test ID | Input | Expected | Validates |
-|---------|-------|----------|-----------|
-| FD-040 | `loct metadata` | Error or treated as path | Bare word not a filter |
-| FD-041 | `loct .hidden-file.ts` | Ambiguous - file or filter? | Document behavior |
-| FD-042 | `loct ''` | Error: empty filter | Empty string rejected |
-| FD-043 | `loct ' .metadata '` | Recognized as filter | Whitespace trimmed |
-
----
-
-## 2. Snapshot Discovery Tests
-
-These tests verify correct snapshot file discovery and override behavior.
-
-### 2.1 Auto-discovery (newest snapshot)
-
-| Test ID | Setup | Command | Expected | Validates |
-|---------|-------|---------|----------|-----------|
-| SD-001 | Single `.loctree/snapshot.json` | `loct '.metadata'` | Uses that snapshot | Basic discovery |
-| SD-002 | Multiple: `main@abc123/`, `develop@def456/` | `loct '.metadata'` | Uses newest by mtime | Multi-snapshot selection |
-| SD-003 | Only `develop@xyz/snapshot.json` | `loct '.metadata'` | Uses branch-specific | Branch isolation works |
-| SD-004 | Empty `.loctree/` directory | `loct '.metadata'` | Error: no snapshot found | Clear error on missing |
-| SD-005 | No `.loctree/` directory | `loct '.metadata'` | Error: no snapshot found | Missing dir handled |
-
-### 2.2 Explicit snapshot path
-
-| Test ID | Setup | Command | Expected | Validates |
-|---------|-------|---------|----------|-----------|
-| SD-010 | Multiple snapshots exist | `loct '.metadata' --snapshot .loctree/old.json` | Uses specified file | Override works |
-| SD-011 | Specified file missing | `loct '.metadata' --snapshot missing.json` | Error: file not found | Clear error |
-| SD-012 | Invalid JSON file | `loct '.metadata' --snapshot broken.json` | Error: invalid snapshot | Parse error |
-| SD-013 | Valid JSON, wrong schema | `loct '.metadata' --snapshot other.json` | Error or warning | Schema validation |
-
-### 2.3 Directory traversal
-
-| Test ID | Setup | Command | Expected | Validates |
-|---------|-------|---------|----------|-----------|
-| SD-020 | Run from subdirectory | `loct '.metadata'` | Finds parent's `.loctree/` | Upward search |
-| SD-021 | Run from project root | `loct '.metadata'` | Finds `./.loctree/` | Direct path |
-| SD-022 | Multiple `.loctree/` in ancestors | `loct '.metadata'` | Uses nearest | Closest wins |
-
----
-
-## 3. Filter Execution Tests
-
-These tests verify correct jq filter execution on snapshot data.
-
-### 3.1 Simple field access
-
-| Test ID | Filter | Expected Output | Validates |
-|---------|--------|-----------------|-----------|
-| FE-001 | `.metadata` | Full metadata object | Top-level field |
-| FE-002 | `.files` | Array of file analyses | Array field |
-| FE-003 | `.edges` | Array of graph edges | Another array |
-| FE-004 | `.barrels` | Array of barrel files | Optional field |
-| FE-005 | `.nonexistent` | `null` | Missing field returns null |
-
-### 3.2 Nested field access
-
-| Test ID | Filter | Expected Output | Validates |
-|---------|--------|-----------------|-----------|
-| FE-010 | `.metadata.git_branch` | `"develop"` (or current branch) | Nested string |
-| FE-011 | `.metadata.file_count` | `44` (or current count) | Nested number |
-| FE-012 | `.metadata.schema_version` | `"0.5.0-rc"` | Nested string |
-| FE-013 | `.metadata.languages` | `["rs"]` or `["ts", "rs"]` | Nested array |
-| FE-014 | `.metadata.nonexistent.deep` | `null` | Deep missing returns null |
-
-### 3.3 Array iteration
-
-| Test ID | Filter | Expected Output | Validates |
-|---------|--------|-----------------|-----------|
-| FE-020 | `.files[]` | Each file as separate output | Array iteration |
-| FE-021 | `.edges[]` | Each edge as separate output | Edge iteration |
-| FE-022 | `.files[0]` | First file analysis | Index access |
-| FE-023 | `.files[-1]` | Last file analysis | Negative index |
-| FE-024 | `.files[0:3]` | First 3 files | Slice notation |
-
-### 3.4 Field extraction from arrays
-
-| Test ID | Filter | Expected Output | Validates |
-|---------|--------|-----------------|-----------|
-| FE-030 | `.files[].path` | List of all file paths | Field from each |
-| FE-031 | `.edges[].from` | List of all source files | Edge sources |
-| FE-032 | `.edges[].to` | List of all target files | Edge targets |
-| FE-033 | `.files[].exports[].name` | All export names | Nested array extraction |
-
-### 3.5 Select/filter expressions
-
-| Test ID | Filter | Expected Output | Validates |
-|---------|--------|-----------------|-----------|
-| FE-040 | `.edges[] \| select(.to == "src/types.rs")` | Edges pointing to types.rs | Equality select |
-| FE-041 | `.files[] \| select(.loc > 500)` | Files with >500 LOC | Numeric comparison |
-| FE-042 | `.files[] \| select(.language == "ts")` | TypeScript files only | String match |
-| FE-043 | `.files[] \| select(.is_test == true)` | Test files only | Boolean match |
-| FE-044 | `.edges[] \| select(.label == "reexport")` | Re-export edges only | Label filter |
-| FE-045 | `.files[] \| select(.path \| contains("utils"))` | Files with utils in path | String contains |
-| FE-046 | `.files[] \| select(.path \| test(".*\\.rs$"))` | Rust files (regex) | Regex match |
-
-### 3.6 Variable binding (--arg)
-
-| Test ID | Command | Expected Output | Validates |
-|---------|---------|-----------------|-----------|
-| FE-050 | `loct '.edges[] \| select(.to == $file)' --arg file src/types.rs` | Edges to types.rs | String variable |
-| FE-051 | `loct '.files[] \| select(.loc > $min)' --argjson min 100` | Files >100 LOC | JSON number variable |
-| FE-052 | `loct '.edges[] \| select(.from == $f and .to == $t)' --arg f a.ts --arg t b.ts` | Specific edge | Multiple variables |
-
-### 3.7 Aggregate functions
-
-| Test ID | Filter | Expected Output | Validates |
-|---------|--------|-----------------|-----------|
-| FE-060 | `.edges \| length` | Number of edges | Array length |
-| FE-061 | `.files \| length` | Number of files | File count |
-| FE-062 | `[.files[].loc] \| add` | Total LOC | Sum |
-| FE-063 | `[.files[].loc] \| max` | Largest file LOC | Max |
-| FE-064 | `[.files[].loc] \| min` | Smallest file LOC | Min |
-| FE-065 | `.files \| group_by(.language) \| length` | Language count | Group by |
-| FE-066 | `[.files[] \| select(.loc > 500)] \| length` | Count of large files | Filtered count |
-
-### 3.8 Object construction
-
-| Test ID | Filter | Expected Output | Validates |
-|---------|--------|-----------------|-----------|
-| FE-070 | `.files[] \| {path, loc}` | Objects with path and loc | Field subset |
-| FE-071 | `.edges[] \| {source: .from, target: .to}` | Renamed fields | Field renaming |
-| FE-072 | `.files[] \| {path, exports: (.exports \| length)}` | Computed field | Nested computation |
-
-### 3.9 Sorting and limiting
-
-| Test ID | Filter | Expected Output | Validates |
-|---------|--------|-----------------|-----------|
-| FE-080 | `.files \| sort_by(.loc) \| reverse` | Files by LOC descending | Sort reverse |
-| FE-081 | `.files \| sort_by(.loc) \| .[:10]` | Top 10 by LOC | Sort + limit |
-| FE-082 | `.edges \| unique_by(.to)` | Unique targets | Deduplication |
-| FE-083 | `[.files[] \| .path] \| sort` | Sorted file paths | Simple sort |
-
----
-
-## 4. Output Flag Tests
-
-These tests verify output formatting flags work correctly.
-
-### 4.1 Raw output (-r)
-
-| Test ID | Command | Expected Output | Validates |
-|---------|---------|-----------------|-----------|
-| OF-001 | `loct '.metadata.git_branch' -r` | `develop` (no quotes) | String unquoted |
-| OF-002 | `loct '.metadata.file_count' -r` | `44` | Number unchanged |
-| OF-003 | `loct '.files[0].path' -r` | `src/analyzer/assets.rs` | Path unquoted |
-| OF-004 | `loct '.metadata' -r` | JSON object (formatted) | Objects unchanged |
-| OF-005 | `loct '.files[].path' -r` | One path per line | Array items unquoted |
-
-### 4.2 Compact output (-c)
-
-| Test ID | Command | Expected Output | Validates |
-|---------|---------|-----------------|-----------|
-| OF-010 | `loct '.metadata' -c` | Single-line JSON | No pretty-print |
-| OF-011 | `loct '.files[0]' -c` | Compact file JSON | Object compacted |
-| OF-012 | `loct '.edges[:3]' -c` | Compact array | Array compacted |
-
-### 4.3 Exit code mode (-e)
-
-| Test ID | Command | Expected Exit Code | Validates |
-|---------|---------|-------------------|-----------|
-| OF-020 | `loct '.metadata' -e` | 0 | Non-null result |
-| OF-021 | `loct '.nonexistent' -e` | 1 | Null result |
-| OF-022 | `loct 'false' -e` | 1 | False result |
-| OF-023 | `loct '""' -e` | 1 | Empty string |
-| OF-024 | `loct '0' -e` | 0 | Zero is truthy |
-| OF-025 | `loct '[]' -e` | 1 | Empty array is falsy |
-| OF-026 | `loct '.edges \| length > 0' -e` | 0 | True condition |
-
-### 4.4 Combined flags
-
-| Test ID | Command | Expected | Validates |
-|---------|---------|----------|-----------|
-| OF-030 | `loct '.files[].path' -rc` | Compact paths, unquoted | Raw + compact |
-| OF-031 | `loct '.edges \| length' -re` | Count, exit 0 if >0 | Raw + exit |
-
----
-
-## 5. Preset Query Tests
-
-These tests verify preset queries work correctly.
-
-### 5.1 @imports preset
-
-| Test ID | Command | Expected Output | Validates |
-|---------|---------|-----------------|-----------|
-| PQ-001 | `loct @imports src/types.rs` | Files importing types.rs | Basic imports |
-| PQ-002 | `loct @imports src/nonexistent.ts` | `[]` (empty array) | Missing file |
-| PQ-003 | `loct @imports types.rs` | Same as full path | Path normalization |
-| PQ-004 | `loct @imports src/analyzer/` | Files importing from dir | Directory import |
-
-### 5.2 @exports preset
-
-| Test ID | Command | Expected Output | Validates |
-|---------|---------|-----------------|-----------|
-| PQ-010 | `loct @exports src/types.rs` | Export symbols | File exports |
-| PQ-011 | `loct @exports src/nonexistent.ts` | Error or empty | Missing file |
-| PQ-012 | `loct @exports src/analyzer/mod.rs` | Module exports | Rust mod exports |
-
-### 5.3 @dead preset
-
-| Test ID | Command | Expected Output | Validates |
-|---------|---------|-----------------|-----------|
-| PQ-020 | `loct @dead` | Dead export list | All dead exports |
-| PQ-021 | `loct @dead --json` | JSON format dead | JSON output |
-| PQ-022 | `loct @dead --top 5` | Top 5 dead exports | Limit works |
-
-### 5.4 @consumers preset
-
-| Test ID | Command | Expected Output | Validates |
-|---------|---------|-----------------|-----------|
-| PQ-030 | `loct @consumers src/types.rs` | Files that use types.rs | Transitive consumers |
-| PQ-031 | `loct @consumers src/main.rs` | Entry point consumers | Entry file |
-
-### 5.5 Unknown preset
-
-| Test ID | Command | Expected | Validates |
-|---------|---------|----------|-----------|
-| PQ-040 | `loct @unknown` | Error: unknown preset '@unknown' | Clear error |
-| PQ-041 | `loct @` | Error: empty preset name | Empty preset |
-
----
-
-## 6. Edge Cases
-
-### 6.1 Empty/null results
-
-| Test ID | Filter | Expected Output | Validates |
-|---------|--------|-----------------|-----------|
-| EC-001 | `.edges[] \| select(.to == "nonexistent")` | Empty output | No matches |
-| EC-002 | `.barrels` (when empty) | `[]` | Empty array |
-| EC-003 | `.files[999]` | `null` | Out of bounds |
-| EC-004 | `.metadata.resolver_config` (when null) | `null` | Null field |
-
-### 6.2 Invalid filter syntax
-
-| Test ID | Filter | Expected | Validates |
-|---------|--------|----------|-----------|
-| EC-010 | `.metadata[` | Error: parse error | Unclosed bracket |
-| EC-011 | `.edges \| select(` | Error: parse error | Unclosed paren |
-| EC-012 | `.files \| unknownfn()` | Error: unknown function | Bad function |
-| EC-013 | `. \| . \| . \| .` | Success (identity chain) | Valid but weird |
-
-### 6.3 Snapshot edge cases
-
-| Test ID | Scenario | Command | Expected | Validates |
-|---------|----------|---------|----------|-----------|
-| EC-020 | Snapshot with 0 files | `.files \| length` | `0` | Empty snapshot |
-| EC-021 | Snapshot with 0 edges | `.edges \| length` | `0` | No edges |
-| EC-022 | Corrupted JSON | `.metadata` | Error: invalid snapshot | Parse failure |
-| EC-023 | Schema v0.4 snapshot | `.metadata` | Warning or error | Schema mismatch |
-
-### 6.4 Special characters
-
-| Test ID | Filter | Expected | Validates |
-|---------|--------|----------|-----------|
-| EC-030 | `.files[] \| select(.path \| contains("$"))` | Files with $ in path | Special char in string |
-| EC-031 | `.edges[] \| select(.to == "src/types.d.ts")` | Edge to .d.ts | Dots in value |
-| EC-032 | Filter with Unicode | Appropriate handling | Unicode support |
-
----
-
-## 7. Integration Tests
-
-### 7.1 Workflow: Scan then Query
-
-```bash
-# Setup: Fresh project
-loct scan # Create snapshot
-loct '.metadata.file_count' # Query: should show count
-loct '.edges | length' # Query: should show edge count
-```
-
-| Test ID | Step | Expected | Validates |
-|---------|------|----------|-----------|
-| IT-001 | After scan | Snapshot exists | Scan creates snapshot |
-| IT-002 | Query after scan | Returns data | Query uses snapshot |
-| IT-003 | Multiple queries | Consistent results | Snapshot stable |
-
-### 7.2 Workflow: Branch switching
-
-```bash
-git checkout feature-branch
-loct scan # Branch snapshot
-loct '.metadata.git_branch' # Should show feature-branch
-git checkout main
-loct '.metadata.git_branch' # Should find main snapshot or error
-```
-
-| Test ID | Scenario | Expected | Validates |
-|---------|----------|----------|-----------|
-| IT-010 | Query on branch | Branch snapshot used | Branch isolation |
-| IT-011 | Switch branch, no snapshot | Error: no snapshot | Clear error |
-
-### 7.3 Comparison with dead command
-
-```bash
-# These should produce equivalent results
-loct dead --json
-loct @dead --json
-loct '.files[] | select(.exports[] | select(.import_count == 0)) | .path'
-```
-
-| Test ID | Comparison | Expected | Validates |
-|---------|------------|----------|-----------|
-| IT-020 | @dead vs dead command | Same results | Preset matches command |
-| IT-021 | Filter vs preset | Same results | Filter equivalent |
-
----
-
-## 8. Performance Tests
-
-### 8.1 Large snapshot handling
-
-| Test ID | Scenario | Metric | Threshold | Validates |
-|---------|----------|--------|-----------|-----------|
-| PT-001 | 10k files snapshot | Query time | < 100ms | Fast queries |
-| PT-002 | 100k edges snapshot | Filter time | < 500ms | Edge handling |
-| PT-003 | Deep nesting filter | Memory | < 100MB | Memory bound |
-
-### 8.2 Repeated queries
-
-| Test ID | Scenario | Expected | Validates |
-|---------|----------|----------|-----------|
-| PT-010 | 100 sequential queries | Consistent time | No degradation |
-| PT-011 | Parallel queries | All succeed | Thread safety |
-
----
-
-## 9. Test Fixtures Required
-
-### 9.1 Fixture: simple_ts_for_query
-
-```
-simple_ts_for_query/
- .loctree/
- snapshot.json # Pre-generated snapshot
- src/
- index.ts # Main entry
- utils/
- helper.ts # Used by index
- unused.ts # Dead export
- types.ts # Shared types
-```
-
-Snapshot should contain:
-- 4 files
-- At least 3 edges
-- 1 dead export in unused.ts
-- metadata with git info
-
-### 9.2 Fixture: multi_snapshot
-
-```
-multi_snapshot/
- .loctree/
- snapshot.json # Current
- main@abc1234/snapshot.json # Old main
- develop@def5678/snapshot.json # Old develop
-```
-
-### 9.3 Fixture: empty_snapshot
-
-```
-empty_snapshot/
- .loctree/
- snapshot.json # Valid but empty: {metadata: {...}, files: [], edges: []}
-```
-
-### 9.4 Fixture: invalid_snapshots
-
-```
-invalid_snapshots/
- broken.json # Invalid JSON
- old_schema.json # Valid JSON, wrong schema version
- missing_fields.json # Missing required fields
-```
-
----
-
-## 10. Implementation Notes
-
-### 10.1 Recommended jq library
-
-For Rust implementation, consider:
-- `jaq` crate (Rust-native jq implementation)
-- `serde_json` + custom evaluator
-- Shell out to `jq` binary (simpler but requires jq installed)
-
-### 10.2 Filter detection regex
-
-```rust
-fn is_filter_expression(arg: &str) -> bool {
- let arg = arg.trim();
- // Dot-prefix: .metadata, .files[], etc.
- if arg.starts_with('.') {
- return true;
- }
- // Bracket-prefix: [.metadata], [.files[]]
- if arg.starts_with('[') && arg.ends_with(']') {
- return true;
- }
- // Pipe expression without leading dot: length, keys, etc.
- // These would need explicit `loct query` prefix
- false
-}
-
-fn is_preset(arg: &str) -> bool {
- arg.starts_with('@')
-}
-```
-
-### 10.3 Snapshot discovery algorithm
-
-```rust
-fn find_snapshot(explicit: Option<&Path>) -> Result {
- // 1. Explicit path takes precedence
- if let Some(path) = explicit {
- return Ok(path.to_path_buf());
- }
-
- // 2. Search upward for .loctree directory
- let mut current = std::env::current_dir()?;
- loop {
- let loctree_dir = current.join(".loctree");
- if loctree_dir.exists() {
- // 3. Find newest snapshot in directory
- return find_newest_snapshot(&loctree_dir);
- }
- if !current.pop() {
- break;
- }
- }
-
- Err(anyhow!("No snapshot found. Run `loct scan` first."))
-}
-```
-
----
-
-## Appendix A: Expected CLI Help Text
-
-```
-loct query - Query snapshot data with jq-style filters
-
-USAGE:
- loct # Direct filter (starts with . or [)
- loct @ [args] # Preset query
- loct query [OPTIONS] # Explicit query command
-
-FILTERS:
- .metadata Access metadata object
- .files[] Iterate over files
- .edges[] | select(.to == "x") Filter edges
- .files | length Count files
-
-PRESETS:
- @imports Files that import
- @exports Symbols exported by
- @consumers Files consuming
- @dead Dead exports list
-
-OUTPUT OPTIONS:
- -r, --raw-output Output strings without quotes
- -c, --compact-output Compact JSON (no pretty-print)
- -e, --exit-status Set exit code based on result
-
-SNAPSHOT OPTIONS:
- --snapshot Use specific snapshot file
-
-EXAMPLES:
- loct '.metadata.git_branch'
- loct '.files[] | select(.loc > 500) | .path' -r
- loct @imports src/utils.ts
- loct '.edges | length' -e
-```
-
----
-
-## Appendix B: Snapshot Schema Reference
-
-```json
-{
- "metadata": {
- "schema_version": "0.5.0-rc",
- "generated_at": "2025-12-11T10:30:00Z",
- "roots": ["/path/to/project"],
- "languages": ["ts", "rs"],
- "file_count": 100,
- "total_loc": 5000,
- "scan_duration_ms": 500,
- "git_repo": "Loctree",
- "git_branch": "develop",
- "git_commit": "abc1234"
- },
- "files": [
- {
- "path": "src/index.ts",
- "loc": 50,
- "language": "ts",
- "kind": "code",
- "is_test": false,
- "is_generated": false,
- "imports": [...],
- "exports": [
- {"name": "main", "kind": "function", "export_type": "named", "line": 10}
- ]
- }
- ],
- "edges": [
- {"from": "src/app.ts", "to": "src/utils.ts", "label": "import"},
- {"from": "src/index.ts", "to": "src/types.ts", "label": "reexport"}
- ],
- "barrels": [...],
- "export_index": {...},
- "command_bridges": [...],
- "event_bridges": [...]
-}
-```
-
----
-
-## Revision History
-
-| Version | Date | Author | Changes |
-|---------|------|--------|---------|
-| 1.0 | 2025-12-11 | AI Agent | Initial test plan design |
diff --git a/docs/dev/.TL_DR/00_mcp_quickstart.md b/docs/dev/.TL_DR/00_mcp_quickstart.md
deleted file mode 100644
index 43bdcbc4..00000000
--- a/docs/dev/.TL_DR/00_mcp_quickstart.md
+++ /dev/null
@@ -1,272 +0,0 @@
-# MCP Stack Quick Start
-
-## 1. Clone and install
-
-```bash
-# Clone to any directory you like
-git clone https://github.com/Loctree/loctree-suite.git
-cd loctree-suite
-
-# Install MCP binaries (rmcp-mux, rmcp-mux-proxy, loctree-mcp, rmcp_memex)
-make mcp-install
-```
-
-Alternatively, for the full suite including `loct` and `loctree` CLI:
-```bash
-make install-all
-```
-
-## 2. Setup directories
-
-```bash
-make mux-setup
-```
-
-Creates:
-```
-~/.rmcp_servers/
-├── config/mux.toml # <-- EDIT THIS
-├── logs/
-├── pids/
-└── sockets/
-```
-
-## 3. Configure mux.toml
-
-Copy example config (run from repo root):
-```bash
-cp docs/dev/.TL_DR/config-files/mux.toml ~/.rmcp_servers/config/mux.toml
-```
-
-**IMPORTANT**: Edit `~/.rmcp_servers/config/mux.toml` and replace all occurrences of:
-- `/Users/YOURUSER/` → your actual home path (e.g., `/Users/monika/`)
-- `YOUR_BRAVE_API_KEY_HERE` → your Brave Search API key
-- `YOUR_GITHUB_TOKEN_HERE` → your GitHub personal access token
-
-## 4. Configure Claude Code
-
-Add to `~/.claude.json` (merge into existing `mcpServers` section):
-```bash
-cat docs/dev/.TL_DR/config-files/.claude/.claude.json
-```
-
-## 5. Start rmcp-mux
-
-```bash
-make mux-start
-```
-
-This starts a **single rmcp-mux process** that manages ALL servers from `mux.toml`.
-
-## 6. Verify
-
-```bash
-# Quick check via Makefile
-make mux-status
-
-# Or query the daemon directly for detailed info
-rmcp-mux daemon-status
-```
-
-Expected output from `daemon-status`:
-```
-rmcp-mux v0.3.4 | uptime: 5s
-────────────────────────────────────────────────────────────────────────
-Server State Clients Pending Restarts Heartbeat
-────────────────────────────────────────────────────────────────────────
-brave-search ✓ START 0/3 0 0 -
-loctree ✓ UP 0/5 0 0 -
-rmcp-memex ✓ UP 0/5 0 0 -
-youtube-transcript ✓ START 0/3 0 0 -
-────────────────────────────────────────────────────────────────────────
-Total: 4 servers (4 running, 0 errors)
-```
-
-Legend: `UP` = running, `START` = lazy (starts on first connection), `FAIL` = error
-
-## Commands
-
-| Command | Description |
-|---------|-------------|
-| `make mux-start` | Start rmcp-mux (manages all servers) |
-| `make mux-stop` | Stop rmcp-mux |
-| `make mux-restart` | Restart rmcp-mux |
-| `make mux-status` | Show status of all servers |
-| `make mux-kill` | Force kill rmcp-mux |
-| `make mux-tui` | Launch TUI interface |
-| `make mux-restart-service SERVICE=name` | Restart a single service |
-| `rmcp-mux daemon-status` | Query running daemon status |
-| `rmcp-mux daemon-status --json` | Get status as JSON |
-| `make mux-logs` | Tail mux.log (live) |
-| `make mcp-health` | Health check sockets |
-
-## TUI Interface
-
-Launch the multi-server TUI dashboard:
-```bash
-make mux-tui
-```
-
-Keybindings:
-- `j/k` or arrows - Navigate servers
-- `r` - Restart selected server
-- `s` - Stop selected server
-- `S` - Start selected server
-- `q` - Quit
-
-## CLI Flags
-
-Direct `rmcp-mux` usage:
-
-```bash
-# Start all servers from config (default)
-rmcp-mux --config ~/.rmcp_servers/config/mux.toml
-
-# Start only specific servers
-rmcp-mux --config mux.toml --only loctree,rmcp-memex
-
-# Start all except some servers
-rmcp-mux --config mux.toml --except youtube-transcript
-
-# Show status of all configured servers
-rmcp-mux --show-status --config mux.toml
-
-# Restart a specific service
-rmcp-mux --restart-service memex --config mux.toml
-```
-
-## Running Multiple Instances of the Same Server
-
-When you need multiple instances of the same MCP server (e.g., two rmcp-memex with different databases), **each instance MUST have a unique socket path**.
-
-### Example: Two rmcp-memex instances
-
-In `mux.toml`:
-```toml
-[servers.rmcp-memex]
-socket = "~/.rmcp_servers/sockets/rmcp-memex.sock" # Unique socket!
-cmd = "/Users/silver/.cargo/bin/rmcp_memex"
-args = ["serve", "--db-path", "~/.rmcp_servers/rmcp_memex/lancedb"]
-
-[servers.rmcp-memex-ollama]
-socket = "~/.rmcp_servers/sockets/rmcp-memex-ollama.sock" # Different socket!
-cmd = "/Users/silver/.cargo/bin/rmcp_memex"
-args = ["serve", "--db-path", "/path/to/other/lancedb"]
-```
-
-In `~/.claude.json`:
-```json
-{
- "mcpServers": {
- "rmcp-memex": {
- "command": "rmcp-mux",
- "args": ["proxy", "--socket", "/Users/silver/.rmcp_servers/sockets/rmcp-memex.sock"]
- },
- "rmcp-memex-ollama": {
- "command": "rmcp-mux",
- "args": ["proxy", "--socket", "/Users/silver/.rmcp_servers/sockets/rmcp-memex-ollama.sock"]
- }
- }
-}
-```
-
-### Key Rules
-
-1. **Socket path must be unique per instance** - two servers cannot share a socket
-2. **Server name in mux.toml must be unique** - this becomes the service name
-3. **MCP server name in claude.json can be anything** - this is what Claude sees
-4. **Same binary, different args** - the `cmd` can be identical, only args differ
-5. **SLED_PATH required when sharing LanceDB** - see below
-
-### Sharing LanceDB Between Instances
-
-If multiple rmcp-memex instances point to the **same** LanceDB path (e.g., for different Claude sessions accessing shared knowledge), each instance needs its own sled K/V cache:
-
-```toml
-[servers.memex-session-1]
-socket = "~/.rmcp_servers/sockets/memex-1.sock"
-cmd = "rmcp_memex"
-args = ["serve", "--db-path", "/shared/lancedb"]
-env = { SLED_PATH = "~/.rmcp_servers/sled/memex-1" } # Unique sled!
-
-[servers.memex-session-2]
-socket = "~/.rmcp_servers/sockets/memex-2.sock"
-cmd = "rmcp_memex"
-args = ["serve", "--db-path", "/shared/lancedb"] # Same LanceDB OK
-env = { SLED_PATH = "~/.rmcp_servers/sled/memex-2" } # Different sled!
-```
-
-**Why?** Sled is an embedded K/V store that requires exclusive file locking. Without unique `SLED_PATH`, you'll get:
-```
-Error: could not acquire lock on ".../.sled/db": Resource temporarily unavailable
-```
-
-### Common Mistake
-
-```toml
-# WRONG - same socket for different instances!
-[servers.memex-1]
-socket = "~/.rmcp_servers/sockets/memex.sock" # Same socket
-cmd = "rmcp_memex"
-args = ["serve", "--db-path", "/db1"]
-
-[servers.memex-2]
-socket = "~/.rmcp_servers/sockets/memex.sock" # Conflict!
-cmd = "rmcp_memex"
-args = ["serve", "--db-path", "/db2"]
-```
-
-## Troubleshooting
-
-### Server won't start
-```bash
-# Check logs
-tail -100 ~/.rmcp_servers/logs/mux.log
-
-# Common issue: wrong path in mux.toml
-# Fix: use FULL paths, not ~/
-```
-
-### Sled lock conflict (multiple memex instances)
-```
-Error: could not acquire lock on ".../.sled/db": Resource temporarily unavailable
-```
-**Fix**: Add unique `SLED_PATH` env var for each instance sharing the same LanceDB.
-See "Sharing LanceDB Between Instances" section above.
-
-### Socket exists but server dead
-```bash
-make mux-kill # removes pids and sockets
-make mux-start
-```
-
-### Claude Code can't connect
-1. Check server is running: `make mux-status`
-2. Check socket exists: `ls ~/.rmcp_servers/sockets/`
-3. Restart Claude Code
-
-## Architecture
-
-```
-Claude Code
- │
- ▼ (spawns)
-rmcp-mux proxy --socket ~/.rmcp_servers/sockets/loctree.sock
- │
- ▼ (Unix socket)
-rmcp-mux daemon (SINGLE PROCESS - manages ALL servers)
- │
- ├── loctree-mcp (child process)
- ├── rmcp_memex (child process)
- ├── brave-search (child process)
- ├── sequential-thinking (child process)
- └── youtube-transcript (child process)
-```
-
-Benefits:
-- **Single process** manages all MCP servers
-- One PID to track, one log to tail
-- Atomic start/stop/restart
-- Centralized TUI dashboard
-- Shared Tokio runtime (memory efficient)
-- Fast reconnection (no cold start)
diff --git a/docs/dev/.TL_DR/config-files/.claude/.claude.json b/docs/dev/.TL_DR/config-files/.claude/.claude.json
deleted file mode 100644
index fbff6e54..00000000
--- a/docs/dev/.TL_DR/config-files/.claude/.claude.json
+++ /dev/null
@@ -1,29 +0,0 @@
-{
- "_comment": "Add this mcpServers block to ~/.claude.json",
- "_important": "Replace /Users/YOURUSER with your actual home path!",
- "_architecture": "rmcp-mux runs as single daemon managing ALL servers. Proxy subcommand bridges Claude to mux sockets.",
-
- "mcpServers": {
- "loctree": {
- "command": "/Users/YOURUSER/.cargo/bin/rmcp-mux",
- "args": ["proxy", "--socket", "/Users/YOURUSER/.rmcp_servers/sockets/loctree.sock"],
- "description": "Semantic codebase analysis - USE THIS BEFORE grep/search!"
- },
- "rmcp-memex": {
- "command": "/Users/YOURUSER/.cargo/bin/rmcp-mux",
- "args": ["proxy", "--socket", "/Users/YOURUSER/.rmcp_servers/sockets/rmcp-memex.sock"]
- },
- "brave-search": {
- "command": "/Users/YOURUSER/.cargo/bin/rmcp-mux",
- "args": ["proxy", "--socket", "/Users/YOURUSER/.rmcp_servers/sockets/brave-search.sock"]
- },
- "sequential-thinking": {
- "command": "/Users/YOURUSER/.cargo/bin/rmcp-mux",
- "args": ["proxy", "--socket", "/Users/YOURUSER/.rmcp_servers/sockets/sequential-thinking.sock"]
- },
- "youtube-transcript": {
- "command": "/Users/YOURUSER/.cargo/bin/rmcp-mux",
- "args": ["proxy", "--socket", "/Users/YOURUSER/.rmcp_servers/sockets/youtube-transcript.sock"]
- }
- }
-}
diff --git a/docs/dev/.TL_DR/config-files/.codex/config.toml b/docs/dev/.TL_DR/config-files/.codex/config.toml
deleted file mode 100644
index 93f44fef..00000000
--- a/docs/dev/.TL_DR/config-files/.codex/config.toml
+++ /dev/null
@@ -1,36 +0,0 @@
-# Codex MCP Configuration
-# Location: ~/.codex/config.toml
-#
-# ARCHITECTURE: rmcp-mux runs as single daemon managing ALL servers.
-# The `rmcp-mux proxy` subcommand bridges Codex STDIO to mux Unix sockets.
-#
-# IMPORTANT: Replace /Users/YOURUSER with your actual home path!
-
-# =============================================================================
-# MCP Servers (via rmcp-mux proxy subcommand)
-# =============================================================================
-
-[mcp_servers.loctree]
-command = "/Users/YOURUSER/.cargo/bin/rmcp-mux"
-args = ["proxy", "--socket", "/Users/YOURUSER/.rmcp_servers/sockets/loctree.sock"]
-startup_timeout_sec = 5
-
-[mcp_servers.rmcp-memex]
-command = "/Users/YOURUSER/.cargo/bin/rmcp-mux"
-args = ["proxy", "--socket", "/Users/YOURUSER/.rmcp_servers/sockets/rmcp-memex.sock"]
-startup_timeout_sec = 5
-
-[mcp_servers.brave-search]
-command = "/Users/YOURUSER/.cargo/bin/rmcp-mux"
-args = ["proxy", "--socket", "/Users/YOURUSER/.rmcp_servers/sockets/brave-search.sock"]
-startup_timeout_sec = 60
-
-[mcp_servers.sequential-thinking]
-command = "/Users/YOURUSER/.cargo/bin/rmcp-mux"
-args = ["proxy", "--socket", "/Users/YOURUSER/.rmcp_servers/sockets/sequential-thinking.sock"]
-startup_timeout_sec = 60
-
-[mcp_servers.youtube-transcript]
-command = "/Users/YOURUSER/.cargo/bin/rmcp-mux"
-args = ["proxy", "--socket", "/Users/YOURUSER/.rmcp_servers/sockets/youtube-transcript.sock"]
-startup_timeout_sec = 60
diff --git a/docs/dev/.TL_DR/config-files/mux.toml b/docs/dev/.TL_DR/config-files/mux.toml
deleted file mode 100644
index 346d1729..00000000
--- a/docs/dev/.TL_DR/config-files/mux.toml
+++ /dev/null
@@ -1,141 +0,0 @@
-# rmcp-mux Configuration Template
-# Location: ~/.rmcp-servers/config/mux.toml
-#
-# ARCHITECTURE: Single rmcp-mux process manages ALL servers defined here.
-# Start with: rmcp-mux --config ~/.rmcp-servers/config/mux.toml
-# or: make mux-start
-#
-# IMPORTANT: Replace /Users/YOURUSER with your actual home path!
-# The ~ shorthand works for socket paths but NOT for cmd paths.
-#
-# =============================================================================
-# PARAMETER REFERENCE
-# =============================================================================
-#
-# socket - Unix socket path (required, supports ~)
-# cmd - Command to run (required)
-# args - Command arguments (default: [])
-# env - Environment variables (default: {})
-# max_active_clients - Max concurrent clients (default: 5)
-# lazy_start - Start on first request vs immediately (default: false)
-# false = eager, starts with daemon
-# true = lazy, spawns on first connection
-# heartbeat_enabled - Enable health check pings (default: true)
-# Set to false for servers that don't implement MCP ping
-# tray - Show in system tray (default: false)
-#
-# =============================================================================
-# Core Servers (eager start - always running)
-# =============================================================================
-
-[servers.loctree]
-socket = "~/.rmcp-servers/sockets/loctree.sock"
-cmd = "/Users/YOURUSER/.cargo/bin/loctree-mcp"
-args = []
-env = {}
-max_active_clients = 5
-lazy_start = false
-tray = false
-heartbeat_enabled = false # loctree-mcp doesn't implement MCP ping yet
-
-[servers.rmcp-memex]
-socket = "~/.rmcp-servers/sockets/rmcp-memex.sock"
-cmd = "/Users/YOURUSER/.cargo/bin/rmcp_memex"
-args = [
- "serve",
- "--config", "/Users/YOURUSER/.rmcp-servers/rmcp_memex/config.toml",
- "--db-path", "/Users/YOURUSER/.ai-memories/lancedb",
- "--log-level", "info"
-]
-env = { SLED_PATH = "/Users/YOURUSER/.rmcp-servers/sled/memex" }
-max_active_clients = 5
-lazy_start = false
-tray = false
-heartbeat_enabled = false # rmcp_memex doesn't implement MCP ping yet
-
-# =============================================================================
-# Utility Servers (lazy start - spawn on first request)
-# =============================================================================
-
-[servers.brave-search]
-socket = "~/.rmcp-servers/sockets/brave-search.sock"
-cmd = "npx"
-args = ["-y", "@brave/brave-search-mcp-server"]
-env = { BRAVE_API_KEY = "YOUR_BRAVE_API_KEY_HERE" }
-max_active_clients = 3
-lazy_start = true
-heartbeat_enabled = false # NPX servers don't implement MCP ping
-
-[servers.sequential-thinking]
-socket = "~/.rmcp-servers/sockets/sequential-thinking.sock"
-cmd = "npx"
-args = ["-y", "@modelcontextprotocol/server-sequential-thinking"]
-env = {}
-max_active_clients = 3
-lazy_start = true
-heartbeat_enabled = false
-
-[servers.youtube-transcript]
-socket = "~/.rmcp-servers/sockets/youtube-transcript.sock"
-cmd = "npx"
-args = ["-y", "@kazuph/mcp-youtube"]
-env = {}
-max_active_clients = 3
-lazy_start = true
-heartbeat_enabled = false
-
-# =============================================================================
-# Optional Servers (uncomment if needed)
-# =============================================================================
-
-# [servers.github]
-# socket = "~/.rmcp-servers/sockets/github.sock"
-# cmd = "npx"
-# args = ["-y", "@modelcontextprotocol/server-github"]
-# env = { GITHUB_PERSONAL_ACCESS_TOKEN = "YOUR_GITHUB_TOKEN_HERE" }
-# max_active_clients = 3
-# lazy_start = true
-# heartbeat_enabled = false
-
-# [servers.memory]
-# socket = "~/.rmcp-servers/sockets/memory.sock"
-# cmd = "npx"
-# args = ["-y", "@modelcontextprotocol/server-memory"]
-# env = { MEMORY_FILE_PATH = "/Users/YOURUSER/AI_memory/memory.json" }
-# max_active_clients = 3
-# lazy_start = true
-# heartbeat_enabled = false
-
-# [servers.curl]
-# socket = "~/.rmcp-servers/sockets/curl.sock"
-# cmd = "npx"
-# args = ["-y", "@mcp-get-community/server-curl"]
-# env = {}
-# max_active_clients = 3
-# lazy_start = true
-# heartbeat_enabled = false
-
-# =============================================================================
-# CLI Usage Examples
-# =============================================================================
-#
-# Start all servers:
-# rmcp-mux --config ~/.rmcp-servers/config/mux.toml
-# make mux-start
-#
-# Check status:
-# rmcp-mux daemon-status # Query running daemon
-# rmcp-mux daemon-status --json # JSON output
-# make mux-status
-#
-# Start only specific servers:
-# rmcp-mux --config mux.toml --only loctree,rmcp-memex
-#
-# Start all except some:
-# rmcp-mux --config mux.toml --except youtube-transcript
-#
-# Restart single service:
-# rmcp-mux --restart-service memex --config mux.toml
-#
-# TUI dashboard:
-# make mux-tui
diff --git a/docs/dev/00_readme.md b/docs/dev/00_readme.md
deleted file mode 100644
index d1e56a49..00000000
--- a/docs/dev/00_readme.md
+++ /dev/null
@@ -1,57 +0,0 @@
-# Loctree Developer Docs
-
-Technical notes for contributors working inside the public `loctree-ast`
-workspace.
-
-## Primary Docs
-
-| Document | Purpose |
-|----------|---------|
-| [01_installation.md](01_installation.md) | Install, verify, and update the workspace |
-| [02_architecture.md](02_architecture.md) | Current workspace shape and blast-radius hubs |
-| [03_cli_reference.md](03_cli_reference.md) | CLI contract and developer reference |
-
-## Quick Start
-
-```bash
-git clone https://github.com/Loctree/loctree-ast.git
-cd loctree-ast
-make install
-make precheck
-```
-
-## Workspace Crates
-
-The public workspace currently ships these members:
-
-| Crate | Version | Purpose |
-|-------|---------|---------|
-| `loctree` | 0.8.17 | Core analyzer + CLI (`loct`, `loctree`) |
-| `loctree-mcp` | 0.8.17 | MCP server |
-| `report-leptos` | 0.8.17 | HTML report renderer |
-| `rmcp-common` | 0.8.17 | Shared MCP/common utilities |
-
-## Binaries
-
-| Binary | Purpose |
-|--------|---------|
-| `loct` | Canonical CLI |
-| `loctree` | Quiet compatibility alias for `loct` |
-| `loctree-mcp` | MCP server |
-
-## External Surfaces
-
-These are part of the broader Loctree ecosystem, but not members of this
-workspace:
-
-- `loctree-suite` for editor/LSP surfaces
-- thin release repos: `Loctree/loct` and `Loctree/loctree-mcp`
-- Homebrew taps: `Loctree/homebrew-cli` and `Loctree/homebrew-mcp`
-
-## Core Gates
-
-```bash
-make precheck # fast repo-wide check
-make check # fmt + clippy + cargo check + semgrep
-make test # workspace tests
-```
diff --git a/docs/dev/01_installation.md b/docs/dev/01_installation.md
deleted file mode 100644
index b321dcdf..00000000
--- a/docs/dev/01_installation.md
+++ /dev/null
@@ -1,217 +0,0 @@
-# Loctree - Installation Guide
-
-Complete installation guide for the public Loctree OSS workspace.
-
-## Quick Start
-
-```bash
-# Fastest public install path: CLI + MCP server
-curl -fsSL https://loct.io/install.sh | sh
-
-# Cargo alternative (reproducible lockfile build)
-cargo install --locked loctree loctree-mcp
-
-# Or from source
-git clone https://github.com/Loctree/loctree-ast.git
-cd loctree-ast
-make install
-```
-
-Public install channels follow the latest published release, which can lag
-behind the workspace version on this branch. Verify the exact published version
-on crates.io, npm, or GitHub Releases when you need release-exact behavior.
-
-## What Gets Installed
-
-| Binary | Crate | Description |
-|--------|-------|-------------|
-| `loct` | loctree | Primary CLI - fast, agent-optimized |
-| `loctree` | loctree | Compatibility alias for `loct` |
-| `loctree-mcp` | loctree-mcp | MCP server for AI agents (Claude, Cursor, etc.) |
-
-## Installation Methods
-
-### 1. One-Liner Installer
-
-```bash
-curl -fsSL https://loct.io/install.sh | sh
-```
-
-The installer defaults to `loctree + loctree-mcp`. Set `INSTALL_MCP=0` only if
-you explicitly want CLI-only.
-
-### 2. Cargo (Recommended)
-
-```bash
-cargo install --locked loctree loctree-mcp
-```
-
-### 3. Homebrew (macOS/Linux)
-
-```bash
-brew install loctree/cli/loct
-brew install loctree/mcp/loctree-mcp
-```
-
-Use one global channel per machine. If you already installed Loctree globally
-via Homebrew, avoid `npm install -g loctree` on the same setup unless you first
-remove the existing global binaries.
-
-### 4. npm (CLI only)
-
-```bash
-npm install -g loctree
-```
-
-Supported npm targets are defined by the latest published npm release. Alpine
-/musl should use Cargo or direct release assets instead.
-
-This installs the CLI only. Install `loctree-mcp` separately via Cargo,
-Homebrew, or GitHub Releases if your workflow needs MCP.
-
-### 5. Direct GitHub Release Assets
-
-The monorepo release page is the public fallback for installable CLI and MCP
-tarballs. Thin release repos are part of the release choreography and may lag
-while assets are being mirrored:
-
-- CLI: `Loctree/loct`
-- MCP: `Loctree/loctree-mcp`
-
-### 6. From Source
-
-```bash
-git clone https://github.com/Loctree/loctree-ast.git
-cd loctree-ast
-make install
-```
-
-## Clean-Room macOS Note
-
-The public release binaries use vendored `libgit2`, so macOS release artifacts
-do not depend on Homebrew runtime paths such as `/opt/homebrew/opt/libgit2/...`.
-
-For a reproducible local verification on Apple Silicon:
-
-```bash
-make smoke-release-macos-arm64
-```
-
-## Workspace Structure
-
-```text
-Loctree/
-├── loctree_rs/ # Core library + CLI (loct, loctree)
-├── loctree-mcp/ # MCP server for loctree
-├── rmcp-common/ # Shared MCP/common utilities
-├── reports/ # Leptos-based HTML reports
-└── distribution/ # Release/install channels and packaging docs
-```
-
-## Configuration
-
-### MCP Server Setup (Claude Code / Cursor)
-
-Add to your MCP config (`~/.config/claude/claude_desktop_config.json` or similar):
-
-```json
-{
- "mcpServers": {
- "loctree": {
- "command": "loctree-mcp",
- "args": []
- }
- }
-}
-```
-
-## Verification
-
-```bash
-# Check versions
-loct --version
-loctree --version
-loctree-mcp --version
-
-# Test loctree on current directory
-loct
-
-# Test MCP server
-echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}' | loctree-mcp
-```
-
-## Makefile Targets
-
-```bash
-make install # Install loct, loctree, loctree-mcp
-make install-cli # Install only loct + loctree
-make install-mcp # Install only loctree-mcp
-make build # Build all crates (release)
-make build-core # Build only core
-make precheck # Fast repo-wide gate
-make test # Run all workspace tests
-make check # Run the full quality gate
-make fmt # Format code
-make clean # Clean build artifacts
-make mcp-build # Build loctree-mcp
-make smoke-release-macos-arm64 # Verify macOS arm64 release portability
-```
-
-## Troubleshooting
-
-### Build Lock Conflict
-
-```text
-Another build running (PID xxxx). Aborting.
-```
-
-Solution:
-
-```bash
-make unlock
-```
-
-### Cargo Install Conflicts
-
-If you have both crates.io and local versions:
-
-```bash
-cargo uninstall loctree loctree-mcp
-make install
-```
-
-## Platform Support
-
-| Platform | CLI | MCP | Notes |
-|----------|-----|-----|-------|
-| macOS (Apple Silicon) | Full | Full | Primary releaseability target |
-| macOS (Intel) | Full | Full | Built in release workflow |
-| Linux (x86_64 glibc) | Full | Full | Built in release workflow |
-| Windows (x86_64) | Full | Full | Built in release workflow |
-
-## Updating
-
-```bash
-# From crates.io
-cargo install --locked loctree loctree-mcp --force
-
-# From source
-git pull
-make install
-```
-
-## Uninstalling
-
-```bash
-# Cargo-installed binaries
-cargo uninstall loctree loctree-mcp
-
-# Or manually
-rm ~/.cargo/bin/loct
-rm ~/.cargo/bin/loctree
-rm ~/.cargo/bin/loctree-mcp
-```
-
----
-
-𝚅𝚒𝚋𝚎𝚌𝚛𝚊𝚏𝚝𝚎𝚍. with AI Agents ⓒ 2025-2026 Loctree Team
diff --git a/docs/dev/02_architecture.md b/docs/dev/02_architecture.md
deleted file mode 100644
index fc97e6c5..00000000
--- a/docs/dev/02_architecture.md
+++ /dev/null
@@ -1,74 +0,0 @@
-# Loctree Architecture
-
-Current architecture of the public `loctree-ast` workspace.
-
-## Workspace Layout
-
-```text
-loctree-ast/
-├── Cargo.toml # workspace manifest
-├── Makefile # build, install, release, and smoke gates
-├── loctree_rs/ # core library + CLI binaries
-├── loctree-mcp/ # MCP server
-├── rmcp-common/ # shared MCP/common utilities
-├── reports/ # Leptos-based HTML reports
-├── distribution/ # install and release channel contracts
-├── docs/ # user + developer docs
-├── scripts/ # release/install helpers
-└── tools/ # hooks and fixtures
-```
-
-## Crate Graph
-
-```text
- loctree (loctree_rs)
- / \
- / \
- loctree-mcp report-leptos
- \
- \
- rmcp-common
-```
-
-`reports/wasm` is a sub-crate under the report renderer for WASM assets.
-
-## High-Risk Hubs
-
-These files carry the largest blast radius in the live tree:
-
-- `loctree_rs/src/types.rs`
-- `loctree_rs/src/snapshot.rs`
-- `reports/src/types.rs`
-
-Before heavy edits, follow the repo discipline:
-
-```text
-repo-view -> focus -> slice -> impact -> find -> follow
-```
-
-## Distribution Shape
-
-The monorepo is the source of truth for code, CI, and release choreography.
-
-User-facing binary distribution is split outward into thin repos and taps:
-
-- CLI release repo: `Loctree/loct`
-- MCP release repo: `Loctree/loctree-mcp`
-- CLI tap: `Loctree/homebrew-cli`
-- MCP tap: `Loctree/homebrew-mcp`
-
-Those release channels are orchestrated from `.github/workflows/publish.yml` and
-`distribution/`.
-
-## What Is Not In This Workspace
-
-Older docs sometimes referred to directories that no longer live here. The
-public workspace does **not** contain:
-
-- `landing/`
-- `rmcp-mux/`
-- `rmcp-memex/`
-- `loctree_memex/`
-
-Editor/LSP surfaces live in the external `loctree-suite` project rather than
-this workspace.
diff --git a/docs/dev/03_cli_reference.md b/docs/dev/03_cli_reference.md
deleted file mode 100644
index 22c18e5c..00000000
--- a/docs/dev/03_cli_reference.md
+++ /dev/null
@@ -1,134 +0,0 @@
-# Loctree - CLI Reference
-
-Truthful reference for the public Loctree command surface in this repo.
-
-## loct
-
-`loct` is the canonical CLI. It auto-scans by default, writes artifacts to the
-user cache dir (override with `LOCT_CACHE_DIR`), and lets you query the same
-snapshot through focused commands.
-
-### Everyday usage
-
-```bash
-loct # Default auto-scan for current directory
-loct /path/to/project # Auto-scan a specific project
-loct --fresh # Force rescan even if snapshot exists
-loct --for-ai # AI context bundle (JSONL)
-loct --agent-json # Single agent bundle JSON
-```
-
-### Query mode
-
-```bash
-loct '.metadata'
-loct '.files | length'
-loct '.summary.health_score'
-loct '.dead_parrots[]'
-loct '.cycles[]'
-```
-
-### Core commands
-
-```bash
-loct findings # Canonical findings JSON
-loct findings --summary # Summary JSON for CI / status checks
-loct slice src/App.tsx --consumers
-loct find useAuth
-loct impact src/utils/api.ts
-loct health
-loct dead --confidence high
-loct cycles
-loct twins
-loct audit
-loct doctor
-loct lint --fail --sarif > loctree.sarif
-loct report --serve --port 4173
-```
-
-### Common flags
-
-| Flag | Description |
-|------|-------------|
-| `--fresh` | Force rescan even if snapshot exists |
-| `--json` | JSON output on commands that support it |
-| `--for-ai` | AI-optimized JSONL stream |
-| `--agent-json` | One-shot agent bundle JSON |
-| `--quiet`, `-q` | Suppress non-essential output |
-| `--verbose` | Show detailed progress |
-| `--fail-stale` | Fail if cached snapshot is stale |
-
-Notes:
-- Prefer `loct findings` over the legacy bare `loct --findings` shortcut in new docs and scripts.
-- Use `loct findings --summary` for summary JSON. The `--summary` flag still belongs on commands like `loct tree`.
-
-## loctree
-
-`loctree` is the quiet compatibility alias for `loct`. Keep using `loct` in new
-examples; use `loctree` only when preserving older scripts or operator muscle
-memory.
-
-## loctree-mcp
-
-`loctree-mcp` is the production MCP server for this workspace. It runs over
-stdio and auto-scans a project on first use when no snapshot exists.
-
-### Usage
-
-```bash
-loctree-mcp
-loctree-mcp --version
-```
-
-### MCP tools
-
-| Tool | Description |
-|------|-------------|
-| `repo-view` | Repo overview: files, LOC, languages, health, top hubs |
-| `slice` | File + dependencies + consumers in one call |
-| `find` | Symbol search and reverse-import lookups |
-| `impact` | Direct + transitive consumer blast radius |
-| `focus` | Module/directory deep-dive |
-| `tree` | Directory tree with LOC counts |
-| `follow` | Structural signals: dead, cycles, twins, hotspots, trace, pipelines |
-
-### Configuration
-
-```json
-{
- "mcpServers": {
- "loctree": {
- "command": "loctree-mcp",
- "args": []
- }
- }
-}
-```
-
-### Recommended agent flow
-
-```text
-repo-view -> focus -> slice -> impact -> find -> follow
-```
-
-## Exit codes
-
-| Code | Meaning |
-|------|---------|
-| `0` | Success |
-| `1` | Command reported findings or general runtime failure |
-| `2` | Invalid arguments / usage error |
-| `101` | Rust panic |
-
-## Cross-check sources
-
-When this page and the runtime ever disagree, trust these repo-owned sources:
-
-- `loctree_rs/src/bin/loct.rs`
-- `loctree_rs/src/cli/command/help.rs`
-- `loctree_rs/src/cli/parser/core.rs`
-- `loctree-mcp/src/main.rs`
-
----
-
-𝚅𝚒𝚋𝚎𝚌𝚛𝚊𝚏𝚝𝚎𝚍. with AI Agents ⓒ 2025-2026 Loctree Team
diff --git a/docs/feature-requests/claude-code-smart-hook.md b/docs/feature-requests/claude-code-smart-hook.md
deleted file mode 100644
index aa74236a..00000000
--- a/docs/feature-requests/claude-code-smart-hook.md
+++ /dev/null
@@ -1,112 +0,0 @@
-# Feature Request: Claude Code Smart Grep→loct Suggestion Hook
-
-## Summary
-
-Bundle an optional Claude Code hook that intelligently suggests `loct` commands when grep patterns would benefit from code-aware analysis. This would be installed alongside `mcp-server-loctree` configuration.
-
-## Motivation
-
-AI agents (Claude Code, Cursor, etc.) frequently use grep/ripgrep for code search. However, many search patterns would be served better by loct's semantic analysis:
-
-| grep pattern | What user wants | loct advantage |
-|--------------|-----------------|----------------|
-| `useAuthHandler` | Find hook definition + usages | `loct f` knows import chain |
-| `ChatPanel` | Find component | `loct f` shows [DEF] + consumers |
-| `run_agent` | Find Rust symbol | `loct f` works across TS+Rust |
-| `dead` / `unused` | Find dead code | `loct '.dead_parrots'` is instant |
-| `circular` | Find cycles | `loct '.cycles'` pre-indexed |
-
-## Proposed Solution
-
-### 1. New installer option
-
-```bash
-loct install-claude-hook # Interactive setup
-loct install-claude-hook -y # Auto-yes, non-interactive
-```
-
-### 2. What it installs
-
-**Hook script** → `~/.claude/hooks/loct-smart-suggest.sh`
-- Non-blocking (always exit 0)
-- Pattern detection for 12+ use cases
-- Max 3 suggestions per session (anti-spam)
-- Suggests jq-style queries where applicable
-
-**Settings update** → `~/.claude/settings.json`
-```json
-{
- "hooks": {
- "PreToolUse": [
- {
- "matcher": "Grep",
- "hooks": [{
- "type": "command",
- "command": "~/.claude/hooks/loct-smart-suggest.sh"
- }]
- }
- ]
- }
-}
-```
-
-### 3. Combined with MCP server setup
-
-The existing `mcp-server-loctree` installation could offer this as optional step:
-
-```
-$ loct mcp install
-
-Installing MCP server for Claude Code...
-✓ Added mcp-server-loctree to ~/.claude/settings.json
-
-Would you like to install the smart grep→loct suggestion hook? [Y/n]
-This shows helpful loct commands when grep patterns would benefit from code-aware search.
-
-✓ Installed hook to ~/.claude/hooks/loct-smart-suggest.sh
-✓ Added PreToolUse hook to settings.json
-
-Done! Restart Claude Code to activate.
-```
-
-## Pattern Detection Cases
-
-The hook detects when loct would genuinely help:
-
-1. **PascalCase** (`UserProfile`) → `loct f` for React components/types
-2. **useXxx hooks** (`useAuth`) → `loct f` with import chain
-3. **handleXxx/onXxx** → `loct f` for event handlers
-4. **snake_case** (`run_agent`) → `loct f` cross-language
-5. **invoke/emit** → `loct trace` for Tauri bridge
-6. **import/export** → `loct query who-imports`
-7. **dead/unused/orphan** → `loct '.dead_parrots'`
-8. **circular/cycle** → `loct '.cycles'`
-9. **duplicate/twin** → `loct '.twins'`
-10. **count/total** → `loct '.files | length'`
-
-## Example Output
-
-When Claude Code uses Grep with pattern `useAgentSlashHandler`:
-
-```
-┌─────────────────────────────────────────────────────────────
-│ 🌳 Hook search? loct shows definition + import chain
-│ → loct f useAgentSlashHandler
-└─────────────────────────────────────────────────────────────
-```
-
-## Implementation Notes
-
-- Hook reads tool input from stdin (JSON format)
-- Uses jq for parsing, falls back to grep
-- Session-based counter prevents suggestion spam
-- Zero blocking - grep always runs, just with helpful hint
-
-## Reference Implementation
-
-Working prototype at: `~/.claude/hooks/loct-smart-suggest.sh`
-(Created during Vista development session by M&K)
-
----
-
-𝚅𝚒𝚋𝚎𝚌𝚛𝚊𝚏𝚝𝚎𝚍. with AI Agents ⓒ 2025-2026 Loctree Team
diff --git a/docs/fixes/git-root-discovery.md b/docs/fixes/git-root-discovery.md
deleted file mode 100644
index 8807bf5e..00000000
--- a/docs/fixes/git-root-discovery.md
+++ /dev/null
@@ -1,284 +0,0 @@
-# Fix: Git Root Discovery from Nested Directories
-
-**Issue**: Git context missing when running loctree from subdirectories
-**Fixed in**: `v0.8.9`
-**Affected versions**: `<= v0.8.8`
-
-## Problem Description
-
-Loctree was failing to detect git repository context when invoked from nested subdirectories, git worktrees, or certain monorepo structures.
-
-### Symptoms
-
-- Snapshot paths missing `branch@commit` segment (falling back to legacy path)
-- `.gitignore` rules not being applied correctly
-- `git_context` showing `null` values in snapshot metadata
-- Different behavior depending on which directory you ran `loct` from
-
-### Example of Affected Scenario
-
-```bash
-# From project root - works
-$ cd /project
-$ loct scan
-[OK] Saved to ./.loctree/main@abc1234/snapshot.json
-
-# From nested directory - fails to detect git
-$ cd /project/src/deep/nested/module
-$ loct scan
-[OK] Saved to ./.loctree/snapshot.json # Missing branch@commit!
-```
-
-## Root Cause
-
-Two components used shell commands that assumed the working directory was already inside a git repository:
-
-### 1. GitIgnoreChecker (fs_utils.rs)
-
-```rust
-// OLD: Only works if `root` is directly in a git repo
-Command::new("git")
- .arg("-C")
- .arg(root) // <- If this isn't in a git repo, fails
- .arg("rev-parse")
- .arg("--show-toplevel")
-```
-
-### 2. get_git_info (snapshot.rs)
-
-```rust
-// OLD: Commands run with root as working directory
-Command::new("git")
- .args(["rev-parse", "--abbrev-ref", "HEAD"])
- .current_dir(root) // <- Assumes root is in a git repo
-```
-
-Neither implementation searched **upward** from the given path to find the actual `.git` directory.
-
-### When It Broke
-
-The bug manifested when loctree was called with a `root` parameter that wasn't directly inside a git repository, or when the scan was initiated from outside the repo:
-
-```
-/project/.git/ <- Git root
-/project/src/module/ <- User runs: loct scan /project/src/module
-
-# Old code did:
-git -C /project/src/module rev-parse --show-toplevel
-# This actually WORKS (git searches upward)
-
-# But GitIgnoreChecker passed absolute paths that confused the logic,
-# and get_git_info assumed current_dir was sufficient without explicit
-# upward discovery. Edge cases like worktrees (.git as file) failed.
-```
-
-The real issues were:
-1. **Inconsistent path handling** between different git operations
-2. **No explicit upward search** - relied on git's implicit behavior which varied
-3. **Worktrees not handled** - `.git` as a file broke assumptions
-
-The issue was particularly problematic for:
-- **Monorepos**: Multiple packages, running from a package subdirectory
-- **Git worktrees**: Where `.git` is a file pointing to the main repo
-- **Deep directory structures**: Common in large projects
-
-## Solution
-
-### New Utility Function
-
-Added `find_git_root()` in `git.rs` that uses libgit2's `Repository::discover()`:
-
-```rust
-/// Find the git repository root by searching upward from the given path.
-///
-/// Uses libgit2's `Repository::discover()` which properly handles:
-/// - Nested directories (searches upward to find .git)
-/// - Git worktrees (where .git is a file, not a directory)
-/// - Submodules
-///
-/// Returns `None` if no git repository is found.
-pub fn find_git_root(path: &Path) -> Option {
- Repository::discover(path)
- .ok()
- .and_then(|repo| repo.workdir().map(|p| p.to_path_buf()))
-}
-```
-
-### Updated GitIgnoreChecker
-
-```rust
-impl GitIgnoreChecker {
- pub fn new(root: &Path) -> Option {
- // Use libgit2 to find git root (searches upward properly)
- let repo_root = crate::git::find_git_root(root)?;
- Some(Self { repo_root })
- }
-}
-```
-
-### Updated get_git_info
-
-```rust
-fn get_git_info(root: &Path) -> (Option, Option, Option) {
- // Find the actual git root (searches upward from root)
- let git_root = match crate::git::find_git_root(root) {
- Some(r) => r,
- None => return (None, None, None),
- };
-
- // Now run git commands from the discovered root
- let repo = Command::new("git")
- .args(["remote", "get-url", "origin"])
- .current_dir(&git_root) // <- Use discovered root
- // ...
-}
-```
-
-## Files Changed
-
-```
-loctree_rs/src/git.rs
-├── find_git_root() - new utility function
-├── test_find_git_root_from_repo_root() - test from root
-├── test_find_git_root_from_nested_dir() - test from deep nested
-├── test_find_git_root_non_git_dir() - test non-git returns None
-├── test_find_git_root_worktree() - test worktree support
-└── test_find_git_root_nested_repo_chooses_closest() - test nested repo picks closest
-
-loctree_rs/src/fs_utils.rs
-└── GitIgnoreChecker::new() - now uses find_git_root()
-
-loctree_rs/src/snapshot.rs
-└── get_git_info() - now uses find_git_root()
-```
-
-## Testing
-
-### Before Fix
-
-```bash
-$ cd /project/src/components
-$ loct scan
-[OK] Saved to ./.loctree/snapshot.json
-# Missing branch@commit in path!
-
-$ loct '.git_context'
-{
- "repo": null,
- "branch": null,
- "commit": null,
- "scan_id": null
-}
-```
-
-### After Fix
-
-```bash
-$ cd /project/src/components
-$ loct scan
-[OK] Saved to ./.loctree/main@abc1234/snapshot.json
-
-$ loct '.git_context'
-{
- "repo": "my-project",
- "branch": "main",
- "commit": "abc1234",
- "scan_id": "main@abc1234"
-}
-```
-
-### Regression Tests
-
-```rust
-#[test]
-fn test_find_git_root_from_nested_dir() {
- let (temp_dir, _repo) = create_test_repo();
- let path = temp_dir.path();
-
- // Create deeply nested directory structure
- let nested = path.join("src").join("deep").join("nested").join("dir");
- std::fs::create_dir_all(&nested).unwrap();
-
- // find_git_root should find the repo root from nested dir
- let root = find_git_root(&nested);
- assert!(root.is_some(), "Should find git root from nested directory");
-
- let expected = temp_dir.path().canonicalize().unwrap();
- let actual = root.unwrap().canonicalize().unwrap();
- assert_eq!(actual, expected);
-}
-
-#[test]
-fn test_find_git_root_non_git_dir() {
- let temp_dir = TempDir::new().unwrap();
- let root = find_git_root(temp_dir.path());
- assert!(root.is_none(), "Should return None for non-git directory");
-}
-
-#[test]
-fn test_find_git_root_worktree() {
- let (main_dir, main_repo) = create_test_repo();
- let worktree_dir = TempDir::new().unwrap();
-
- // Create a worktree (this creates a .git file pointing to main repo)
- main_repo
- .worktree("test-worktree", worktree_dir.path(), None)
- .unwrap();
-
- // find_git_root should work from worktree
- let root = find_git_root(worktree_dir.path());
- assert!(root.is_some(), "Should find git root from worktree");
-
- let actual = root.unwrap().canonicalize().unwrap();
- let expected = worktree_dir.path().canonicalize().unwrap();
- assert_eq!(actual, expected);
-}
-
-#[test]
-fn test_find_git_root_nested_repo_chooses_closest() {
- let (outer_dir, _outer_repo) = create_test_repo();
-
- // Create an inner git repo inside the outer one
- let inner_path = outer_dir.path().join("packages").join("inner");
- std::fs::create_dir_all(&inner_path).unwrap();
- let inner_repo = Repository::init(&inner_path).unwrap();
-
- // Create a nested dir inside the inner repo
- let deep = inner_path.join("src").join("deep");
- std::fs::create_dir_all(&deep).unwrap();
-
- // find_git_root from deep should find inner repo, not outer
- let root = find_git_root(&deep);
- assert!(root.is_some(), "Should find git root");
-
- let actual = root.unwrap().canonicalize().unwrap();
- let expected = inner_path.canonicalize().unwrap();
- assert_eq!(actual, expected, "Should find closest (inner) repo, not outer");
-}
-```
-
-## Impact
-
-- Consistent git context detection regardless of working directory
-- Proper `.gitignore` application from any subdirectory
-- Correct `branch@commit` in snapshot paths
-- Support for git worktrees and submodules
-
-## Technical Notes
-
-### Why libgit2 instead of shell commands?
-
-1. **Proper upward search**: `Repository::discover()` walks up the directory tree
-2. **Worktree support**: Handles `.git` files (not just directories)
-3. **No subprocess overhead**: Native library call
-4. **Already a dependency**: Used by `GitRepo` for blame/diff features
-
-### Backwards Compatibility
-
-The fix is transparent - existing workflows continue to work, but now also work correctly from subdirectories.
-
-## Related
-
-- Git context in snapshots: `loct '.git_context'`
-- GitIgnoreChecker: `loctree_rs/src/fs_utils.rs`
-- Snapshot path resolution: `loctree_rs/src/snapshot.rs`
diff --git a/docs/fixes/inline-comments-tauri-command-detection.md b/docs/fixes/inline-comments-tauri-command-detection.md
deleted file mode 100644
index 72dcd74b..00000000
--- a/docs/fixes/inline-comments-tauri-command-detection.md
+++ /dev/null
@@ -1,181 +0,0 @@
-# Fix: Comments Breaking Tauri Command Detection
-
-**Issue**: False "missing handler" reports for valid `#[tauri::command]` functions
-**Fixed in**: `v0.8.9`
-**Affected versions**: `<= v0.8.8`
-
-## Problem Description
-
-Loctree was failing to detect Tauri command handlers when comments appeared after attributes.
-
-### Example of Affected Code
-
-```rust
-#[tauri::command]
-#[allow(non_snake_case)] // camelCase param matches frontend convention
-pub async fn process_data(
- app_handle: tauri::AppHandle,
- inputData: Vec,
-) -> Result, String> {
- // ...
-}
-```
-
-This pattern is common when developers document *why* an attribute is needed (e.g., explaining `#[allow(...)]` suppressions).
-
-### Symptoms
-
-- `loct commands` reported the handler as `[MISSING]`
-- `handlers.json` showed `backend_handler: null` for the command
-- The snapshot showed `command_handlers: []` for the file despite having valid `#[tauri::command]` functions
-
-## Root Cause
-
-The regex pattern for detecting `#[tauri::command]` functions only allowed whitespace (`\s*`) between:
-1. The `#[tauri::command]` attribute
-2. Additional attributes (like `#[allow(...)]`)
-3. The `pub async fn` definition
-
-When a comment appeared after an attribute, the regex failed to match.
-
-### Original Regex (simplified)
-
-```regex
-#[tauri::command...]
-(?:\s*#\s*\[[^\]]*\])* <- additional attributes with whitespace
-\s* <- ONLY whitespace allowed here
-(?:pub...)?fn...
-```
-
-### The Breaking Patterns
-
-```rust
-#[allow(non_snake_case)] // comment here
- ^ NOT whitespace - regex fails
-pub async fn handler()
-```
-
-```rust
-#[allow(non_snake_case)] /* block comment */
- ^ also fails
-pub fn handler()
-```
-
-## Solution
-
-Updated the regex with two improvements:
-
-### 1. Comment Support
-
-Accept whitespace, line comments (`// ...`), AND block comments (`/* ... */`):
-
-```regex
-^\s*#[tauri::command...]
-(?:\s*(?://[^\n]*|/\*[\s\S]*?\*/))? <- optional comment after main attr
-(?:(?:\s|//[^\n]*|/\*[\s\S]*?\*/)*#\[...])* <- attrs with whitespace OR comments
-(?:\s|//[^\n]*|/\*[\s\S]*?\*/)* <- whitespace OR comments before pub
-(?:pub...)?fn...
-```
-
-The key change: `\s*` -> `(?:\s|//[^\n]*|/\*[\s\S]*?\*/)*`
-
-This allows:
-- Pure whitespace (as before)
-- Line comments (`// ...`) after attributes
-- Block comments (`/* ... */`) after attributes
-- Multiline block comments between attributes
-- Standalone comment lines between attributes
-
-### 2. Line Anchoring
-
-Added `^\s*` at the start to anchor to line beginning. This prevents false positives from matching `#[tauri::command]` inside comments or strings:
-
-```rust
-// This won't match anymore:
-let example = "#[tauri::command]\npub fn fake() {}";
-
-// Neither will this:
-// #[tauri::command]
-// pub fn commented_out() {}
-```
-
-## Files Changed
-
-```
-loctree_rs/src/analyzer/regexes.rs
-+-- regex_tauri_command_fn() - main fix
-+-- regex_custom_command_fn() - same fix for custom macros
-|
-+-- Positive tests (should match):
-| +-- test_tauri_command_with_inline_comment() - // after attr
-| +-- test_tauri_command_comment_between_attrs() - // between attrs
-| +-- test_tauri_command_with_block_comment() - /* */ after attr
-| +-- test_tauri_command_with_multiline_block_comment()
-|
-+-- Negative tests (should NOT match):
- +-- test_tauri_command_in_line_comment_no_match()
- +-- test_tauri_command_in_string_no_match()
-```
-
-## Testing
-
-### Before Fix
-
-```bash
-$ loct commands | grep my_handler
- [MISSING] my_handler
- Frontend calls (1): src/services/api.ts:42
- [!] Why: Frontend calls invoke('my_handler') but no #[tauri::command] found
-```
-
-### After Fix
-
-```bash
-$ loct commands | grep my_handler
- [OK] my_handler
- Frontend calls (1): src/services/api.ts:42
- Backend: src-tauri/src/commands/handlers.rs:15
-```
-
-### Regression Tests
-
-```rust
-#[test]
-fn test_tauri_command_with_inline_comment() {
- let re = regex_tauri_command_fn();
- let with_comment = r#"#[tauri::command]
-#[allow(non_snake_case)] // parameter name matches frontend camelCase
-pub async fn my_handler(...) -> Result {"#;
-
- assert!(re.captures(with_comment).is_some());
-}
-
-#[test]
-fn test_tauri_command_with_block_comment() {
- let re = regex_tauri_command_fn();
- let with_block = r#"#[tauri::command]
-#[allow(non_snake_case)] /* camelCase for frontend */
-pub fn my_handler() {}"#;
-
- assert!(re.captures(with_block).is_some());
-}
-
-#[test]
-fn test_tauri_command_in_line_comment_no_match() {
- let re = regex_tauri_command_fn();
- let commented_out = r#"// #[tauri::command]
-// pub fn disabled_handler() {}"#;
-
- assert!(re.captures(commented_out).is_none());
-}
-```
-
-## Impact
-
-Commands that were previously reported as "missing" due to comments after attributes are now correctly detected. The line anchoring also prevents false positives from commented-out or string-embedded code.
-
-## Related
-
-- Tauri command bridge detection: `loct commands`
-- Rust analyzer: `loctree_rs/src/analyzer/rust/mod.rs`
-- Custom command macros: Also fixed in `regex_custom_command_fn()`
diff --git a/docs/getting-started.md b/docs/getting-started.md
deleted file mode 100644
index a3c5e532..00000000
--- a/docs/getting-started.md
+++ /dev/null
@@ -1,126 +0,0 @@
-# Getting Started with loctree
-
-5-minute quickstart to scanning a codebase, reading the artifacts, and wiring
-Loctree into an AI workflow.
-
-## Install
-
-Choose one channel per machine:
-
-```bash
-# Fastest public path: CLI + MCP server
-curl -fsSL https://loct.io/install.sh | sh
-
-# Cargo, reproducible lockfile build
-cargo install --locked loctree loctree-mcp
-
-# npm (CLI only; published targets follow the latest npm release)
-npm install -g loctree
-
-# From source
-git clone https://github.com/Loctree/loctree-ast.git
-cd loctree-ast
-make install
-```
-
-Public install channels follow the latest published release, not necessarily the
-workspace version on the branch you're reading. Check crates.io, npm, or GitHub
-Releases if you need release-exact verification.
-
-Verify the install:
-
-```bash
-loct --version
-loctree --version
-loctree-mcp --version
-```
-
-## First Scan
-
-Run Loctree inside any project directory:
-
-```bash
-cd your-project
-loct
-```
-
-Artifacts are written into your OS cache directory by default. In CI or when
-you want repo-local output, set `LOCT_CACHE_DIR=.loctree`.
-
-## Essential Commands
-
-```bash
-loct # Scan or refresh the cached snapshot
-loct --for-ai # AI-optimized overview
-loct slice src/App.tsx --consumers # File + deps + consumers
-loct find useAuth # Find symbol definitions/usages
-loct impact src/utils/api.ts # Blast radius before refactor/delete
-loct health # Quick health summary
-loct dead --confidence high # High-confidence dead exports
-loct cycles # Circular imports
-loct twins # Duplicate exports / dead parrots / barrel drift
-loct audit # Full structural review
-```
-
-## Artifacts
-
-After a scan, Loctree keeps four core files per project snapshot:
-
-- `snapshot.json` — the dependency graph and file metadata
-- `findings.json` — structural findings such as dead exports and cycles
-- `agent.json` — AI-optimized overview with quick wins and health data
-- `manifest.json` — artifact index for tooling
-
-Query artifacts directly:
-
-```bash
-loct '.metadata'
-loct '.files | length'
-loct findings | jq '.dead_exports.items[] | select(.confidence == "high")'
-loct findings --summary | jq '.health_score'
-```
-
-## MCP Server
-
-`loctree-mcp` is the production MCP surface for AI agents. Start it via stdio:
-
-```bash
-loctree-mcp
-```
-
-Example Claude Desktop / Claude Code config:
-
-```json
-{
- "mcpServers": {
- "loctree": {
- "command": "loctree-mcp",
- "args": []
- }
- }
-}
-```
-
-The server exposes seven tools:
-
-- `repo-view`
-- `slice`
-- `find`
-- `impact`
-- `focus`
-- `tree`
-- `follow`
-
-See [integrations/mcp-server.md](integrations/mcp-server.md) for the full MCP contract.
-
-## IDE / LSP
-
-The public OSS workspace does not ship `loct lsp`. Editor integrations live in
-the external `loctree-suite` project. The docs in [`docs/ide/`](ide/) are kept
-as compatibility notes and setup pointers for that external surface.
-
-## Next Steps
-
-- Read [CLI Commands](cli/commands.md) for the full command surface
-- Read [Use Cases](use-cases/README.md) for real-world analysis flows
-- Read [dev/01_installation.md](dev/01_installation.md) if you are contributing to the workspace itself
diff --git a/docs/ide/lsp-protocol.md b/docs/ide/lsp-protocol.md
deleted file mode 100644
index 3d1abb28..00000000
--- a/docs/ide/lsp-protocol.md
+++ /dev/null
@@ -1,169 +0,0 @@
-# LSP Protocol Reference
-
-> **Part of [loctree-suite](https://github.com/Loctree/loctree-suite)**
-> The Loctree language server ships with loctree-suite.
-
-Technical reference for the Loctree Language Server Protocol implementation.
-
-## Server Capabilities
-
-```json
-{
- "textDocumentSync": {
- "openClose": true,
- "save": { "includeText": false }
- },
- "hoverProvider": true,
- "definitionProvider": true,
- "referencesProvider": true,
- "codeActionProvider": {
- "codeActionKinds": ["quickfix", "refactor"]
- },
- "diagnosticProvider": {
- "interFileDependencies": true,
- "workspaceDiagnostics": true
- }
-}
-```
-
-## Supported Methods
-
-### Lifecycle
-
-| Method | Support | Notes |
-|--------|---------|-------|
-| `initialize` | ✅ | Returns capabilities |
-| `initialized` | ✅ | Loads snapshot, starts file watcher |
-| `shutdown` | ✅ | Cleanup |
-| `exit` | ✅ | Process termination |
-
-### Text Document
-
-| Method | Support | Notes |
-|--------|---------|-------|
-| `textDocument/didOpen` | ✅ | Triggers diagnostics |
-| `textDocument/didSave` | ✅ | Refreshes diagnostics |
-| `textDocument/didClose` | ✅ | Clears diagnostics |
-| `textDocument/hover` | ✅ | Import stats, consumers |
-| `textDocument/definition` | ✅ | Export location |
-| `textDocument/references` | ✅ | All import locations |
-| `textDocument/codeAction` | ✅ | Quick fixes |
-| `textDocument/publishDiagnostics` | ✅ | Dead/cycle/twin warnings |
-
-### Workspace
-
-| Method | Support | Notes |
-|--------|---------|-------|
-| `workspace/didChangeConfiguration` | ✅ | Settings updates |
-| `workspace/didChangeWatchedFiles` | ✅ | Snapshot refresh |
-
-## Diagnostic Types
-
-### Dead Export (`loctree:dead-export`)
-
-```json
-{
- "range": { "start": {"line": 10, "character": 7}, "end": {"line": 10, "character": 20} },
- "severity": 2,
- "code": "dead-export",
- "source": "loctree",
- "message": "Export 'unusedFunction' has 0 imports",
- "data": {
- "symbol": "unusedFunction",
- "confidence": "high"
- }
-}
-```
-
-**Severity levels:**
-- `Warning (2)`: High confidence dead export
-- `Information (3)`: Low confidence (might be API)
-- `Hint (4)`: Test-only export
-
-### Circular Import (`loctree:cycle`)
-
-```json
-{
- "range": { "start": {"line": 1, "character": 0}, "end": {"line": 1, "character": 30} },
- "severity": 2,
- "code": "cycle",
- "source": "loctree",
- "message": "Circular import: a.ts → b.ts → c.ts → a.ts",
- "relatedInformation": [
- {
- "location": { "uri": "file:///project/b.ts", "range": {...} },
- "message": "imports c.ts"
- }
- ]
-}
-```
-
-### Twin Symbol (`loctree:twin`)
-
-```json
-{
- "range": { "start": {"line": 5, "character": 7}, "end": {"line": 5, "character": 13} },
- "severity": 3,
- "code": "twin",
- "source": "loctree",
- "message": "Symbol 'Config' also exported from 3 other files",
- "relatedInformation": [
- {
- "location": { "uri": "file:///project/other/config.ts", "range": {...} },
- "message": "Also exported here"
- }
- ]
-}
-```
-
-## Code Actions
-
-### Quick Fixes (`quickfix`)
-
-| Action | Trigger | Effect |
-|--------|---------|--------|
-| Remove unused export | `dead-export` | Deletes `export` keyword |
-| Add to .loctignore | `dead-export` | Appends pattern |
-| Show in report | `dead-export` | Opens HTML report |
-| Go to next in cycle | `cycle` | Navigates to next file |
-
-### Refactors (`refactor`)
-
-| Action | Description |
-|--------|-------------|
-| Extract to barrel | Move export to index.ts |
-| Inline barrel export | Replace re-export with direct |
-| Consolidate twins | Show picker for all locations |
-
-## Custom Commands
-
-Executable via `workspace/executeCommand`:
-
-| Command | Parameters | Description |
-|---------|------------|-------------|
-| `loctree.refresh` | none | Re-run analysis |
-| `loctree.openReport` | none | Open HTML report |
-| `loctree.navigateToFile` | `path: string` | Open file in editor |
-
-## Initialization Options
-
-```json
-{
- "initializationOptions": {
- "workspaceRoot": "/path/to/project",
- "autoRefresh": false
- }
-}
-```
-
-## Error Codes
-
-| Code | Message | Resolution |
-|------|---------|------------|
-| -32001 | Snapshot not found | Run `loct` first |
-| -32002 | Snapshot stale | Run `loct` to refresh |
-| -32003 | Parse error | Check file syntax |
-
----
-
-𝚅𝚒𝚋𝚎𝚌𝚛𝚊𝚏𝚝𝚎𝚍. with AI Agents ⓒ 2025-2026 Loctree Team
diff --git a/docs/ide/neovim.md b/docs/ide/neovim.md
deleted file mode 100644
index d9f7bc75..00000000
--- a/docs/ide/neovim.md
+++ /dev/null
@@ -1,143 +0,0 @@
-# Neovim Setup
-
-> **Part of [loctree-suite](https://github.com/Loctree/loctree-suite)**
-> The LSP server and editor integrations ship with loctree-suite.
-> Install the free CLI with `cargo install --locked loctree`, then upgrade to suite for IDE features.
-
-Configure Neovim to use the loctree-suite language server for dead code detection and navigation.
-
-## Prerequisites
-
-- Neovim 0.8+
-- [nvim-lspconfig](https://github.com/neovim/nvim-lspconfig)
-- [loctree-suite](https://github.com/Loctree/loctree-suite) with language server binary
-- Loctree CLI installed: `cargo install --locked loctree`
-
-## Configuration
-
-Add to your Neovim config (`init.lua` or `lua/plugins/lsp.lua`):
-
-```lua
--- Add loctree to lspconfig
-local lspconfig = require('lspconfig')
-local configs = require('lspconfig.configs')
-
--- Define loctree LSP if not already defined
-if not configs.loctree then
- configs.loctree = {
- default_config = {
- cmd = { '/path/to/suite-language-server' },
- filetypes = {
- 'typescript', 'typescriptreact',
- 'javascript', 'javascriptreact',
- 'rust', 'python', 'go', 'vue', 'svelte'
- },
- root_dir = lspconfig.util.root_pattern('.loctree', '.git'),
- settings = {},
- },
- }
-end
-
--- Setup with your preferred options
-lspconfig.loctree.setup({
- on_attach = function(client, bufnr)
- -- Your on_attach function
- -- Loctree provides: diagnostics, hover, definition, references
- end,
-})
-```
-
-## Lazy.nvim Example
-
-```lua
-{
- 'neovim/nvim-lspconfig',
- config = function()
- local lspconfig = require('lspconfig')
- local configs = require('lspconfig.configs')
-
- if not configs.loctree then
- configs.loctree = {
- default_config = {
- cmd = { '/path/to/suite-language-server' },
- filetypes = { 'typescript', 'javascript', 'rust', 'python' },
- root_dir = lspconfig.util.root_pattern('.loctree', '.git'),
- },
- }
- end
-
- lspconfig.loctree.setup({})
- end,
-}
-```
-
-## Features
-
-### Diagnostics
-
-Dead exports, cycles, and twins appear as LSP diagnostics:
-
-```
-W: Export 'unusedFunction' has 0 imports [loctree:dead-export]
-W: Circular import: a.ts → b.ts → a.ts [loctree:cycle]
-I: Symbol 'Config' also exported from 3 files [loctree:twin]
-```
-
-### Hover
-
-`:lua vim.lsp.buf.hover()` or `K` shows:
-
-```
-Export: useAuth
-─────────────────
-12 imports across 8 files
-Top consumers: App.tsx, Login.tsx, Dashboard.tsx
-```
-
-### Go to Definition
-
-`gd` jumps to the original export location, resolving re-export chains.
-
-### References
-
-`gr` lists all files importing the symbol.
-
-## Keybindings
-
-Suggested mappings (add to your config):
-
-```lua
-vim.keymap.set('n', 'gd', vim.lsp.buf.definition, { desc = 'Go to definition' })
-vim.keymap.set('n', 'gr', vim.lsp.buf.references, { desc = 'Find references' })
-vim.keymap.set('n', 'K', vim.lsp.buf.hover, { desc = 'Hover info' })
-vim.keymap.set('n', 'ca', vim.lsp.buf.code_action, { desc = 'Code actions' })
-vim.keymap.set('n', 'lr', ':!loct', { desc = 'Refresh loctree' })
-```
-
-## Troubleshooting
-
-### LSP not starting
-
-```vim
-:LspInfo
-```
-
-Check if loctree is listed and running.
-
-### No diagnostics
-
-Ensure a snapshot exists (run `loct` once):
-
-```bash
-loct # Generate snapshot
-```
-
-### Check LSP logs
-
-```vim
-:lua vim.cmd('edit ' .. vim.lsp.get_log_path())
-```
-
----
-
-𝚅𝚒𝚋𝚎𝚌𝚛𝚊𝚏𝚝𝚎𝚍. with AI Agents ⓒ 2025-2026 Loctree Team
diff --git a/docs/ide/vscode.md b/docs/ide/vscode.md
deleted file mode 100644
index 1e1a5a99..00000000
--- a/docs/ide/vscode.md
+++ /dev/null
@@ -1,138 +0,0 @@
-# VSCode Extension
-
-> **Part of [loctree-suite](https://github.com/Loctree/loctree-suite)**
-> The LSP server and editor integrations ship with loctree-suite.
-> Install the free CLI with `cargo install --locked loctree`, then upgrade to suite for IDE features.
-
-The Loctree VSCode extension provides real-time dead code detection, circular import warnings, and code navigation powered by the loctree-suite language server.
-
-## Installation
-
-### From loctree-suite
-
-```bash
-cd loctree-suite/editors/vscode
-npm install
-npm run compile
-```
-
-Then in VSCode: `F1` → "Developer: Install Extension from Location" → select `editors/vscode`
-
-### VSIX (Recommended for forks like Cursor/Windsurf)
-
-```bash
-cd loctree-suite/editors/vscode
-LOCTREE_LSP_PATH=/path/to/suite-language-server npm run package
-```
-
-### From Marketplace (Coming Soon)
-
-```
-ext install libraxis.loctree
-```
-
-## Features
-
-### Diagnostics
-
-The extension shows warnings directly in your editor:
-
-| Diagnostic | Severity | Description |
-|------------|----------|-------------|
-| Dead Export | Warning | Export has 0 imports across codebase |
-| Circular Import | Warning | File is part of an import cycle |
-| Twin Symbol | Information | Symbol exported from multiple files |
-
-### Hover Information
-
-Hover over any export to see:
-- Import count across the codebase
-- Top consumer files
-- Export location details
-
-### Go to Definition
-
-`F12` or `Ctrl+Click` on imports to jump to:
-- Original export location
-- Re-export chain resolution
-- Cross-language definitions (TS → Rust for Tauri)
-
-### Code Actions
-
-`Ctrl+.` on diagnostics to access quick fixes:
-- **Remove unused export** - Delete the export keyword
-- **Add to .loctignore** - Suppress this warning
-- **Show in HTML report** - Open detailed analysis
-
-## Configuration
-
-In VSCode settings (`Ctrl+,`):
-
-```json
-{
- "loctree.serverPath": "/custom/path/to/suite-language-server",
- "loctree.autoRefresh": false,
- "loctree.trace.server": "verbose"
-}
-```
-
-| Setting | Default | Description |
-|---------|---------|-------------|
-| `serverPath` | auto-detect | Path to the loctree-suite language server binary |
-| `autoRefresh` | `false` | Re-scan on file save |
-| `autoDownload` | `true` | Download the loctree-suite language server if missing |
-| `downloadBaseUrl` | (empty) | Override repo URL for downloads |
-| `downloadTag` | `latest` | Release tag for downloads |
-| `trace.server` | `off` | LSP message logging |
-
-## Status Bar
-
-The status bar shows loctree status:
-
-- 🌳 **Loctree: healthy** - No issues detected
-- 🌳 **Loctree: 5 dead** - Number of dead exports
-- 🌳 **Loctree: loading** - Scanning in progress
-
-Click to open the Output panel for details.
-
-## Commands
-
-Open command palette (`F1`) and search for "Loctree":
-
-| Command | Description |
-|---------|-------------|
-| `Loctree: Refresh` | Re-run `loct` and update diagnostics |
-| `Loctree: Open Report` | Open HTML report in browser |
-| `Loctree: Show Health` | Display health score summary |
-
-## Requirements
-
-- [loctree-suite](https://github.com/Loctree/loctree-suite) with the language server binary
-- Loctree CLI installed (`cargo install --locked loctree`)
-- Run `loct` once in the project root (writes snapshot to cache; set `LOCT_CACHE_DIR=.loctree` for repo-local artifacts)
-
-## Troubleshooting
-
-### No diagnostics appearing
-
-1. Check Output panel → "Loctree" for errors
-2. Ensure a snapshot exists (run `loct` once)
-3. Run `loct` in project root
-
-### Server not starting
-
-```bash
-# Check if your language server binary is in PATH
-which
-
-# Or set custom path in settings
-"loctree.serverPath": "/path/to/suite-language-server"
-```
-
-### Stale diagnostics
-
-Click status bar → "Loctree: Refresh" or run `loct` in terminal.
-
----
-
-𝚅𝚒𝚋𝚎𝚌𝚛𝚊𝚏𝚝𝚎𝚍. with AI Agents ⓒ 2025-2026 Loctree Team
diff --git a/docs/integrations/ci-cd.md b/docs/integrations/ci-cd.md
deleted file mode 100644
index 16c0bbc2..00000000
--- a/docs/integrations/ci-cd.md
+++ /dev/null
@@ -1,186 +0,0 @@
-# CI/CD Integration
-
-Integrate loctree into your continuous integration pipeline to catch dead code, circular imports, and duplicates before they reach production.
-
-## GitHub Actions
-
-### Basic Workflow
-
-```yaml
-# .github/workflows/loctree.yml
-name: Loctree Analysis
-
-on:
- pull_request:
- push:
- branches: [main, develop]
-
-jobs:
- analyze:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
-
- - name: Install loctree
- run: cargo install --locked loctree
-
- - name: Run analysis
- run: LOCT_CACHE_DIR=.loctree loct findings > .loctree/findings.json
-
- - name: Check for issues
- run: |
- DEAD=$(jq '.dead_exports.total' .loctree/findings.json)
- CYCLES=$(jq '.cycles.total' .loctree/findings.json)
- if [ "$DEAD" -gt 0 ] || [ "$CYCLES" -gt 0 ]; then
- echo "Found $DEAD dead exports and $CYCLES cycles"
- exit 1
- fi
-```
-
-### With Caching
-
-```yaml
-jobs:
- analyze:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
-
- - name: Cache cargo
- uses: actions/cache@v3
- with:
- path: |
- ~/.cargo/bin/
- ~/.cargo/registry/
- key: ${{ runner.os }}-cargo-loctree
-
- - name: Install loctree
- run: |
- if ! command -v loct &> /dev/null; then
- cargo install --locked loctree
- fi
-
- - name: Analyze summary
- run: LOCT_CACHE_DIR=.loctree loct findings --summary > .loctree/summary.json
-```
-
-### PR Comment with Report
-
-```yaml
- - name: Generate summary report
- run: loct findings --summary > report.json
-
- - name: Comment on PR
- if: github.event_name == 'pull_request'
- uses: actions/github-script@v6
- with:
- script: |
- const fs = require('fs');
- const report = fs.readFileSync('report.json', 'utf8');
- github.rest.issues.createComment({
- issue_number: context.issue.number,
- owner: context.repo.owner,
- repo: context.repo.repo,
- body: '## Loctree Analysis\n```\n' + report + '\n```'
- });
-```
-
-## Pre-commit Hook
-
-### Using pre-commit framework
-
-```yaml
-# .pre-commit-config.yaml
-repos:
- - repo: local
- hooks:
- - id: loctree-lint
- name: Run structural lint
- entry: loct lint --fail
- language: system
- pass_filenames: false
-```
-
-### Manual git hook
-
-```bash
-#!/bin/sh
-# .git/hooks/pre-push
-
-echo "Running loctree analysis..."
-loct --quiet
-
-DEAD=$(loct findings | jq '.dead_exports.total')
-if [ "$DEAD" -gt 0 ]; then
- echo "ERROR: $DEAD dead exports found"
- echo "Run 'loct dead' for details"
- exit 1
-fi
-
-echo "Loctree: OK"
-```
-
-## CLI Flags for CI
-
-| Flag | Description | Use Case |
-|------|-------------|----------|
-| `--json` | JSON output | Parsing in scripts |
-| `--quiet` | No progress output | Clean logs |
-| `--fail-stale` | Fail if snapshot outdated | Enforce fresh analysis |
-| `--fresh` | Force full rescan | Ensure accuracy |
-| `findings --summary` | Summary JSON | Quick status / PR comments |
-
-## Exit Codes
-
-| Code | Meaning |
-|------|---------|
-| 0 | Success, no issues |
-| 1 | Issues found (dead, cycles) |
-| 2 | Configuration error |
-| 3 | Snapshot missing/stale |
-
-## Badge
-
-Add to your README:
-
-```markdown
-[](https://crates.io/crates/loctree)
-```
-
-Result: [](https://crates.io/crates/loctree)
-
-## GitLab CI
-
-```yaml
-# .gitlab-ci.yml
-loctree:
- stage: test
- image: rust:latest
- script:
- - cargo install --locked loctree
- - loct --fail-stale
- cache:
- paths:
- - /usr/local/cargo/bin/loct
-```
-
-## CircleCI
-
-```yaml
-# .circleci/config.yml
-version: 2.1
-jobs:
- loctree:
- docker:
- - image: rust:latest
- steps:
- - checkout
- - run: cargo install --locked loctree
- - run: loct findings --summary > results.json
- - store_artifacts:
- path: results.json
-```
-
----
-
-𝚅𝚒𝚋𝚎𝚌𝚛𝚊𝚏𝚝𝚎𝚍. with AI Agents ⓒ 2025-2026 Loctree Team
diff --git a/docs/integrations/mcp-server.md b/docs/integrations/mcp-server.md
deleted file mode 100644
index 42cc2625..00000000
--- a/docs/integrations/mcp-server.md
+++ /dev/null
@@ -1,126 +0,0 @@
-# MCP Server Integration
-
-`loctree-mcp` exposes Loctree's structural analysis as MCP tools that AI agents
-can call directly over stdio.
-
-For the repo's default operating model, pair this with:
-
-- [`PERCEPTION.md`](../../PERCEPTION.md)
-- [`docs/perception/adr.md`](../perception/adr.md)
-
-## What Ships Here
-
-The public workspace ships one MCP binary:
-
-```bash
-loctree-mcp
-```
-
-It is project-agnostic:
-
-- first use on a project auto-scans if needed
-- snapshots are cached in memory
-- every tool accepts an optional `project` parameter
-
-## Install
-
-Choose whichever channel matches your workflow:
-
-```bash
-# Cargo
-cargo install --locked loctree-mcp
-
-# Full public install path (CLI + MCP)
-curl -fsSL https://loct.io/install.sh | sh
-
-# From source
-git clone https://github.com/Loctree/loctree-ast.git
-cd loctree-ast
-make install-mcp
-```
-
-## Configuration
-
-Example Claude Desktop / Claude Code config:
-
-```json
-{
- "mcpServers": {
- "loctree": {
- "command": "loctree-mcp",
- "args": []
- }
- }
-}
-```
-
-If you use an external MCP multiplexer such as `rmcp-mux`, keep that config in
-your client/runtime layer. It is not part of this workspace anymore.
-
-## Available Tools
-
-### `repo-view(project?: string)`
-
-Use this first. It returns repo summary, health, top hubs, quick wins, and the
-recommended next loctree calls.
-
-### `slice(project?: string, file: string, consumers?: boolean)`
-
-Returns a file plus its dependencies and consumers. Use before modifying code.
-
-### `find(project?: string, name: string, limit?: number)`
-
-Symbol search with regex support. Use before creating new functions, types, or components.
-
-### `impact(project?: string, file: string)`
-
-Shows direct and transitive consumers. Use before deleting or major refactors.
-
-### `focus(project?: string, directory: string)`
-
-Module-level deep dive: files, LOC, exports, internal edges, and external dependencies.
-
-### `tree(project?: string, depth?: number, loc_threshold?: number)`
-
-Directory structure with LOC counts.
-
-### `follow(project?: string, scope: string, limit?: number, handler?: string)`
-
-Drills into repo-view signals such as dead exports, cycles, twins, hotspots,
-commands, events, and pipelines.
-
-## Recommended Agent Flow
-
-The default Loctree sequence stays:
-
-```text
-repo-view -> focus -> slice -> impact -> find -> follow
-```
-
-That keeps AI context grounded in structure instead of grep drift.
-
-## Verification
-
-Quick checks after install:
-
-```bash
-loctree-mcp --version
-```
-
-If your client supports MCP inspection, confirm the server exposes these tool
-names exactly:
-
-- `repo-view`
-- `slice`
-- `find`
-- `impact`
-- `focus`
-- `tree`
-- `follow`
-
-## Notes
-
-- The public OSS workspace does not ship a `for_ai()` MCP tool anymore. The
- current overview entrypoint is `repo-view`.
-- The public OSS workspace does not ship `loct lsp`. Editor/LSP integrations are
- maintained outside this repo.
diff --git a/docs/perception/adr.md b/docs/perception/adr.md
deleted file mode 100644
index 3625e15c..00000000
--- a/docs/perception/adr.md
+++ /dev/null
@@ -1,97 +0,0 @@
-# ADR: Context over Memory
-
-- **Status:** Accepted
-- **Date:** 2026-02-17
-- **Owners:** loctree maintainers
-
-## Context
-
-Agentic workflows have been increasingly optimized around persistent memory and retrieval layers. In practice, we observed recurring issues:
-
-- startup context bloat,
-- stale retrieval against changing codebases,
-- poor reproducibility across sessions,
-- low explainability of "why this context was selected."
-
-At the same time, loctree already provides deterministic structural perception (`repo-view`, `focus`, `slice`, `impact`, `find`) with current-state guarantees.
-
-## Decision
-
-We standardize on **context-over-memory** as the primary architecture for agent workflows:
-
-1. Use graph-backed, on-demand perception as default context acquisition.
-2. Use prepared context bundles for predictable recurrent workflows.
-3. Keep long-term memory optional and subordinate to fresh structural data.
-
-## Scope
-
-This ADR applies to:
-
-- CLI and MCP usage guidance,
-- documentation and examples,
-- internal integration recommendations for agent teams.
-
-It does not force removal of existing memory integrations; it defines priority and default behavior.
-
-## Decision Drivers
-
-- Determinism
-- Freshness
-- Debuggability
-- Lower latency
-- Lower token overhead
-- Safer refactors
-
-## Consequences
-
-### Positive
-
-- Better first-pass accuracy in code modifications.
-- Lower context-token overhead for multi-step tasks.
-- Clear provenance of context ("which command produced this view?").
-- Easier production incident analysis.
-
-### Negative / Trade-offs
-
-- Requires disciplined context mapping habits.
-- Increases reliance on tool availability and quality.
-- Some longitudinal use cases still benefit from memory layers.
-
-## Alternatives considered
-
-### A) Memory-first (vector retrieval as primary)
-
-Rejected as default due to probabilistic recall and drift under active code change.
-
-### B) Huge static preloaded prompts
-
-Rejected due to latency, cost, and context pollution.
-
-### C) Hybrid with memory as secondary (chosen)
-
-Accepted: memory can enrich, but perception and scoped context remain source of truth.
-
-## Guardrails
-
-Before non-trivial edits, workflows should perform:
-
-1. `repo-view`
-2. `focus`
-3. `slice`
-4. `impact`
-5. `find`
-
-Use grep as local detail tool, not as primary mapping layer.
-
-## Rollout
-
-1. Publish manifesto and KPI definitions.
-2. Add these docs to `docs/README.md`.
-3. Update integration examples to reference this ADR.
-4. Track KPI deltas for at least 2 release cycles.
-
-## Success Criteria
-
-See: [Agent Context KPIs](../metrics/agent-context-kpis.md).
-
-This ADR is considered successful if reliability and context efficiency improve without reducing task throughput.
diff --git a/docs/perception/kpis.md b/docs/perception/kpis.md
deleted file mode 100644
index b2fd03cd..00000000
--- a/docs/perception/kpis.md
+++ /dev/null
@@ -1,83 +0,0 @@
-# Agent Context KPIs
-
-## Purpose
-Define measurable outcomes for the `context-over-memory` architecture and track whether reliability improves without sacrificing throughput.
-
-## Measurement Window
-- Track per release and rolling 30-day windows.
-- Compare against a baseline collected before ADR `2026-02-17-context-over-memory`.
-- Evaluate for at least 2 release cycles.
-
-## Primary KPIs
-
-### 1) First-Pass Correct Change Rate (FPCR)
-Percentage of agent-authored changes accepted without rework requests.
-
-Formula:
-`FPCR = accepted_without_rework / total_agent_changes`
-
-Target trend:
-- Up and to the right.
-- No release should regress more than 5% from previous stable baseline.
-
-### 2) Context Token Cost per Completed Task (CTC)
-Average context tokens consumed to complete one successful task.
-
-Formula:
-`CTC = total_context_tokens / completed_tasks`
-
-Target trend:
-- Decrease while maintaining or improving FPCR.
-
-### 3) Context Provenance Coverage (CPC)
-Share of non-trivial tasks where context sources are explicitly traceable to commands.
-
-Formula:
-`CPC = tasks_with_command_provenance / non_trivial_tasks`
-
-Minimum threshold:
-- 90%+
-
-### 4) Freshness Violation Rate (FVR)
-Rate of incidents where stale context caused wrong edits or wrong recommendations.
-
-Formula:
-`FVR = stale_context_incidents / total_agent_tasks`
-
-Target trend:
-- Near zero.
-
-### 5) Mean Context Bootstrap Time (MCBT)
-Median time from task start to first actionable edit.
-
-Formula:
-`MCBT = median(t_first_edit - t_task_start)`
-
-Target trend:
-- Flat or down, despite stricter mapping guardrails.
-
-### 6) Post-Review Rework Rate (PRR)
-Rate of tasks requiring follow-up fixes after initial review.
-
-Formula:
-`PRR = tasks_with_post_review_rework / reviewed_tasks`
-
-Target trend:
-- Down.
-
-## Secondary KPIs
-- `Tool Coverage Rate`: percentage of non-trivial tasks that used the full mapping chain (`repo-view`, `focus`, `slice`, `impact`, `find`).
-- `Refactor Safety Incident Rate`: breakages introduced in medium/large refactors.
-- `Throughput`: completed tasks per engineer-day (must not materially decline).
-
-## Instrumentation Guidance
-- Log task metadata: task size, touched files, commands used, token usage, outcome.
-- Store a compact execution trace for reproducibility.
-- Tag incidents with root cause category: stale context, missing context, tool failure, logic error.
-
-## Success Criteria
-The ADR is successful when:
-1. FPCR improves.
-2. CTC decreases or stays flat with better FPCR.
-3. FVR stays near zero.
-4. Throughput does not regress materially.
diff --git a/docs/perception/research.md b/docs/perception/research.md
deleted file mode 100644
index 45965cf1..00000000
--- a/docs/perception/research.md
+++ /dev/null
@@ -1,74 +0,0 @@
-# Global Direction Research: Context over Memory
-
-- **Date:** 2026-02-17
-- **Method:** synthesis from `web.run` page reads and Brave web search across primary sources (vendor docs, protocol specs, research papers).
-- **Objective:** validate whether `context-over-memory` is aligned with broader agent engineering direction.
-
-## Executive Summary
-Global direction is converging on **context engineering** and **tool-mediated perception** rather than pure memory-first retrieval. The dominant pattern is:
-
-1. Keep context windows curated and scoped.
-2. Retrieve fresh context through tools/protocols (especially MCP).
-3. Use memory as a secondary layer for continuity, not as source of truth for current state.
-
-This supports loctree’s `repo-view -> focus -> slice -> impact -> find` workflow as a production-oriented default.
-
-## Evidence
-
-### 1) Vendor guidance now emphasizes context quality over raw context volume
-- Anthropic’s agent guidance prioritizes simplicity, transparency, and strong tool interfaces over unnecessary complexity.
-- Anthropic’s context-engineering guidance frames context as a managed state with finite attention budget.
-- OpenAI’s agent guidance emphasizes tool-based context retrieval, guardrails, and workflow orchestration instead of monolithic prompts.
-
-### 2) MCP is becoming standard context infrastructure
-- Official MCP specification (2025-06-18 revision) formalizes tools/resources/prompts and transport/lifecycle behavior.
-- OpenAI documents MCP usage across API, connectors, and Codex workflows.
-- Google Cloud announced official MCP support for Google services and Cloud systems.
-- Microsoft announced GA MCP integrations in Copilot Studio and Visual Studio experiences.
-
-Inference from these sources: the ecosystem is standardizing on **protocolized context access** (discoverable, auditable, composable) rather than bespoke memory stacks.
-
-### 3) Long-context research still supports selective context strategies
-- *Lost in the Middle* shows degradation when relevant information sits in the middle of long inputs, supporting selective retrieval and ordering.
-- ReAct and Toolformer-era evidence supports tool use for grounding and action over pure in-prompt recall.
-
-Inference: larger windows help, but do not eliminate the need for careful context selection, compression, and provenance.
-
-## Implications for loctree
-`Context-over-memory` is not a niche stance; it is compatible with current industry movement:
-
-- **Determinism:** tool call provenance is auditable.
-- **Freshness:** context is generated from current repository state.
-- **Debuggability:** failures can be traced to command outputs.
-- **Cost control:** fewer irrelevant tokens than broad memory preload.
-
-Repository-specific mapping and roadmap are documented separately:
-- `docs/research/loctree-codebase-map-and-perception-first-vision-2026-02-17.md`
-
-## Recommended Direction (next 2 cycles)
-1. Keep perception-first guardrails as default for non-trivial edits.
-2. Instrument KPIs from `docs/metrics/agent-context-kpis.md`.
-3. Reference ADR/manifest in integration docs and examples.
-4. Keep memory integrations available, but explicitly secondary to structural context.
-
-## Sources
-Primary:
-- MCP spec and docs: https://modelcontextprotocol.io/specification/2025-06-18
-- MCP GitHub repository: https://github.com/modelcontextprotocol/modelcontextprotocol
-- Anthropic: Building Effective AI Agents: https://www.anthropic.com/research/building-effective-agents
-- Anthropic: Effective context engineering for AI agents: https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents
-- OpenAI practical guide: https://openai.com/business/guides-and-resources/a-practical-guide-to-building-ai-agents/
-- OpenAI building agents track: https://developers.openai.com/tracks/building-agents/
-- OpenAI MCP guide: https://platform.openai.com/docs/mcp
-- OpenAI connectors + MCP: https://platform.openai.com/docs/guides/tools-connectors-mcp
-- OpenAI Codex MCP docs: https://developers.openai.com/codex/mcp
-- OpenAI cookbook (state/context pattern): https://cookbook.openai.com/examples/agents_sdk/context_personalization
-- Google Cloud MCP support announcement: https://cloud.google.com/blog/products/ai-machine-learning/announcing-official-mcp-support-for-google-services
-- Microsoft Copilot Studio MCP GA: https://www.microsoft.com/en-us/microsoft-copilot/blog/copilot-studio/model-context-protocol-mcp-is-now-generally-available-in-microsoft-copilot-studio/
-- Microsoft Visual Studio MCP GA: https://devblogs.microsoft.com/visualstudio/mcp-is-now-generally-available-in-visual-studio/
-- Lost in the Middle (ACL/TACL): https://aclanthology.org/2024.tacl-1.9/
-- ReAct paper: https://arxiv.org/abs/2210.03629
-- Toolformer paper: https://arxiv.org/abs/2302.04761
-
-Supplementary signals (ecosystem/adoption tracking):
-- Google adoption coverage: https://techcrunch.com/2025/04/09/google-says-itll-embrace-anthropics-standard-for-connecting-ai-models-to-data/
diff --git a/docs/refactor-strategist.md b/docs/refactor-strategist.md
deleted file mode 100644
index 746d18ab..00000000
--- a/docs/refactor-strategist.md
+++ /dev/null
@@ -1,458 +0,0 @@
-# Refactor Strategist
-
-> **loct plan** - Generate architectural refactoring plans with risk-ordered execution phases
-
-The Refactor Strategist analyzes module coupling and generates safe refactoring plans. It detects architectural layers, identifies misplaced files, and produces phased migration scripts ordered by risk level.
-
----
-
-## Table of Contents
-
-- [Overview](#overview)
-- [Quick Start](#quick-start)
-- [Layer Detection](#layer-detection)
-- [Risk Assessment](#risk-assessment)
-- [Output Formats](#output-formats)
-- [Shimming Strategy](#shimming-strategy)
-- [Cyclic Dependency Handling](#cyclic-dependency-handling)
-- [Configuration](#configuration)
-- [Examples](#examples)
-- [Integration with Other Commands](#integration-with-other-commands)
-
----
-
-## Overview
-
-Large codebases accumulate architectural debt over time. Files get placed in wrong directories, layers become blurred, and refactoring becomes risky due to complex dependencies.
-
-**Refactor Strategist** solves this by:
-
-1. **Detecting Layers** - Classifies files into UI, App, Kernel, Infra, or Test layers using path heuristics
-2. **Analyzing Impact** - Uses dependency graph to calculate consumer counts and identify high-risk moves
-3. **Detecting Cycles** - Identifies files involved in circular dependencies (via Tarjan's SCC)
-4. **Ordering by Risk** - Sorts moves from LOW → MEDIUM → HIGH risk for safe incremental execution
-5. **Generating Shims** - Creates re-export stubs for heavily-imported files to maintain backward compatibility
-
----
-
-## Quick Start
-
-```bash
-# Generate markdown plan for current directory
-loct plan
-
-# Generate plan for specific directory
-loct plan src/features
-
-# Generate all formats (markdown, JSON, shell script)
-loct plan --all -o refactor-2026
-
-# Generate executable migration script
-loct plan --script > migrate.sh
-chmod +x migrate.sh
-./migrate.sh --dry # Preview changes
-./migrate.sh # Execute migration
-```
-
----
-
-## Layer Detection
-
-Files are classified into architectural layers based on path patterns:
-
-| Layer | Directory Patterns | File Patterns |
-|-------|-------------------|---------------|
-| **UI** | `components/`, `views/`, `pages/`, `ui/`, `widgets/`, `screens/` | `.tsx`, `.vue`, `.svelte` |
-| **App** | `hooks/`, `services/`, `stores/`, `state/`, `context/`, `providers/` | `use*.ts` (React hooks) |
-| **Kernel** | `core/`, `domain/`, `models/`, `entities/`, `business/` | - |
-| **Infra** | `utils/`, `helpers/`, `lib/`, `adapters/`, `api/`, `clients/` | - |
-| **Test** | `tests/`, `__tests__/`, `spec/` | `.test.*`, `.spec.*`, `*_test.*` |
-
-### Detection Priority
-
-1. Test patterns are checked first (highest priority)
-2. UI patterns next (but excludes hooks/stores)
-3. App patterns (hooks, services, stores)
-4. Kernel patterns (core business logic)
-5. Infra patterns (utilities, infrastructure)
-6. If no match, `Unknown` layer is assigned
-
-### Custom Layer Mapping
-
-Override default layer detection with `--target-layout`:
-
-```bash
-loct plan --target-layout "core=src/kernel,ui=src/views,infra=src/shared"
-```
-
----
-
-## Risk Assessment
-
-Each file move is assigned a risk level based on impact analysis:
-
-### Risk Levels
-
-| Risk | Icon | Thresholds | Description |
-|------|------|------------|-------------|
-| **LOW** | 🟢 | <5 consumers, <200 LOC, not in cycle | Safe to move with minimal impact |
-| **MEDIUM** | 🟡 | 5-10 consumers, 200-500 LOC | Moderate impact, review recommended |
-| **HIGH** | 🔴 | >10 consumers, >500 LOC, or in cycle | Significant impact, proceed carefully |
-
-### Risk Calculation Formula
-
-```
-if in_cycle → HIGH
-if direct_consumers >= 10 OR transitive_consumers >= 50 → HIGH
-if loc >= 500 → HIGH
-if direct_consumers >= 5 OR transitive_consumers >= 20 → MEDIUM
-if loc >= 200 → MEDIUM
-else → LOW
-```
-
-### Phased Execution
-
-Moves are grouped into phases by risk level:
-
-```
-Phase 1: LOW Risk (10 files) ← Execute first
-Phase 2: MEDIUM Risk (6 files) ← Execute second
-Phase 3: HIGH Risk (10 files) ← Execute last, with extra care
-```
-
-This ordering minimizes disruption: if Phase 1 breaks something, you haven't touched the critical files yet.
-
----
-
-## Output Formats
-
-### Markdown (Default)
-
-Human-readable report with tables, git commands, and shim instructions:
-
-```bash
-loct plan # Print to stdout
-loct plan -o refactor.md # Write to file
-```
-
-**Sections:**
-- Summary (file counts, risk breakdown)
-- Layer distribution (before/after)
-- Phased execution plan with tables
-- Git commands for each phase
-- Shimming strategy
-
-### JSON
-
-Machine-readable format for tooling integration:
-
-```bash
-loct plan --json # Print to stdout
-loct plan --json -o plan.json
-```
-
-**Structure:**
-```json
-{
- "target": "src/features",
- "moves": [...],
- "shims": [...],
- "cyclic_groups": [...],
- "phases": [...],
- "stats": {
- "total_files": 47,
- "files_to_move": 23,
- "shims_needed": 8,
- "layer_before": {"Unknown": 23, "UI": 10, ...},
- "layer_after": {"Infra": 15, "UI": 10, ...},
- "by_risk": {"LOW": 12, "MEDIUM": 8, "HIGH": 3}
- }
-}
-```
-
-### Shell Script
-
-Executable bash script with phase functions:
-
-```bash
-loct plan --script > migrate.sh
-chmod +x migrate.sh
-
-# Usage options:
-./migrate.sh # Execute all phases
-./migrate.sh --dry # Preview (no changes)
-./migrate.sh 1 # Execute only Phase 1
-./migrate.sh 2 # Execute only Phase 2
-```
-
-**Script Features:**
-- `set -e` for fail-fast execution
-- Color-coded output (green/yellow/red by risk)
-- Dry-run mode (`--dry`)
-- Phase selection (`./migrate.sh 1`)
-- Automatic `mkdir -p` for target directories
-- Git mv commands with proper quoting
-
-### All Formats
-
-Generate all three formats at once:
-
-```bash
-loct plan --all -o refactor-2026
-# Creates:
-# refactor-2026.md
-# refactor-2026.json
-# refactor-2026.sh (executable)
-```
-
----
-
-## Shimming Strategy
-
-When a file has many importers (>3), moving it directly would require updating all import statements. Instead, a **shim** can be created at the old location that re-exports from the new location.
-
-### When Shims Are Suggested
-
-```
-direct_consumers > 3 → suggest shim
-```
-
-### Shim Examples
-
-**TypeScript/JavaScript:**
-```typescript
-// Old location: src/utils/format.ts (shim)
-export { formatDate, formatCurrency } from '../infra/format';
-// or
-export * from '../infra/format';
-```
-
-**Rust:**
-```rust
-// Old location: src/utils.rs (shim)
-pub use crate::infra::utils::*;
-```
-
-**Python:**
-```python
-# Old location: src/utils.py (shim)
-from .infra.utils import *
-```
-
-### Gradual Migration
-
-1. Move file to new location
-2. Create shim at old location
-3. Update importers incrementally
-4. Remove shim when no importers remain
-
----
-
-## Cyclic Dependency Handling
-
-Files involved in circular imports are flagged as **HIGH risk** and grouped together.
-
-### Detection
-
-Uses Tarjan's Strongly Connected Components (SCC) algorithm to detect cycles in the dependency graph.
-
-### Output
-
-```markdown
-## ⚠️ Cyclic Dependencies
-
-The following groups of files have circular imports. Move these together or break the cycle first:
-
-**Cycle 1:**
-- `src/a.ts`
-- `src/b.ts`
-
-**Cycle 2:**
-- `src/models/patient.ts`
-- `src/services/patientService.ts`
-- `src/hooks/usePatient.ts`
-```
-
-### Recommendations
-
-1. **Break the cycle first** - Extract shared types to a third module
-2. **Move together** - If the cycle is intentional, move all files in the group together
-3. **Review architecture** - Cycles often indicate design issues
-
----
-
-## Configuration
-
-### Command Options
-
-| Option | Short | Description |
-|--------|-------|-------------|
-| `--target-layout ` | | Custom layer mapping (e.g., `"core=src/kernel"`) |
-| `--markdown` | `--md` | Output as markdown (default) |
-| `--json` | | Output as JSON |
-| `--script` | `--sh` | Output as executable shell script |
-| `--all` | | Generate all formats (.md, .json, .sh) |
-| `--output ` | `-o` | Output file path (without extension for --all) |
-| `--no-open` | | Don't auto-open the generated report |
-| `--include-tests` | | Include test files in analysis |
-| `--min-coupling ` | | Minimum coupling score to include (0.0-1.0) |
-| `--max-module-size ` | | Maximum module LOC before suggesting split |
-
-### Examples
-
-```bash
-# Custom layer mapping
-loct plan --target-layout "core=src/kernel,ui=src/components,infra=src/shared"
-
-# Include test files (normally excluded)
-loct plan --include-tests
-
-# Generate all formats to specific directory
-loct plan --all -o reports/refactor-$(date +%Y%m%d)
-
-# Pipe JSON to other tools
-loct plan --json | jq '.moves | length' # Count moves
-loct plan --json | jq '.stats.by_risk' # Risk breakdown
-```
-
----
-
-## Examples
-
-### Example 1: React Feature Module
-
-**Directory:** `src/features/patients/`
-
-**Before:**
-```
-src/features/patients/
-├── PatientList.tsx → UI (correct)
-├── PatientCard.tsx → UI (correct)
-├── utils.ts → Unknown (should be Infra)
-├── types.ts → Unknown (should be Kernel)
-├── usePatients.ts → App (correct, hook pattern)
-└── api.ts → Unknown (should be Infra)
-```
-
-**Command:**
-```bash
-loct plan src/features/patients
-```
-
-**Output:**
-```markdown
-# Refactor Plan: src/features/patients
-
-## Summary
-- Files analyzed: 6
-- Files to move: 3
-- Risk: 2 LOW, 1 MEDIUM
-
-## 🟢 Phase 1: LOW Risk (2 files)
-| File | From | To | Reason |
-|------|------|-------|--------|
-| utils.ts | Unknown | Infra | Utility functions |
-| api.ts | Unknown | Infra | API client |
-
-## 🟡 Phase 2: MEDIUM Risk (1 file)
-| File | From | To | Reason |
-|------|------|-------|--------|
-| types.ts | Unknown | Kernel | 5 consumers |
-```
-
-### Example 2: Rust Crate Reorganization
-
-**Directory:** `src/cli/`
-
-**Command:**
-```bash
-loct plan src/cli --script > reorganize-cli.sh
-./reorganize-cli.sh --dry
-```
-
-**Output (excerpt):**
-```bash
-phase_1 () {
- echo -e "${GREEN}=== Phase 1: LOW Risk ===${NC}"
- echo "Moving 10 files..."
-
- run mkdir -p "src/cli/infra"
- run git mv "src/cli/helpers.rs" "src/cli/infra/helpers.rs"
- run git mv "src/cli/utils.rs" "src/cli/infra/utils.rs"
- # ...
-}
-```
-
-### Example 3: CI Integration
-
-**GitHub Actions:**
-```yaml
-- name: Architectural Review
- run: |
- loct plan --json > plan.json
- FILES_TO_MOVE=$(jq '.stats.files_to_move' plan.json)
- if [ "$FILES_TO_MOVE" -gt 0 ]; then
- echo "::warning::$FILES_TO_MOVE files may need reorganization"
- jq '.stats' plan.json
- fi
-```
-
----
-
-## Integration with Other Commands
-
-### Before Planning
-
-```bash
-# Understand current state
-loct health # Quick health check
-loct focus # Directory context
-loct hotspots # Find hub files
-```
-
-### During Execution
-
-```bash
-# Verify each move
-loct impact # What breaks?
-loct cycles # Check for new cycles
-```
-
-### After Migration
-
-```bash
-# Validate results
-loct health # Re-check health
-loct audit # Full audit
-loct report --html # Visual report
-```
-
----
-
-## Related Commands
-
-| Command | Purpose |
-|---------|---------|
-| `loct impact ` | Analyze what breaks if a file is changed |
-| `loct focus ` | Extract directory context (deps + consumers) |
-| `loct cycles` | Detect and classify circular imports |
-| `loct audit` | Full codebase audit (dead + cycles + twins) |
-| `loct health` | Quick health summary |
-
----
-
-## Architecture
-
-The Refactor Strategist uses these loctree building blocks:
-
-1. **HolographicFocus** - Extracts files in target directory with their dependencies
-2. **ImpactAnalysis** - Calculates direct and transitive consumers for risk scoring
-3. **Tarjan SCC** - Detects cyclic dependency groups
-4. **LayerDetection** - Classifies files by architectural layer via path heuristics
-5. **ShimGeneration** - Creates re-export code for backward compatibility
-
-**Performance:** <3s for 500-file directories (uses cached snapshot, no re-scanning)
-
----
-
-𝚅𝚒𝚋𝚎𝚌𝚛𝚊𝚏𝚝𝚎𝚍. with AI Agents ⓒ 2025-2026 Loctree Team
diff --git a/docs/rmcp-memex/01_security.md b/docs/rmcp-memex/01_security.md
deleted file mode 100644
index eba9e58b..00000000
--- a/docs/rmcp-memex/01_security.md
+++ /dev/null
@@ -1,337 +0,0 @@
-# Security - Namespace Access Control
-
-## Problem
-
-W środowisku multi-agent, gdzie wiele AI agentów może korzystać z tego samego serwera rmcp-memex, potrzebna jest izolacja danych między agentami. Bez mechanizmu kontroli dostępu:
-- Agent A może odczytać dane Agenta B
-- Brak możliwości ochrony wrażliwych namespace'ów
-- Trudność w audycie dostępu do danych
-
-Dodatkowo, ograniczenie dostępu do plików tylko do `$HOME` i `cwd` było zbyt restrykcyjne - blokowało legitymowe użycie zewnętrznych wolumenów (np. `/Volumes/ExternalDrive`).
-
-## Rozwiązanie
-
-Zaimplementowano dwupoziomowy system bezpieczeństwa:
-
-### 1. Konfigurowalna Whitelist Ścieżek
-
-Zamiast hardcoded ograniczenia do `$HOME` i `cwd`, wprowadzono konfigurowalną listę dozwolonych ścieżek.
-
-```toml
-# ~/.rmcp_servers/config/rmcp-memex.toml
-allowed_paths = [
- "~", # Home directory
- "/Volumes/LibraxisShare/data", # External volume
- "/opt/shared/documents" # Shared directory
-]
-```
-
-**Zachowanie:**
-- Jeśli `allowed_paths` jest puste → domyślnie `$HOME` + `cwd` (backward compatible)
-- Jeśli `allowed_paths` jest ustawione → tylko te ścieżki są dozwolone
-- Wspiera `~` expansion do home directory
-- Walidacja przez canonicalization (rozwiązuje symlinki)
-
-### 2. Namespace Access Tokens
-
-Token-based access control dla namespace'ów. Chronione namespace'y wymagają tokena do odczytu/zapisu.
-
-```
-┌─────────────────────────────────────────────────────────────┐
-│ Namespace Security │
-├─────────────────────────────────────────────────────────────┤
-│ │
-│ Public Namespace Protected Namespace │
-│ ┌─────────────┐ ┌─────────────────────┐ │
-│ │ "default" │ │ "pamietnik" │ │
-│ │ │ │ │ │
-│ │ No token │ │ Token: rmx_7f3a9b │ │
-│ │ required │ │ required │ │
-│ └─────────────┘ └─────────────────────┘ │
-│ │
-│ Agent A: ✓ access Agent A: ✗ no token │
-│ Agent B: ✓ access Agent B: ✓ has token │
-│ │
-└─────────────────────────────────────────────────────────────┘
-```
-
-## Użycie
-
-### Włączenie Security
-
-```bash
-# CLI
-rmcp_memex serve --security-enabled
-
-# Lub w config.toml
-security_enabled = true
-token_store_path = "~/.rmcp_servers/rmcp_memex/tokens.json"
-```
-
-### Tworzenie Tokena dla Namespace
-
-```json
-// MCP Request
-{
- "method": "tools/call",
- "params": {
- "name": "namespace_create_token",
- "arguments": {
- "namespace": "pamietnik",
- "description": "Personal diary namespace"
- }
- }
-}
-
-// Response
-{
- "content": [{
- "type": "text",
- "text": "Token created for namespace 'pamietnik': rmx_a1b2c3d4e5f6..."
- }]
-}
-```
-
-**WAŻNE:** Token jest zwracany tylko raz przy tworzeniu. Zapisz go w bezpiecznym miejscu!
-
-### Dostęp do Chronionego Namespace
-
-```json
-// Bez tokena - BŁĄD
-{
- "method": "tools/call",
- "params": {
- "name": "memory_search",
- "arguments": {
- "namespace": "pamietnik",
- "query": "moje wspomnienia"
- }
- }
-}
-// Error: "Access denied: namespace 'pamietnik' requires a valid token"
-
-// Z tokenem - OK
-{
- "method": "tools/call",
- "params": {
- "name": "memory_search",
- "arguments": {
- "namespace": "pamietnik",
- "query": "moje wspomnienia",
- "token": "rmx_a1b2c3d4e5f6..."
- }
- }
-}
-// Success: returns search results
-```
-
-### Odwołanie Tokena
-
-```json
-{
- "method": "tools/call",
- "params": {
- "name": "namespace_revoke_token",
- "arguments": {
- "namespace": "pamietnik"
- }
- }
-}
-```
-
-Po odwołaniu tokena, namespace staje się ponownie publiczny.
-
-### Lista Chronionych Namespace'ów
-
-```json
-{
- "method": "tools/call",
- "params": {
- "name": "namespace_list_protected",
- "arguments": {}
- }
-}
-
-// Response
-{
- "content": [{
- "type": "text",
- "text": "[\"pamietnik\", \"projekty\", \"finanse\"]"
- }]
-}
-```
-
-### Status Security
-
-```json
-{
- "method": "tools/call",
- "params": {
- "name": "namespace_security_status",
- "arguments": {}
- }
-}
-
-// Response (enabled)
-{
- "content": [{
- "type": "text",
- "text": "{\"enabled\":true,\"token_store_path\":\"~/.rmcp_servers/rmcp_memex/tokens.json\"}"
- }]
-}
-
-// Response (disabled)
-{
- "content": [{
- "type": "text",
- "text": "{\"enabled\":false,\"message\":\"Namespace security is disabled. All namespaces are publicly accessible.\"}"
- }]
-}
-```
-
-## Format Tokena
-
-Tokeny mają format: `rmx_<32 znaki hex>`
-
-```
-rmx_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6
-│ └─────────────────────────────────┘
-│ 32 znaki hex (128 bit)
-└── prefix "rmx_" (rmcp-memex)
-```
-
-Tokeny są generowane kryptograficznie bezpiecznie (`rand::thread_rng()`).
-
-## Token Store
-
-Tokeny są przechowywane w pliku JSON:
-
-```json
-// ~/.rmcp_servers/rmcp_memex/tokens.json
-{
- "pamietnik": {
- "token_hash": "5e884898da28047d...",
- "created_at": "2024-12-22T10:30:00Z",
- "description": "Personal diary namespace"
- },
- "projekty": {
- "token_hash": "d033e22ae348aeb5...",
- "created_at": "2024-12-22T11:00:00Z",
- "description": null
- }
-}
-```
-
-**Bezpieczeństwo:**
-- Przechowywany jest tylko **hash** tokena (SHA-256), nie sam token
-- Token plaintext jest zwracany tylko raz przy tworzeniu
-- Weryfikacja przez porównanie hashy
-
-## Path Validation
-
-Funkcja `validate_path()` chroni przed path traversal attacks:
-
-```rust
-// Blokowane wzorce
-"../../../etc/asdpasswd" // Path traversal
-sd"/etc/passwd" // Outside allowed paths
-"~/../../root/.ssh" // Traversal after expansion
-
-// Dozwolone (jeśli w allowed_paths)
-"~/Documents/notes.md" // Under home
-"/Volumes/Data/file.txt" // Configured external volume
-```
-
-**Walidacja:**
-1. Sprawdzenie czy ścieżka nie jest pusta
-2. Expansion `~` do home directory
-3. Sprawdzenie wzorca `..` (path traversal)
-4. Canonicalization (rozwiązanie symlinków)
-5. Sprawdzenie czy canonical path jest pod dozwoloną ścieżką
-
-## Implementacja
-
-### Pliki źródłowe
-
-| Plik | Opis |
-|------|------|
-| `rmcp-memex/src/security/mod.rs` | `NamespaceAccessManager`, `TokenStore`, token generation/verification |
-| `rmcp-memex/src/handlers/mod.rs` | `validate_path()`, integration z access manager |
-| `rmcp-memex/src/lib.rs` | `NamespaceSecurityConfig`, re-exports |
-| `rmcp-memex/src/bin/rmcp_memex.rs` | CLI flags `--security-enabled`, `--token-store-path` |
-
-### Kluczowe struktury
-
-```rust
-/// Konfiguracja security
-pub struct NamespaceSecurityConfig {
- pub enabled: bool,
- pub token_store_path: Option,
-}
-
-/// Manager dostępu do namespace'ów
-pub struct NamespaceAccessManager {
- enabled: bool,
- store: Option>>,
-}
-
-/// Przechowywanie tokenów
-pub struct TokenStore {
- path: PathBuf,
- tokens: HashMap,
-}
-
-/// Wpis tokena
-pub struct TokenEntry {
- pub token_hash: String,
- pub created_at: DateTime,
- pub description: Option,
-}
-```
-
-### Testy
-
-```bash
-cd rmcp-memex && cargo test security
-```
-
-Testy pokrywają:
-- `test_token_generation` - generowanie tokenów w poprawnym formacie
-- `test_access_manager_disabled` - zachowanie gdy security wyłączone
-- `test_token_store_create_and_verify` - tworzenie i weryfikacja tokenów
-- `test_access_manager_enabled` - pełny flow z włączonym security
-
-## Best Practices
-
-### Dla administratorów
-
-1. **Włącz security w produkcji** - `--security-enabled`
-2. **Ogranicz allowed_paths** - tylko niezbędne ścieżki
-3. **Backup token store** - tokeny są nieodwracalne
-4. **Rotacja tokenów** - okresowo revoke + create nowe
-
-### Dla agentów AI
-
-1. **Przechowuj tokeny bezpiecznie** - env vars lub secure storage
-2. **Nie loguj tokenów** - unikaj wyświetlania w logach
-3. **Używaj dedykowanych namespace'ów** - izolacja danych
-4. **Sprawdzaj security_status** - upewnij się że security jest włączone
-
-## Przyszłe rozszerzenia
-
-### Faza 3: Szyfrowanie Namespace'ów (planowane)
-
-```toml
-# Przyszła konfiguracja
-[namespaces.pamietnik]
-encrypted = true
-key_derivation = "argon2id"
-```
-
-- Dane w LanceDB szyfrowane kluczem namespace'u
-- Bez klucza = dane bezużyteczne
-- Dla naprawdę wrażliwych danych
-
----
-
-𝚅𝚒𝚋𝚎𝚌𝚛𝚊𝚏𝚝𝚎𝚍. with AI Agents ⓒ 2025-2026 Loctree Team
diff --git a/docs/rmcp-memex/02_configuration.md b/docs/rmcp-memex/02_configuration.md
deleted file mode 100644
index 2ba11c81..00000000
--- a/docs/rmcp-memex/02_configuration.md
+++ /dev/null
@@ -1,299 +0,0 @@
-# Configuration Guide
-
-## Przegląd
-
-rmcp-memex można skonfigurować na trzy sposoby (w kolejności priorytetu):
-1. **Flagi CLI** - najwyższy priorytet
-2. **Plik konfiguracyjny TOML** - średni priorytet
-3. **Wartości domyślne** - najniższy priorytet
-
-## Opcje CLI
-
-```bash
-rmcp_memex [OPTIONS] [COMMAND]
-```
-
-### Komendy
-
-| Komenda | Opis |
-|---------|------|
-| `serve` | Uruchom serwer MCP (domyślna) |
-| `wizard` | Interaktywny kreator konfiguracji |
-| `index` | Batch indexing dokumentów |
-
-### Globalne Opcje
-
-| Flaga | Opis | Domyślnie |
-|-------|------|-----------|
-| `--config ` | Ścieżka do pliku konfiguracyjnego TOML | brak |
-| `--mode ` | Tryb serwera: `memory` lub `full` | `full` |
-| `--features ` | Lista funkcji (comma-separated) | `filesystem,memory,search` |
-| `--cache-mb ` | Rozmiar cache w MB | `4096` |
-| `--db-path ` | Ścieżka do LanceDB | `~/.rmcp_servers/rmcp_memex/lancedb` |
-| `--max-request-bytes ` | Max rozmiar requestu | `5242880` (5MB) |
-| `--log-level ` | Poziom logowania | `info` |
-| `--allowed-paths ` | Dozwolone ścieżki (można powtórzyć) | `$HOME`, `cwd` |
-| `--security-enabled` | Włącz namespace security | `false` |
-| `--token-store-path ` | Ścieżka do token store | `~/.rmcp_servers/rmcp_memex/tokens.json` |
-
-### Przykłady CLI
-
-```bash
-# Podstawowe uruchomienie
-rmcp_memex serve
-
-# Tryb memory-only (bez dostępu do filesystem)
-rmcp_memex serve --mode memory
-
-# Z własną konfiguracją
-rmcp_memex serve --config ~/.rmcp_servers/config/rmcp-memex.toml
-
-# Z security i custom paths
-rmcp_memex serve \
- --security-enabled \
- --allowed-paths ~ \
- --allowed-paths /Volumes/Data \
- --log-level debug
-
-# Batch indexing
-rmcp_memex index ./documents --namespace docs --recursive --glob "*.md"
-```
-
-## Plik Konfiguracyjny (TOML)
-
-### Lokalizacja
-
-Domyślna lokalizacja: `~/.rmcp_servers/config/rmcp-memex.toml`
-
-### Pełny Przykład
-
-```toml
-# Tryb serwera: "memory" lub "full"
-mode = "full"
-
-# Lista włączonych funkcji
-features = "filesystem,memory,search"
-
-# Rozmiar cache w MB
-cache_mb = 4096
-
-# Ścieżka do LanceDB vector store
-db_path = "~/.rmcp_servers/rmcp_memex/lancedb"
-
-# Maksymalny rozmiar requestu JSON-RPC (bytes)
-max_request_bytes = 5242880
-
-# Poziom logowania: trace, debug, info, warn, error
-log_level = "info"
-
-# Whitelist dozwolonych ścieżek dla operacji na plikach
-# Jeśli puste, domyślnie $HOME i current working directory
-allowed_paths = [
- "~",
- "/Volumes/LibraxisShare/Klaudiusz",
- "/opt/shared/documents"
-]
-
-# Włącz namespace token-based access control
-security_enabled = true
-
-# Ścieżka do pliku z tokenami namespace'ów
-token_store_path = "~/.rmcp_servers/rmcp_memex/tokens.json"
-```
-
-### Minimalna Konfiguracja
-
-```toml
-# Tylko niezbędne ustawienia
-db_path = "~/.rmcp_servers/rmcp_memex/lancedb"
-security_enabled = true
-```
-
-## Tryby Serwera
-
-### Full Mode (domyślny)
-
-Wszystkie funkcje włączone:
-- RAG indexing z plików
-- Memory operations
-- Semantic search
-
-```bash
-rmcp_memex serve --mode full
-# lub
-rmcp_memex serve # domyślnie full
-```
-
-### Memory Mode
-
-Tylko operacje pamięciowe, bez dostępu do filesystem:
-- Memory upsert/get/search/delete
-- Semantic search
-- Brak rag_index (tylko rag_index_text)
-
-```bash
-rmcp_memex serve --mode memory
-```
-
-Użyj tego trybu gdy:
-- Serwer nie powinien mieć dostępu do plików
-- Tylko vector memory jest potrzebne
-- Zwiększone bezpieczeństwo
-
-## Zmienne Środowiskowe
-
-| Zmienna | Opis |
-|---------|------|
-| `HOME` / `USERPROFILE` | Home directory (dla ~ expansion) |
-| `LANCEDB_PATH` | Override ścieżki LanceDB |
-| `SLED_PATH` | Override ścieżki sled K/V store |
-| `FASTEMBED_CACHE_PATH` | Cache dla modeli FastEmbed |
-| `HF_HUB_CACHE` | Cache dla modeli HuggingFace |
-
-## Konfiguracja dla Claude/MCP
-
-### ~/.claude.json
-
-```json
-{
- "mcpServers": {
- "rmcp-memex": {
- "command": "rmcp_memex",
- "args": ["serve", "--config", "~/.rmcp_servers/config/rmcp-memex.toml"]
- }
- }
-}
-```
-
-### Z security enabled
-
-```json
-{
- "mcpServers": {
- "rmcp-memex": {
- "command": "rmcp_memex",
- "args": [
- "serve",
- "--security-enabled",
- "--allowed-paths", "~",
- "--allowed-paths", "/Volumes/Data"
- ]
- }
- }
-}
-```
-
-## Batch Indexing
-
-Komenda `index` pozwala na masowe indeksowanie dokumentów.
-
-### Składnia
-
-```bash
-rmcp_memex index [OPTIONS]
-```
-
-### Opcje
-
-| Flaga | Opis |
-|-------|------|
-| `-n, --namespace ` | Namespace dla dokumentów (domyślnie: `rag`) |
-| `-r, --recursive` | Rekursywnie przeglądaj podkatalogi |
-| `-g, --glob ` | Filtruj pliki wzorcem glob |
-| `--max-depth ` | Maksymalna głębokość (0 = bez limitu) |
-
-### Przykłady
-
-```bash
-# Indeksuj pojedynczy plik
-rmcp_memex index ./README.md
-
-# Indeksuj folder rekursywnie
-rmcp_memex index ./docs --recursive --namespace documentation
-
-# Tylko pliki markdown
-rmcp_memex index ./notes --recursive --glob "*.md" --namespace notes
-
-# Z limitem głębokości
-rmcp_memex index ./project --recursive --max-depth 3
-```
-
-## Wizard (Kreator Konfiguracji)
-
-Interaktywny kreator do generowania konfiguracji.
-
-```bash
-rmcp_memex wizard
-
-# Dry run - pokaż zmiany bez zapisywania
-rmcp_memex wizard --dry-run
-```
-
-Wizard pomoże skonfigurować:
-- Ścieżkę do LanceDB
-- Dozwolone ścieżki
-- Security settings
-- Integrację z Claude
-
-## Priorytet Konfiguracji
-
-Gdy ta sama opcja jest ustawiona w wielu miejscach:
-
-```
-CLI flag > Config file > Default value
-```
-
-Przykład:
-```bash
-# Config file: log_level = "info"
-# CLI: --log-level debug
-# Wynik: debug (CLI wygrywa)
-rmcp_memex serve --config config.toml --log-level debug
-```
-
-## Walidacja Konfiguracji
-
-Serwer waliduje konfigurację przy starcie:
-
-1. **Ścieżki** - sprawdza czy istnieją i są dostępne
-2. **Allowed paths** - rozwiązuje ~ i sprawdza uprawnienia
-3. **Token store** - tworzy plik jeśli nie istnieje (gdy security enabled)
-4. **LanceDB** - inicjalizuje bazę jeśli nie istnieje
-
-Błędy konfiguracji są raportowane przy starcie z jasnym komunikatem.
-
-## Troubleshooting
-
-### "Access denied: path outside allowed directories"
-
-Dodaj ścieżkę do `allowed_paths`:
-```toml
-allowed_paths = [
- "~",
- "/path/to/your/directory"
-]
-```
-
-### "Cannot resolve config path"
-
-Sprawdź czy plik konfiguracyjny istnieje:
-```bash
-ls -la ~/.rmcp_servers/config/rmcp-memex.toml
-```
-
-### "Token store not found"
-
-Przy pierwszym uruchomieniu z `--security-enabled`, token store jest tworzony automatycznie. Upewnij się że katalog nadrzędny istnieje:
-```bash
-mkdir -p ~/.rmcp_servers/rmcp_memex
-```
-
-### Logi debugowania
-
-```bash
-rmcp_memex serve --log-level trace
-```
-
----
-
-𝚅𝚒𝚋𝚎𝚌𝚛𝚊𝚏𝚝𝚎𝚍. with AI Agents ⓒ 2025-2026 Loctree Team
diff --git a/docs/rmcp-memex/README.md b/docs/rmcp-memex/README.md
deleted file mode 100644
index d5ee8ae7..00000000
--- a/docs/rmcp-memex/README.md
+++ /dev/null
@@ -1,239 +0,0 @@
-# rmcp-memex
-
-RAG/Memory MCP Server with LanceDB vector storage for AI agents.
-
-## Overview
-
-`rmcp-memex` is an MCP (Model Context Protocol) server providing:
-- **RAG (Retrieval-Augmented Generation)** - document indexing and semantic search
-- **Vector Memory** - semantic storage and retrieval of text chunks
-- **Namespace Isolation** - data isolation in namespaces
-- **Security** - token-based access control for protected namespaces
-- **Onion Slice Architecture** - hierarchical embeddings (OUTER→MIDDLE→INNER→CORE)
-- **Preprocessing** - automatic noise filtering from conversation exports (~36-40% reduction)
-- **Exact-Match Deduplication** - SHA256-based dedup for overlapping exports
-
-## Architecture
-
-```
-┌─────────────────────────────────────────────────────────────┐
-│ rmcp-memex │
-├─────────────────────────────────────────────────────────────┤
-│ MCP Server (JSON-RPC over stdio) │
-│ ├── handlers/mod.rs - Request routing & validation │
-│ ├── security/mod.rs - Namespace access control │
-│ └── rag/mod.rs - RAG pipeline │
-├─────────────────────────────────────────────────────────────┤
-│ Storage Layer │
-│ ├── LanceDB - Vector embeddings │
-│ ├── sled - Key-value store │
-│ └── moka - In-memory cache │
-├─────────────────────────────────────────────────────────────┤
-│ Embeddings (External Providers) │
-│ ├── Ollama - Local models (recommended) │
-│ ├── MLX Bridge - Apple Silicon acceleration │
-│ └── OpenAI-compatible - Any compatible endpoint │
-└─────────────────────────────────────────────────────────────┘
-```
-
-## Features
-
-### RAG Tools
-| Tool | Description |
-|------|-------------|
-| `rag_index` | Index document from file |
-| `rag_index_text` | Index raw text |
-| `rag_search` | Search documents semantically |
-
-### Memory Tools
-| Tool | Description |
-|------|-------------|
-| `memory_upsert` | Add/update chunk in namespace |
-| `memory_get` | Get chunk by ID |
-| `memory_search` | Search semantically in namespace |
-| `memory_delete` | Delete chunk |
-| `memory_purge_namespace` | Delete all chunks in namespace |
-
-### Security Tools
-| Tool | Description |
-|------|-------------|
-| `namespace_create_token` | Create access token for namespace |
-| `namespace_revoke_token` | Revoke token (namespace becomes public) |
-| `namespace_list_protected` | List protected namespaces |
-| `namespace_security_status` | Security system status |
-
-## Quick Start
-
-### Installation
-
-```bash
-cd loctree-suite
-cargo install --path rmcp-memex
-```
-
-### Running
-
-```bash
-# Default mode (all features)
-rmcp_memex serve
-
-# Memory-only mode (no filesystem access)
-rmcp_memex serve --mode memory
-
-# With security enabled
-rmcp_memex serve --security-enabled
-```
-
-### Configuration (TOML)
-
-```toml
-# ~/.rmcp_servers/config/rmcp-memex.toml
-
-mode = "full"
-db_path = "~/.rmcp_servers/rmcp_memex/lancedb"
-cache_mb = 4096
-log_level = "info"
-
-# Whitelist of allowed paths
-allowed_paths = [
- "~",
- "/Volumes/ExternalDrive/data"
-]
-
-# Security
-security_enabled = true
-token_store_path = "~/.rmcp_servers/rmcp_memex/tokens.json"
-```
-
-## Documentation
-
-- [01_security.md](./01_security.md) - Security system (namespace tokens)
-- [02_configuration.md](./02_configuration.md) - Configuration and CLI options
-
-## Onion Slice Architecture
-
-Instead of traditional flat chunking, rmcp-memex offers hierarchical "onion slices":
-
-```
-┌─────────────────────────────────────────┐
-│ OUTER (~100 chars) │ ← Minimum context, maximum navigation
-│ Keywords + ultra-compression │
-├─────────────────────────────────────────┤
-│ MIDDLE (~300 chars) │ ← Key sentences + context
-├─────────────────────────────────────────┤
-│ INNER (~600 chars) │ ← Expanded content
-├─────────────────────────────────────────┤
-│ CORE (full text) │ ← Complete document
-└─────────────────────────────────────────┘
-```
-
-**Philosophy:** "Minimum info → Maximum navigation paths"
-
-### CLI Commands
-
-```bash
-# Index with onion slicing (default)
-rmcp_memex index -n memories /path/to/data/ --slice-mode onion
-
-# Index with flat chunking (backward compatible)
-rmcp_memex index -n memories /path/to/data/ --slice-mode flat
-
-# Search in namespace
-rmcp_memex search -n memories -q "best moments" --limit 10
-
-# Search only in specific layer
-rmcp_memex search -n memories -q "query" --layer outer
-
-# Drill down in hierarchy (expand children)
-rmcp_memex expand -n memories -i "slice_id_here"
-
-# Get chunk by ID
-rmcp_memex get -n memories -i "chunk_abc123"
-
-# RAG search (cross-namespace)
-rmcp_memex rag-search -q "search term" --limit 5
-
-# List namespaces with stats
-rmcp_memex namespaces --stats
-
-# Export namespace to JSON
-rmcp_memex export -n memories -o backup.json --include-embeddings
-```
-
-### Preprocessing (Noise Filtering)
-
-Automatic removal of ~36-40% noise from conversation exports:
-- MCP tool artifacts (``, ``, etc.)
-- CLI output (git status, cargo build, npm install)
-- Metadata (UUIDs, timestamps → placeholders)
-- Empty/boilerplate content
-
-```bash
-# Index with preprocessing
-rmcp_memex index -n memories /path/to/export.json --preprocess
-```
-
-### Exact-Match Deduplication
-
-SHA256-based dedup for overlapping exports (e.g., quarterly exports containing 6 months of data):
-
-```bash
-# Dedup enabled (default)
-rmcp_memex index -n memories /path/to/data/
-
-# Disable dedup
-rmcp_memex index -n memories /path/to/data/ --no-dedup
-```
-
-**Output with statistics:**
-```
-Indexing complete:
- New chunks: 234
- Files indexed: 67
- Skipped (duplicate): 33
- Deduplication: enabled
-```
-
-## Code Structure
-
-```
-rmcp-memex/
-├── src/
-│ ├── lib.rs # Public API & ServerConfig
-│ ├── bin/
-│ │ └── rmcp_memex.rs # CLI binary (serve, index, search, get, expand, etc.)
-│ ├── handlers/
-│ │ └── mod.rs # MCP request handlers
-│ ├── security/
-│ │ └── mod.rs # Namespace access control
-│ ├── rag/
-│ │ └── mod.rs # RAG pipeline + OnionSlice architecture
-│ ├── preprocessing/
-│ │ └── mod.rs # Noise filtering for conversation exports
-│ ├── storage/
-│ │ └── mod.rs # LanceDB + sled (schema v3 with content_hash)
-│ ├── embeddings/
-│ │ └── mod.rs # MLX/FastEmbed bridge
-│ └── tui/
-│ └── mod.rs # Configuration wizard
-└── Cargo.toml
-```
-
-## Claude/MCP Integration
-
-Add to `~/.claude.json`:
-
-```json
-{
- "mcpServers": {
- "rmcp-memex": {
- "command": "rmcp_memex",
- "args": ["serve", "--security-enabled"]
- }
- }
-}
-```
-
----
-
-𝚅𝚒𝚋𝚎𝚌𝚛𝚊𝚏𝚝𝚎𝚍. with AI Agents ⓒ 2025-2026 Loctree Team
diff --git a/docs/search-tools-comparison.md b/docs/search-tools-comparison.md
deleted file mode 100644
index 334cc086..00000000
--- a/docs/search-tools-comparison.md
+++ /dev/null
@@ -1,300 +0,0 @@
-# Search Tools Comparison Map
-
-## Tools Analyzed
-
-| Tool | Type | Scope | Speed |
-|------|------|-------|-------|
-| `rg` (ripgrep) | Exact text | Respects `.gitignore` | Fast |
-| `grep -rn` | Exact text | All files (incl. .venv) | Medium |
-| `loct find` | Symbol + Semantic | Indexed codebase | Fast |
-| `loct query` | Graph traversal | Dependency graph | Fast |
-| `loct` commands | Static analysis | Full codebase | Varies |
-| Claude `Grep` tool | Exact text (rg) | Respects `.gitignore` | Fast |
-
----
-
-## Quick Reference: When to Use What
-
-| Szukam... | Użyj | Dlaczego |
-|-----------|------|----------|
-| Dokładnego stringa | `rg` | Exact match, fast |
-| Stringa w dependencies | `grep -rn` lub `rg --no-ignore` | Searches .venv |
-| Eksportowanego symbolu | `loct find` lub `loct query where-symbol` | Symbol + semantic |
-| Czegoś z literówką | `loct find` | Semantic recovery |
-| Lokalnych zmiennych | `rg` | loct nie indeksuje locals |
-| Komentarzy/docstringów | `rg` | Text search |
-| Kto importuje plik? | `loct query who-imports` | Reverse deps |
-| Co się zepsuje jak zmienię? | `loct impact` | Transitive analysis |
-| Wszystkie FastAPI routes | `loct routes` | Framework-aware |
-| Circular imports | `loct cycles` | Graph analysis |
-| Unused code | `loct dead` / `loct zombie` | Static analysis |
-| Duplicate symbols | `loct twins` | Cross-file detection |
-| Directory overview | `loct focus` | LOC + deps tree |
-| Health check | `loct health` / `loct audit` | Full report |
-
----
-
-## Loct Command Reference
-
-### Instant Commands (<100ms)
-
-| Command | Description | JSON? | Use Case |
-|---------|-------------|-------|----------|
-| `loct find ` | Symbol + params + semantic search | ✅ | Find functions, classes, parameters by name |
-| `loct query who-imports ` | Reverse dependencies | ✅ | "What files import this?" |
-| `loct query where-symbol ` | Symbol definition + re-exports | ✅ | "Where is X defined?" |
-| `loct query component-of ` | Module ownership | ✅ | "What module owns this file?" |
-| `loct slice ` | File dependencies + LOC | ✅ | "What does this file depend on?" |
-| `loct impact ` | Transitive consumers | ✅ | "What breaks if I change this?" |
-| `loct focus ` | Directory context | ✅ | "Overview of this module" |
-| `loct hotspots` | Import frequency heatmap | ✅ | "What are the core files?" |
-| `loct health` | Quick health summary | ✅ | "Any obvious issues?" |
-
-> **Note (v0.8.4)**: All commands now support `--json` output. `loct find` also searches function parameters!
-
-### Analysis Commands
-
-| Command | Description | JSON? | Use Case |
-|---------|-------------|-------|----------|
-| `loct dead` | Unused exports | ✅ | Find dead code |
-| `loct cycles` | Circular imports | ✅ | Detect import cycles |
-| `loct twins` | Duplicate symbol names | ✅ | Find naming conflicts |
-| `loct zombie` | Dead + orphan + shadows | ✅ | Combined cleanup report |
-| `loct coverage` | Test gaps (structural) | ✅ | "What's not tested?" |
-| `loct audit` | Full codebase report | ❌ | Markdown health report |
-| `loct sniff` | Code smells aggregate | ❌ | twins + dead + crowds |
-| `loct crowd ` | Functional clustering | ❌ | "Files related to X" |
-| `loct tagmap ` | Unified search | ❌ | files + crowd + dead |
-
-### Framework-Specific
-
-| Command | Description | JSON? | Use Case |
-|---------|-------------|-------|----------|
-| `loct routes` | FastAPI/Flask routes | ✅ | List all API endpoints |
-| `loct commands` | Tauri FE↔BE handlers | ❌ | Frontend-backend bridges |
-| `loct events` | Event emit/listen flow | ❌ | Event analysis |
-
-### JQ Queries (on snapshot.json; artifacts cached by default)
-
-```bash
-loct '.metadata' # Scan metadata
-loct '.files | length' # Count files
-loct '.dead_parrots[]' # List dead exports
-loct '.cycles[]' # List circular imports
-```
-
----
-
-## Test Results
-
-### 1. Exported Symbol: `ResponsesAdapter`
-
-| Tool | Result |
-|------|--------|
-| **rg** | ✅ 3 files, exact matches (usage count) |
-| **loct find** | ✅ Symbol match + 19 semantic matches |
-| **loct query where-symbol** | ✅ Exact definition + line number |
-
-**Verdict**: OVERLAP - all find it, loct adds semantic context
-
----
-
-### 2. Typo: `streeming` (meant: streaming)
-
-| Tool | Result |
-|------|--------|
-| **rg** | ❌ No results |
-| **loct find** | ⚠️ Semantic recovery: StreamOptions (0.46) |
-
-**Verdict**: AUGMENT - loct recovers from typos, rg cannot
-
----
-
-### 3. Local Variable: `request_model`
-
-| Tool | Result |
-|------|--------|
-| **rg** | ✅ 14 hits in adapter.py |
-| **loct find** | ⚠️ No symbol match (not exported) |
-| **loct query where-symbol** | ❌ Not found |
-
-**Verdict**: AUGMENT - rg finds locals, loct only indexes exports
-
----
-
-### 4. Reverse Dependencies
-
-| Tool | Result |
-|------|--------|
-| **rg** | ❌ Cannot do reverse deps |
-| **loct query who-imports** | ✅ Full list with import type |
-
-```
-who-imports 'src/mlx_omni_server/responses/store.py':
- src/mlx_omni_server/responses/__init__.py - imports via import
- src/mlx_omni_server/responses/context_builder.py - imports via import
- src/mlx_omni_server/responses/router.py - imports via import
-```
-
-**Verdict**: UNIQUE to loct - graph traversal
-
----
-
-### 5. Impact Analysis
-
-| Tool | Result |
-|------|--------|
-| **rg** | ❌ Cannot analyze |
-| **loct impact** | ✅ Direct + transitive consumers with depth |
-
-```
-Impact analysis for: src/mlx_omni_server/responses/schema.py
- Direct consumers (4 files)
- Transitive impact (13 files)
- [!] Removing would affect 17 files (max depth: 4)
-```
-
-**Verdict**: UNIQUE to loct - refactoring blast radius
-
----
-
-### 6. API Routes Discovery
-
-| Tool | Result |
-|------|--------|
-| **rg '@router'** | ⚠️ Raw decorators, needs parsing |
-| **loct routes** | ✅ Parsed: method, path, handler, file, line |
-
-```json
-{
- "method": "POST",
- "path": "/v1/responses",
- "handler": "create_response",
- "file": "src/mlx_omni_server/responses/router.py",
- "line": 59
-}
-```
-
-**Verdict**: AUGMENT - loct parses, rg just finds text
-
----
-
-## Known Limitations
-
-### Loct False Positives
-
-1. ~~**Monkey-patching patterns**: compat.py exports symbols injected into `sys.modules` - loct sees them as dead~~ **FIXED in v0.8.4!** sys.modules injection now detected
-2. **Aliased imports**: `from x import y as _y` with noqa may not be tracked
-3. **Dynamic imports**: `importlib.import_module()` not detected
-
-### Loct Requires Exact Names
-
-```bash
-loct query where-symbol BatchCoordinator # ❌ Not found
-loct query where-symbol BatchRequestCoordinator # ✅ Found
-```
-
-Use `loct find` for fuzzy matching, `loct query` for exact.
-
----
-
-## Overlap vs Augment Diagram
-
-```
-┌─────────────────────────────────────────────────────────────────────┐
-│ SEARCH SPACE │
-│ │
-│ ┌────────────────────┐ │
-│ │ rg / grep │ ← Exact text, comments, locals, strings │
-│ │ │ │
-│ │ ┌─────────────────┼─────────────────┐ │
-│ │ │ OVERLAP │ │ │
-│ │ │ (exported │ loct find │ ← Semantic search, │
-│ │ │ symbols) │ │ typo recovery, │
-│ │ └─────────────────┼─────────────────┘ related symbols │
-│ │ │ │
-│ └────────────────────┘ │
-│ │
-│ ┌──────────────────────────────────────────────────────────────┐ │
-│ │ loct (UNIQUE) │ │
-│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────────────┐ │ │
-│ │ │ who- │ │ impact │ │ routes │ │ cycles/dead/ │ │ │
-│ │ │ imports │ │ analysis │ │ parsing │ │ twins/zombie │ │ │
-│ │ └──────────┘ └──────────┘ └──────────┘ └──────────────────┘ │ │
-│ └──────────────────────────────────────────────────────────────┘ │
-│ │
-│ GAP: Abstract concepts, natural language queries, runtime behavior │
-└─────────────────────────────────────────────────────────────────────┘
-```
-
----
-
-## Recommended Workflows
-
-### 1. Finding a Symbol
-```bash
-loct find MyClass # Semantic + exact
-rg 'class MyClass' # If loct misses (local class)
-```
-
-### 2. Before Refactoring
-```bash
-loct impact src/module/file.py # What breaks?
-loct slice src/module/file.py # What does it depend on?
-loct query who-imports src/module/file.py # Direct consumers
-```
-
-### 3. Code Cleanup
-```bash
-loct health # Quick overview
-loct dead # Unused exports
-loct twins # Duplicate names
-loct zombie # Combined report
-```
-
-### 4. Understanding a Directory
-```bash
-loct focus src/responses/ # Overview with LOC + deps
-loct hotspots # Core files in project
-```
-
-### 5. API Discovery
-```bash
-loct routes # All endpoints
-loct routes --json | jq '.routes[] | select(.method=="POST")'
-```
-
----
-
-## AI Integration (Claude Code Hooks)
-
-### Hook Augmentation (v10)
-
-Claude Code's Grep tool is automatically augmented with loctree context via PostToolUse hooks:
-
-```bash
-# ~/.claude/hooks/loct-grep-augment.sh
-# Every grep gets semantic context from loct find
-```
-
-**What Claude receives for each grep:**
-- `symbol_matches`: Exact symbol definitions with file + line
-- `param_matches`: Function parameters matching the pattern (NEW in 0.8.4)
-- `semantic_matches`: Similar symbols with similarity scores
-- `dead_status`: Whether the symbol is exported and/or dead
-
-**Example:** Grep for `template` → Hook augments with:
-- Symbol: `extract_vue_template`, `parse_svelte_template_usages`, `DynamicExecTemplate`
-- Params: `template: &str` in `parse_vue_template_usages()`
-- Semantic: Related symbols
-
-### Best Practices for AI
-
-1. **Use grep + hook augmentation** for exploratory searches
-2. **Use `loct find` directly** when you need semantic matching (typo recovery)
-3. **Use `loct impact`** before refactoring to know blast radius
-4. **Use `loct slice`** to understand a file's dependencies
-
----
-
-𝚅𝚒𝚋𝚎𝚌𝚛𝚊𝚏𝚝𝚎𝚍. with AI Agents ⓒ 2025-2026 Loctree Team
diff --git a/docs/tutorials/01_ai_agents_manual.md b/docs/tutorials/01_ai_agents_manual.md
deleted file mode 100644
index 0ba0c22f..00000000
--- a/docs/tutorials/01_ai_agents_manual.md
+++ /dev/null
@@ -1,931 +0,0 @@
-# AI Agent's Manual for Loctree
-
-> Complete guide for AI agents working with codebases using loctree.
-> For quick reference, see [AI_README.md](../../AI_README.md).
-
-## Table of Contents
-
-1. [Why Loctree?](#why-loctree)
-2. [Installation](#installation)
-3. [Core Concepts](#core-concepts)
-4. [Command Reference](#command-reference)
-5. [Agent Bundle for CI](#agent-bundle-for-ci)
-6. [Workflows](#workflows)
-7. [Language-Specific Features](#language-specific-features)
-8. [Integration Patterns](#integration-patterns)
-9. [Troubleshooting](#troubleshooting)
-
----
-
-## Why Loctree?
-
-Loctree is a static analysis tool designed for AI agents. It solves the fundamental problem of **context** - knowing what code exists, how it connects, and what's actually used.
-
-### Problems Loctree Solves
-
-| Problem | Without Loctree | With Loctree |
-|---------|-----------------|--------------|
-| Finding existing code | Grep/search, hope for the best | `loct find Button` |
-| Understanding dependencies | Read imports manually | `loct slice src/Component.tsx --consumers` (deps included) |
-| Knowing what uses a file | Search for import statements | `loct slice src/utils.ts --consumers` |
-| Dead code detection | Guesswork | `loct dead --confidence high` or `loct doctor` |
-| Circular import detection | Runtime errors | `loct cycles` or `loct doctor` |
-| Tauri FE↔BE coverage | Manual audit | `loct commands --missing` |
-
-### Key Philosophy
-
-1. **Scan once, slice many** - Initial scan builds a snapshot; subsequent queries are instant
-2. **Know why it works** - Graph-based analysis over assumptions
-3. **Reduce false positives** - Alias-aware, barrel-aware dead code detection
-4. **Holographic slices** - Extract exactly the context needed for a task
-
----
-
-## Installation
-
-```bash
-# Install from crates.io
-cargo install --locked loctree loctree-mcp
-
-# Verify installation
-loct --version
-```
-
-### Requirements
-
-- Rust toolchain (for installation)
-- Git repository (optional, enables git-aware features)
-
----
-
-## Core Concepts
-
-### Snapshot
-
-A snapshot is a cached representation of your codebase's structure:
-
-```
-.loctree/
-├── snapshot.json # Code graph (files, imports, exports)
-├── findings.json # All issues: dead_parrots, cycles, twins, shadows, orphans
-├── manifest.json # Index for tooling integration
-├── agent.json # AI-ready bundle (replaces --for-ai file)
-├── report.html # Human-readable HTML report
-└── report.sarif # SARIF 2.1.0 for IDE/CI integration
-```
-
-**Creating a snapshot:**
-```bash
-loct # Auto-detect stack, write snapshot.json (fast)
-loct --full-scan # Force rescan (ignore cached mtime)
-```
-
-> **Note (0.7.0+):** The `-A` flag is deprecated. Use `loct doctor` for interactive diagnostics instead.
-
-### Slicing
-
-Slicing extracts relevant context for a specific file or task:
-
-```bash
-# Get file's dependencies (what it imports)
-loct slice src/api/client.ts
-
-# Get file's consumers (what imports it)
-loct slice src/utils/format.ts --consumers
-
-# Full context (deps + consumers + file analysis)
-loct slice src/Component.tsx --consumers --json
-```
-
-### Graph
-
-The import graph maps relationships between files:
-
-```
-src/App.tsx
- └─imports→ src/components/Header.tsx
- └─imports→ src/components/Footer.tsx
- └─imports→ src/hooks/useAuth.ts
- └─imports→ src/api/auth.ts
-```
-
----
-
-## Command Reference
-
-### Short Aliases (v0.7.0+)
-
-Save keystrokes with these built-in aliases:
-
-| Alias | Command | Description |
-|-------|---------|-------------|
-| `s` | `slice` | File context extraction |
-| `f` | `find` | Symbol/file search |
-| `d` | `dead` | Dead export detection |
-| `t` | `twins` | Semantic duplicate analysis |
-| `h` | `health` | Quick health check |
-| `i` | `impact` | Change impact analysis |
-| `c` | `cycles` | Circular import detection |
-| `q` | `query` | Quick graph queries |
-
-**Examples:**
-```bash
-loct h # Quick health check
-loct d --confidence high # Dead exports
-loct s src/App.tsx --consumers # Slice with consumers
-loct f Button # Find Button symbol
-loct t --dead-only # Dead parrots only
-```
-
-### `loct` (default scan)
-
-Scans the project and generates all artifacts.
-
-```bash
-loct # Scan from current directory
-loct src src-tauri # Scan specific roots
-loct --full-scan # Force rescan
-loct --scan-all # Include node_modules, .venv, target
-```
-
-**Output:** Creates `.loctree/` with snapshot and all analysis artifacts.
-
-### `loct slice`
-
-Extract context for a file.
-
-```bash
-loct slice [options]
-
-Options:
- --consumers Include consumers (files that import this) – deps included by default
- --json Output as JSON (for piping to AI)
- --depth N Limit dependency depth (default: 3)
-```
-
-**Examples:**
-```bash
-# Context for AI task
-loct slice src/ChatPanel.tsx --consumers --json | claude
-
-# Just the imports (deps are default)
-loct slice src/utils.ts
-
-# What depends on this?
-loct slice src/api/types.ts --consumers
-```
-
-### `loct find`
-
-Search for code patterns and relationships.
-
-```bash
-loct find # Find symbol definitions and uses
-loct find # Fuzzy find similar names (avoid duplicates)
-loct impact # Show blast radius of changes
-```
-
-**Examples:**
-```bash
-# Before creating Button, check if it exists
-loct find Button
-
-# Find all uses of useAuth hook
-loct find useAuth
-
-# What breaks if I change api.ts?
-loct impact src/utils/api.ts
-```
-
-### `loct dead`
-
-Detect unused exports (dead code).
-
-```bash
-loct dead # All dead exports
-loct dead --confidence high # Only high-confidence (no test files)
-loct dead --json # JSON output
-```
-
-**Confidence levels:**
-- `high` - Export not imported anywhere in production code
-- `medium` - Export only used in tests
-- `low` - Complex re-export patterns, may be false positive
-
-### `loct cycles`
-
-Detect circular imports.
-
-```bash
-loct cycles # List all cycles
-loct cycles --json # JSON output with full paths
-```
-
-**Output example:**
-```
-Circular import detected:
- src/a.ts → src/b.ts → src/c.ts → src/a.ts
-```
-
-### `loct health`
-
-Quick health check summary — combines cycles + dead exports + twins in one command.
-
-```bash
-loct health # Quick summary
-loct health --json # JSON output for CI
-loct health src/ # Analyze specific directory
-```
-
-**Output example:**
-```
-Health Check Summary
-
-Cycles: 3 total (2 hard, 1 structural)
-Dead: 6 high confidence, 24 low
-Twins: 2 duplicate symbol groups
-
-Run `loct cycles`, `loct dead`, `loct twins` for details.
-```
-
-Use this for quick sanity checks before commits or in CI pipelines.
-
-### `loct audit`
-
-Full codebase audit — combines ALL structural analyses into one actionable report. Perfect for getting a complete picture of codebase health on day one.
-
-```bash
-loct audit # Full audit of current directory
-loct audit --json # JSON output for CI
-loct audit src/ # Audit specific directory
-```
-
-**What it includes:**
-- **Cycles** — Circular imports (hard + structural)
-- **Dead exports** — Unused code with 0 imports
-- **Twins** — Same symbol exported from multiple files
-- **Orphan files** — Files with 0 importers (not entry points)
-- **Shadow exports** — Consolidation candidates
-- **Crowds** — Files with similar dependency patterns
-
-**Output example:**
-```
-🔍 Full Codebase Audit
-
-CYCLES (3 total)
- 2 hard cycles (breaking)
- 1 structural cycle
-
-DEAD EXPORTS (12 total)
- 6 high confidence
- 6 low confidence
-
-TWINS (2 groups)
- useAuth exported from 2 files
- formatDate exported from 3 files
-
-ORPHAN FILES (4 files, 1,200 LOC)
- src/legacy/old-utils.ts (450 LOC)
- ...
-
-SHADOW EXPORTS (1)
- store exported by 2 files, 1 dead
-
-CROWDS (2 clusters)
- API handlers: 5 similar files
- Form components: 3 similar files
-
-─────────────────────────────────
-Total: 22 findings to review
-```
-
-Use `loct audit` when onboarding to a new codebase or for comprehensive CI checks. Use `loct health` for quick daily checks.
-
-### `loct doctor` (v0.7.0+)
-
-Interactive diagnostics with actionable recommendations. This is the successor to `loct audit` with intelligent categorization and auto-fix suggestions.
-
-```bash
-loct doctor # Full diagnostics
-loct doctor --apply-suppressions # Auto-add patterns to .loctignore
-```
-
-**Categories findings into:**
-- **Auto-fixable**: High confidence, safe to remove
-- **Needs review**: Low confidence, verify manually
-- **Suggested suppressions**: Patterns for `.loctignore`
-
-**Example output:**
-```
-=== Doctor Diagnostics ===
-
-Found 65 issues: 60 auto-fixable, 5 need review
-
-Dead Exports (12 total):
- 10 high confidence (safe to remove)
- 2 low confidence (needs review)
-
-Cycles (3 total):
- 2 hard cycles (breaking)
- 1 structural cycle
-
-Twins (8 groups):
- Button exported from 2 files
- formatDate exported from 3 files
-
-Suggested .loctignore entries:
- **/index.*
- **/*test*
-
-Next steps:
- 1. Review high-confidence dead exports and remove if safe
- 2. Run tests after each removal
- 3. Break hard cycles (structural cycles are often harmless)
-```
-
-**Workflow:**
-```bash
-# 1. Run diagnostics
-loct doctor
-
-# 2. Apply suppressions for known false positives
-loct doctor --apply-suppressions
-
-# 3. Fix high-confidence issues one by one
-# 4. Verify with tests after each fix
-# 5. Re-run doctor to track progress
-```
-
-### `loct twins`
-
-Semantic duplicate analysis — finds dead parrots, exact twins, and barrel chaos.
-
-```bash
-loct twins # Full analysis: dead parrots + exact twins + barrel chaos
-loct twins --dead-only # Only exports with 0 imports
-loct twins --path src/ # Analyze specific path
-```
-
-**What it detects:**
-
-1. **Dead Parrots** — exports with zero imports (Monty Python reference: code that's "just resting")
- ```
- DEAD PARROTS (75 symbols with 0 imports)
- ├─ ChatPanelTabs (reexport:6) - 0 imports
- ├─ update_profile (reexport:0) - 0 imports
- └─ ...
- ```
-
-2. **Exact Twins** — same symbol name exported from multiple files
- ```
- EXACT TWINS (150 duplicates)
- ├─ "Button" exported from:
- │ src/components/Button.tsx
- │ src/ui/Button.tsx
- └─ ...
- ```
-
-3. **Barrel Chaos** — barrel file issues
- - Missing `index.ts` in directories with many external imports
- - Deep re-export chains (A → B → C → D)
- - Inconsistent import paths (same symbol imported via different paths)
-
-### `loct commands`
-
-Tauri FE↔BE command coverage.
-
-```bash
-loct commands --missing # FE invokes without BE handlers
-loct commands --unused # BE handlers without FE invokes
-loct commands --json # Full command mapping
-```
-
-### `loct events`
-
-Tauri event coverage (emit/listen pairs).
-
-```bash
-loct events # Summary
-loct events --json # Full event mapping
-loct events --ghosts # Emits without listeners
-loct events --orphans # Listeners without emitters
-```
-
-### `loct lint`
-
-CI-friendly linting with policy enforcement.
-
-```bash
-loct lint --fail # Exit 1 if issues found
-loct lint --sarif > results.sarif # SARIF output for IDE
-loct lint --max-dead 0 # Fail if any dead exports
-loct lint --max-cycles 0 # Fail if any circular imports
-```
-
-### `loct git`
-
-Git-aware analysis.
-
-```bash
-loct git compare HEAD~5..HEAD # Semantic diff between commits
-loct git blame src/lib.rs # Symbol-level blame (Rust)
-loct git history --symbol foo # Track symbol evolution
-```
-
-### `loct diff`
-
-Compare snapshots to see what changed.
-
-```bash
-loct diff --since # Compare current vs old snapshot
-loct diff --since main # Compare against main branch snapshot
-```
-
-### jq-style queries
-
-Query snapshot data directly using jq syntax (powered by jaq, a Rust-native jq implementation).
-
-```bash
-loct '' # Query current snapshot
-loct '' --snapshot # Query specific snapshot
-```
-
-**Flags:**
-- `-r` — Raw output (no JSON quotes)
-- `-c` — Compact output (single line)
-- `-e` — Exit code based on empty result
-- `--arg NAME VALUE` — Pass string variable
-- `--argjson NAME JSON` — Pass JSON variable
-
-**Examples:**
-```bash
-# Metadata
-loct '.metadata'
-
-# Count files
-loct '.files | length'
-
-# Find large files (>500 LOC)
-loct '.files[] | select(.loc > 500)' -c
-
-# Filter edges by pattern
-loct '.edges[] | select(.from | contains("api"))'
-
-# List Tauri commands
-loct '.command_bridges | map(.name)'
-
-# Find top export duplicates
-loct '.export_index | to_entries | map(select(.value | length > 1)) | sort_by(.value | length) | reverse | .[0:5]'
-
-# Query findings (0.7.0+)
-loct '.dead_parrots' # Dead exports from findings
-loct '.cycles' # Circular imports
-loct '.twins[:5]' # First 5 twin groups
-loct '.orphans' # Orphan files
-loct '.shadows' # Shadow exports
-```
-
-**Use cases:**
-- Quick codebase statistics
-- Custom filtering and aggregation
-- Integration with shell pipelines
-- Extracting specific data for analysis
-
-**Output includes:**
-- Files added, removed, modified
-- New/resolved circular imports
-- New/removed dead exports
-- Changed graph edges
-
-### `loct dist`
-
-Bundle distribution analysis — verify tree-shaking by comparing source exports against production bundles using source maps.
-
-```bash
-loct dist dist/bundle.js.map src/ # Analyze bundle vs source
-```
-
-**Output:**
-```
-✓ Found 4 dead export(s) (67%)
-Bundle Analysis:
- Source exports: 6
- Bundled exports: 2
- Dead exports: 4
- Reduction: 67%
- Analysis level: symbol
-
-Dead Exports (not in bundle):
- deadFunction (function) in index.ts:5
- DEAD_CONST (var) in index.ts:10
-```
-
-**Features:**
-- Symbol-level detection via VLQ Base64 decoding of source map mappings
-- File-level fallback when source maps lack `names` array
-- Verifies bundler (Vite/Webpack/esbuild) actually eliminated dead code
-
-### `loct query`
-
-Quick graph queries without full analysis.
-
-```bash
-loct query who-imports # Files that import target
-loct query where-symbol # Where symbol is defined/used
-loct query component-of # Graph component containing file
-```
-
-**Examples:**
-```bash
-# What imports my utils?
-loct query who-imports src/utils/helpers.ts
-
-# Where is useAuth defined?
-loct query where-symbol useAuth
-
-# Is this file isolated or connected?
-loct query component-of src/orphan.ts
-```
-
-### jq-style Queries (v0.6.15+)
-
-Query snapshot data directly using jq syntax. Uses jaq (Rust-native jq implementation) for zero external dependencies.
-
-```bash
-loct '' [options]
-```
-
-**Basic Usage:**
-```bash
-loct '.metadata' # Extract snapshot metadata
-loct '.files | length' # Count files in codebase
-loct '.edges | length' # Count import edges
-loct '.command_bridges | length' # Count Tauri commands
-```
-
-**Filtering:**
-```bash
-# Find all edges from api/ directory
-loct '.edges[] | select(.from | contains("api"))'
-
-# Find large files (>500 LOC)
-loct '.files[] | select(.loc > 500)'
-
-# Get all file paths
-loct '.files[].path' -r
-
-# List Tauri command names
-loct '.command_bridges | map(.name)'
-```
-
-**Options:**
-| Flag | Description |
-|------|-------------|
-| `-r`, `--raw` | Raw output (no JSON quotes for strings) |
-| `-c`, `--compact` | Compact output (one line per result) |
-| `-e`, `--exit-status` | Exit 1 if result is false/null |
-| `--arg ` | Bind string variable |
-| `--argjson ` | Bind JSON variable |
-| `--snapshot ` | Use specific snapshot file |
-
-**Variable Binding:**
-```bash
-# Find edges from specific file
-loct '.edges[] | select(.from == $file)' --arg file 'src/api.ts'
-
-# Files with LOC above threshold
-loct '.files[] | select(.loc > $min)' --argjson min 300
-```
-
-**Important:** Filter must come before flags:
-```bash
-# ✅ Correct
-loct '.edges[]' --arg file 'foo.ts'
-
-# ❌ Won't work
-loct --arg file 'foo.ts' '.edges[]'
-```
-
-**Snapshot Discovery:**
-- Auto-discovers newest `.loctree/*/snapshot.json` by modification time
-- Use `--snapshot path/to/snapshot.json` to specify explicitly
-
----
-
-## Agent Bundle for CI
-
-The agent bundle is a complete analysis package for CI pipelines:
-
-```
-.loctree/
-├── snapshot.json # Code graph (files, imports, exports)
-├── findings.json # All issues: dead_parrots, cycles, twins, shadows, orphans
-├── manifest.json # Index for tooling integration
-├── agent.json # AI-ready bundle (replaces --for-ai file)
-├── report.sarif # SARIF 2.1.0 for GitHub/GitLab
-├── report.html # Human review
-└── py_races.json # Python concurrency (if applicable)
-```
-
-### CI Integration
-
-**GitHub Actions:**
-```yaml
-- name: Run loctree analysis
- run: |
- cargo install --locked loctree
- loct
-
-- name: Upload SARIF
- uses: github/codeql-action/upload-sarif@v2
- with:
- sarif_file: .loctree/report.sarif
-```
-
-**Policy enforcement:**
-```yaml
-- name: Check code quality
- run: |
- loct lint --max-dead 0 --max-cycles 0 --fail
-```
-
-**Using findings.json in CI:**
-```yaml
-- name: Check for issues
- run: |
- loct
- dead_count=$(loct '.dead_parrots | length')
- cycle_count=$(loct '.cycles | length')
- echo "Dead exports: $dead_count"
- echo "Cycles: $cycle_count"
- if [ "$dead_count" -gt 0 ] || [ "$cycle_count" -gt 0 ]; then
- exit 1
- fi
-```
-
-### SARIF Contents
-
-The `report.sarif` includes:
-- `duplicate-export` - Same symbol exported from multiple files
-- `missing-handler` - Frontend command without backend handler
-- `unused-handler` - Backend handler without frontend usage
-- `dead-export` - Export never imported
-- `circular-import` - Circular dependency chain
-- `ghost-event` - Event emitted but never listened
-- `orphan-listener` - Listener for non-existent event
-
-### IDE Integration URLs
-
-SARIF results include `loctree://open?f=&l=` URLs in `properties.openUrl` for direct IDE navigation. Compatible with:
-- VS Code (via URL handler extension)
-- JetBrains IDEs (built-in URL handling)
-- Custom editor integrations
-
----
-
-## Workflows
-
-### Starting a New Task
-
-```bash
-# 1. Scan the project (or use cached snapshot)
-loct
-
-# 2. Find relevant context
-loct find FeatureName # Check for existing code
-loct slice src/related.ts --consumers --json
-
-# 3. Understand impact
-loct impact src/file-to-modify.ts
-```
-
-### Before Creating a New Component
-
-```bash
-# Check if similar exists
-loct find Button
-loct find ButtonComponent
-loct find useButton
-
-# If creating, check where to place it
-loct slice src/components/index.ts --consumers
-```
-
-### Debugging Import Issues
-
-```bash
-# Find circular imports
-loct cycles
-
-# Check what imports what
-loct slice problematic-file.ts --consumers
-```
-
-### Cleaning Up Dead Code
-
-```bash
-# Use doctor for interactive diagnostics (0.7.0+)
-loct doctor
-
-# Or find candidates manually
-loct dead --confidence high --json
-
-# Verify each before deletion
-loct find suspectedDead
-loct slice file-with-dead-code.ts --consumers
-```
-
-### Tauri Development
-
-```bash
-# Check FE↔BE contract
-loct commands --missing # What's called but not implemented?
-loct commands --unused # What's implemented but never called?
-
-# Event flow
-loct events --json # Full emit/listen mapping
-loct events --ghosts # Emits going nowhere
-```
-
----
-
-## Language-Specific Features
-
-### TypeScript/JavaScript
-
-- **Path aliases** - Respects `tsconfig.json` `paths` and `baseUrl`
-- **Barrel files** - Understands `index.ts` re-exports
-- **Dynamic imports** - Tracks `import()` expressions
-- **JSX/TSX** - Full support
-- **Flow types** - Flow annotation support (v0.6.x)
-- **WeakMap/WeakSet patterns** - Registry pattern detection (v0.6.x)
-- **.d.ts re-exports** - Proper type-only re-export tracking (v0.6.x)
-
-### SvelteKit
-
-- **Virtual modules** - Resolves `$app/navigation`, `$app/stores`, `$app/environment`, `$app/paths`
-- **`$lib` alias** - Maps `$lib/*` to configured library path
-- **Runtime modules** - Correctly resolves SvelteKit internal runtime paths
-- **Server/client split** - Understands `.server.ts` and `+page.server.ts` patterns
-- **.d.ts re-exports** - Tracks Svelte component type exports (v0.6.x)
-
-### Python
-
-- **Namespace packages** - PEP 420 support (no `__init__.py` required)
-- **Typed packages** - PEP 561 `py.typed` marker detection
-- **Test detection** - Distinguishes test files from production
-- **Concurrency patterns** - Detects threading/asyncio/multiprocessing
-- **`__all__` tracking** - Respects public API declarations (v0.6.x)
-- **Library mode** - Auto-detects Python stdlib (Lib/ directory) (v0.6.x)
-
-### Rust
-
-- **Crate structure** - Understands `mod` declarations and module hierarchy
-- **Crate-internal imports** - Resolves `use crate::foo::Bar`, `use super::Bar`, `use self::foo::Bar`
-- **Same-file usage** - Detects when exported symbols are used locally (e.g., `BUFFER_SIZE` in generics like `fn foo::()`)
-- **Nested brace imports** - Handles complex imports like `use crate::{foo::{A, B}, bar::C}`
-- **Tauri integration** - `#[tauri::command]` detection
-- **Symbol-level blame** - Git blame for fn/struct/enum/impl
-
-### Go
-
-- **Package structure** - Understands Go package imports
-- **Cross-package references** - Accurate dead code detection across packages
-- **Standard library** - Stdlib imports tracked correctly
-
-### Dart/Flutter (v0.6.x)
-
-- **Package imports** - Resolves `package:` imports
-- **Auto-detection** - Recognizes `pubspec.yaml`, ignores `.dart_tool/`, `build/`
-- **Full language support** - Imports, exports, dead code detection
-
-### Vue
-
-- **Single File Components (SFC)** - `
-
-
-
-{chatInput?.focusInput()}
-```
-
-### Version History
-
-| Version | FP Rate | Status |
-|---------|---------|--------|
-| 0.5.16 | 40-50% | Default imports broken |
-| 0.5.17 | 8.4% | Major improvement |
-| 0.6.1-dev | 0% | PERFECT |
-| 0.6.2-dev | 25-33% | REGRESSION |
-
-## Commands Used
-
-```bash
-cd GitButler
-loct # Create snapshot
-loct dead --confidence high # Dead code analysis
-loct twins # Duplicate detection
-```
-
-## Verdict
-
-**REGRESSION** - Svelte component method refs need fixing.
-
-## Key Insights
-
-1. **Svelte Components**: Method refs via `bind:this` not tracked
-2. **Rust Analysis**: Works well
-3. **Tauri Integration**: Command bridges functional
-
-## Workaround
-
-Until fixed, manually verify Svelte component exports:
-```bash
-loct dead --confidence high | grep ".svelte" | while read line; do
- symbol=$(echo "$line" | awk -F: '{print $NF}')
- rg "\\.$symbol\\(" . --type svelte
-done
-```
-
----
-
-*Tested by M&K ⓒ 2025-2026 The Loctree Team*
diff --git a/docs/use-cases/14_golang.md b/docs/use-cases/14_golang.md
deleted file mode 100644
index 3cd6529b..00000000
--- a/docs/use-cases/14_golang.md
+++ /dev/null
@@ -1,59 +0,0 @@
-# Use Case: golang/go - The Go Standard Library
-
-**Repository**: https://github.com/golang/go
-**Stack**: Go
-**Test Date**: 2025-12-08
-**Loctree Version**: 0.6.2-dev
-
----
-
-## Overview
-
-Testing loctree on THE Go standard library - 17,000+ files of pure Go code.
-
-## Repository Scale
-
-| Metric | Value |
-|--------|-------|
-| **Go Files** | 17,182 |
-| **Analysis Time** | 107 seconds |
-| **Throughput** | 160 files/sec |
-
-## Findings
-
-### Dead Code Detection
-- **High Confidence**: 1 finding
-- **False Positive Rate**: ~0%
-
-The single finding is a Python GDB helper edge case (`ChanTypePrinter` used in tuple literals) - acceptable edge case for cross-language tooling.
-
-### Version History
-
-| Version | FP Rate | Status |
-|---------|---------|--------|
-| 0.5.16 | 0% | PERFECT |
-| 0.6.1-dev | 100% | REGRESSION |
-| 0.6.2-dev | ~0% | FIXED |
-
-## Commands Used
-
-```bash
-cd GoLang
-loct # Create snapshot (107s)
-loct dead --confidence high # Dead code analysis
-loct twins # Duplicate detection
-```
-
-## Verdict
-
-**PERFECT** - Go analysis is production-ready. The 0.6.1 regression was fixed in 0.6.2.
-
-## Key Insights
-
-1. **Scalability**: 17K files in under 2 minutes
-2. **Accuracy**: Near-zero false positives
-3. **Regression Fixed**: Cross-package reference tracking restored
-
----
-
-*Tested by M&K ⓒ 2025-2026 The Loctree Team*
diff --git a/docs/use-cases/15_typescript.md b/docs/use-cases/15_typescript.md
deleted file mode 100644
index aa3bbb5e..00000000
--- a/docs/use-cases/15_typescript.md
+++ /dev/null
@@ -1,77 +0,0 @@
-# Use Case: microsoft/TypeScript - The TypeScript Compiler
-
-**Repository**: https://github.com/microsoft/TypeScript
-**Stack**: TypeScript
-**Test Date**: 2025-12-08
-**Loctree Version**: 0.6.2-dev
-
----
-
-## Overview
-
-Testing loctree on THE TypeScript compiler - the ultimate TypeScript analysis test.
-
-## Repository Scale
-
-| Metric | Value |
-|--------|-------|
-| **Total Files** | 75,496 |
-| **Source Files** | `/src` with 21 subdirectories |
-| **Test Fixtures** | `/tests/cases/` (thousands) |
-
-## Known Issue
-
-**UTF-8 Error on Full Repository**:
-```
-Error: stream did not contain valid UTF-8
-```
-
-**Cause**: TypeScript's test suite contains intentionally malformed files to test compiler edge cases:
-- Non-UTF-8 encodings
-- BOM markers
-- Invalid byte sequences
-- Unicode edge cases
-
-**This is NOT a loctree bug** - it's a valid limitation exposed by compiler test fixtures.
-
-## Recommendations
-
-### Option 1: Scan `/src` Only
-```bash
-cd TypeScript/src
-loct # Only production code
-loct dead --confidence high
-```
-
-### Option 2: Use `.loctreeignore`
-```
-# .loctreeignore
-tests/
-```
-
-### Option 3: Alternative Test Targets
-Real-world TypeScript projects work fine:
-- VSCode
-- Playwright
-- Angular
-- NestJS
-
-## Future Improvements Needed
-
-1. **`--skip-invalid-utf8`** flag for graceful degradation
-2. **`.loctreeignore`** support for file exclusion
-3. **Better error context** showing which file failed
-
-## Verdict
-
-**BLOCKED** - Test fixtures with intentional encoding violations prevent full scan. Production TypeScript codebases work fine.
-
-## Key Insights
-
-1. **Edge Case**: Compiler test suites are extreme edge cases
-2. **Production Safe**: Real TS projects are properly UTF-8 encoded
-3. **Feature Request**: Graceful UTF-8 error handling
-
----
-
-*Tested by M&K ⓒ 2025-2026 The Loctree Team*
diff --git a/docs/use-cases/16_nodejs.md b/docs/use-cases/16_nodejs.md
deleted file mode 100644
index 7179ead7..00000000
--- a/docs/use-cases/16_nodejs.md
+++ /dev/null
@@ -1,73 +0,0 @@
-# Use Case: nodejs/node - The Node.js Runtime
-
-**Repository**: https://github.com/nodejs/node
-**Stack**: JavaScript + C++
-**Test Date**: 2025-12-08
-**Loctree Version**: 0.6.2-dev
-
----
-
-## Overview
-
-Testing loctree on THE Node.js runtime - massive hybrid codebase.
-
-## Repository Scale
-
-| Metric | Value |
-|--------|-------|
-| **Total Files** | ~20,400 JS files |
-| **lib/ Only** | 348 files |
-| **Analysis Time** | 0.13s (lib/ only) |
-
-## Known Issue
-
-**UTF-8 Error on Full Repository**:
-```
-Error: stream did not contain valid UTF-8
-```
-
-**Cause**: Binary ICU Unicode data files (`icudt77l.dat.bz2`)
-
-**Workaround**: Test `lib/` directory only.
-
-## Findings (lib/ Directory)
-
-### Dead Code Detection
-- **High Confidence**: 1 finding
-- **False Positive Rate**: 0%
-
-The single finding (`eslint.config_partial.mjs` default export) is a true positive within the isolated scope.
-
-### Architecture
-- **Circular Imports**: 0 (perfect architecture!)
-- Node.js core lib has excellent module structure
-
-## Commands Used
-
-```bash
-cd nodejs/lib
-loct # Create snapshot (0.13s!)
-loct dead --confidence high # Dead code analysis
-loct cycles # Circular dependencies
-```
-
-## Verdict
-
-**INCONCLUSIVE** - Binary file handling needs improvement.
-
-## Key Insights
-
-1. **Performance**: Lightning fast on pure JS (0.13s for 348 files)
-2. **Accuracy**: 0% FP within scope
-3. **Blocker**: Binary file detection needed
-
-## Recommendations
-
-For Node.js-style repos:
-1. Add `.loctreeignore` for binary directories
-2. Implement graceful UTF-8 error recovery
-3. Auto-detect and skip binary files
-
----
-
-*Tested by M&K ⓒ 2025-2026 The Loctree Team*
diff --git a/docs/use-cases/17_cpython.md b/docs/use-cases/17_cpython.md
deleted file mode 100644
index 173f0a01..00000000
--- a/docs/use-cases/17_cpython.md
+++ /dev/null
@@ -1,81 +0,0 @@
-# Use Case: python/cpython - The Python Interpreter
-
-**Repository**: https://github.com/python/cpython
-**Stack**: Python (+ C)
-**Test Date**: 2025-12-08
-**Loctree Version**: 0.6.2-dev
-
----
-
-## Overview
-
-Testing loctree on THE Python interpreter source - the reference implementation of Python.
-
-## Repository Scale
-
-| Metric | Value |
-|--------|-------|
-| **Python Files** | 842 (stdlib) |
-| **Analysis Time** | 25.09 seconds |
-| **Throughput** | 33 files/sec |
-
-## Findings
-
-### Dead Code Detection
-- **High Confidence**: 278 candidates (v0.6.1)
-- **False Positive Rate**: 100% without library mode
-- **With `--library-mode`**: Auto-detects stdlib, excludes `__all__` exports
-
-### Why Library Mode Matters (v0.6.x)
-
-Without library mode, all flagged exports are **public API** for external use:
-- `calendar.APRIL` - Public API constant
-- `csv.DictWriter` - Core utility class
-- `ftplib.all_errors` - Used by urllib, socket, asyncio
-- `typing.override` - Used across stdlib
-
-**v0.6.x improvements**:
-- Auto-detects `Lib/` directory as stdlib
-- Respects `__all__` declarations in modules
-- Use `--library-mode` for proper stdlib analysis
-
-### Additional Findings
-- **Dead Parrots**: 172 classes/functions
-- **Circular Dependencies**: 2 lazy cycles (both safe)
-
-## Known Issue
-
-**Unicode Bug Found**: Devanagari numerals (like `६`) in test files caused panic at `py.rs:224:32`. Test directory excluded to complete scan.
-
-**Status**: Fixed in subsequent patch using `bytes_match_keyword`.
-
-## Commands Used
-
-```bash
-cd cpython
-loct # Create snapshot
-loct dead --confidence high # Dead code analysis
-loct cycles # Circular dependencies
-```
-
-## Verdict
-
-**LIBRARY MODE REQUIRED** - Use `--library-mode` for proper stdlib analysis (v0.6.x).
-
-## Key Insights
-
-1. **Performance**: Fast and stable (33 files/sec)
-2. **Accuracy**: Requires library mode for public API analysis
-3. **v0.6.x**: Auto-detection of stdlib, `__all__` tracking implemented
-
-## Recommendations
-
-For Python stdlib/library analysis:
-- Use `--library-mode` flag for automatic `__all__` exclusion
-- Auto-detects `Lib/` directory as Python stdlib
-- `pyproject.toml` parsing for public API hints
-- Focus on internal modules (`_internal/`, `_impl/`) for application code
-
----
-
-*Tested by M&K ⓒ 2025-2026 The Loctree Team*
diff --git a/docs/use-cases/18_rust.md b/docs/use-cases/18_rust.md
deleted file mode 100644
index e90894d8..00000000
--- a/docs/use-cases/18_rust.md
+++ /dev/null
@@ -1,112 +0,0 @@
-# Use Case: rust-lang/rust - The Rust Compiler
-
-**Repository**: https://github.com/rust-lang/rust
-**Stack**: Rust
-**Test Date**: 2025-12-08
-**Loctree Version**: 0.6.2-dev
-
----
-
-## Overview
-
-The ultimate stress test for Rust analysis - analyzing THE Rust compiler source code itself.
-
-## Repository Scale
-
-| Metric | Value |
-|--------|-------|
-| **Rust Files** | 35,387 |
-| **Total Symbols** | 79,891 |
-| **Repository Size** | 558 MB |
-| **Snapshot Size** | 149 MB |
-
-## Performance
-
-| Metric | Value |
-|--------|-------|
-| **Scan Time** | ~45 seconds |
-| **Throughput** | 787 files/sec |
-| **Dead Analysis** | < 1 second |
-| **Cycles Analysis** | < 1 second |
-
-## Findings
-
-### Dead Code Detection
-- **High Confidence**: 1 finding (test fixture - intentional)
-- **False Positive Rate**: 0%
-
-### Circular Dependencies - Architectural Analysis
-```
-✓ Found 91 circular import cycles (intra-crate)
-```
-
-**Notable cycles detected**:
-
-1. **Core Library** (78-hop chain):
- ```
- core/src/alloc/layout.rs → error.rs → fmt/mod.rs →
- cell.rs → cmp.rs → ... (78 intermediate) ... → fmt/builders.rs
- ```
-
-2. **Type System** (48-hop chain):
- ```
- rustc_middle/src/mir/mono.rs → dep_graph/mod.rs → ty/mod.rs →
- ... (48 intermediate) ... → ty/diagnostics.rs
- ```
-
-3. **AST Module**:
- ```
- rustc_ast/src/ast.rs → format.rs → token.rs →
- tokenstream.rs → ast_traits.rs → util/parser.rs → visit.rs
- ```
-
-**Manual Verification Result**: These are **NOT bugs** - they are normal Rust architecture:
-- All cycles are **intra-crate** (`crate::` imports within same library)
-- Rust allows modules within the same crate to mutually import each other
-- Compiler resolves via lazy name resolution + type checking post-resolution
-- This is fundamentally different from JavaScript/Python circular imports
-- **No upstream issue warranted** - this is standard Rust module organization
-
-### Twins Analysis
-- **Exact Duplicates**: 7,918 (mostly test `main()` functions)
-- **False Positive Rate**: 0% - expected pattern for test suite
-
-## Commands Used
-
-```bash
-cd rust-lang
-loct # Create snapshot (45s)
-loct dead --confidence high # Dead code analysis
-loct cycles # Circular dependencies
-loct twins # Duplicate detection
-```
-
-## Verdict
-
-**EXCEPTIONAL** - If loctree handles rust-lang/rust, it handles ANY Rust project.
-
-## Key Insights
-
-1. **Scalability Proven**: 35K files in 45 seconds
-2. **Accuracy Validated**: 0% FP on dead code
-3. **Cycle Detection**: Found 91 real architectural cycles (intra-crate, by design)
-4. **Zero Crashes**: Complete analysis on 558 MB codebase
-
-## Note on Intra-Crate Cycles
-
-Unlike JavaScript/Python where circular imports can cause `undefined`/`None` at runtime, Rust's module system handles intra-crate cycles gracefully:
-
-```rust
-// This is VALID Rust - fmt imports cell, cell imports fmt
-// crate::fmt::mod.rs
-use crate::cell::Cell;
-
-// crate::cell.rs
-use crate::fmt::{Debug, Display};
-```
-
-Loctree correctly detects these architectural patterns but they should be interpreted as "module interdependencies" rather than "problematic cycles."
-
----
-
-*Tested by M&K ⓒ 2025-2026 The Loctree Team*
diff --git a/docs/use-cases/19_sveltekit.md b/docs/use-cases/19_sveltekit.md
deleted file mode 100644
index 11ced179..00000000
--- a/docs/use-cases/19_sveltekit.md
+++ /dev/null
@@ -1,75 +0,0 @@
-# Use Case: sveltejs/kit - The SvelteKit Framework
-
-**Repository**: https://github.com/sveltejs/kit
-**Stack**: TypeScript + Svelte
-**Test Date**: 2025-12-08
-**Loctree Version**: 0.6.2-dev
-
----
-
-## Overview
-
-Testing loctree on SvelteKit - validating virtual module resolution (`$app/*`, `$lib/*`).
-
-## Repository Scale
-
-| Metric | Value |
-|--------|-------|
-| **Files Scanned** | 1,117 |
-| **Analysis Time** | 26.92 seconds |
-| **Throughput** | 41 files/sec |
-
-## Findings
-
-### Dead Code Detection
-- **High Confidence**: 0
-- **False Positive Rate**: ~0%
-
-### Virtual Module Resolution - MAJOR FIX
-```typescript
-// Previously flagged as dead (WRONG):
-export function enhance() { } // in packages/kit/src/runtime/app/forms.js
-
-// Used via virtual module:
-import { enhance } from '$app/forms'; // NOW CORRECTLY RESOLVED!
-```
-
-### Version History
-
-| Version | FP Rate | Status |
-|---------|---------|--------|
-| 0.5.16 | 83% | Virtual modules broken |
-| 0.5.17 | 67% | Slightly better |
-| 0.6.1-dev | ~100% | REGRESSION |
-| 0.6.2-dev | ~0% | FIXED! |
-
-## Commands Used
-
-```bash
-cd SvelteKit
-loct # Create snapshot
-loct dead --confidence high # Dead code analysis
-loct twins # Duplicate detection
-```
-
-## Verdict
-
-**EXCELLENT** - Virtual module resolution is production-ready.
-
-## Key Insights
-
-1. **Virtual Modules**: `$app/forms`, `$lib/*` correctly resolved
-2. **Framework Magic**: `load()`, `prerender` exports recognized
-3. **Major Improvement**: From 100% FP to ~0% FP
-
-## SvelteKit-Specific Features
-
-Loctree now handles:
-- `$app/forms`, `$app/navigation`, `$app/stores`
-- `$lib/*` path aliases
-- `+page.server.ts` magic exports
-- `export const prerender = true` patterns
-
----
-
-*Tested by M&K ⓒ 2025-2026 The Loctree Team*
diff --git a/docs/use-cases/20_svelte.md b/docs/use-cases/20_svelte.md
deleted file mode 100644
index b5cff650..00000000
--- a/docs/use-cases/20_svelte.md
+++ /dev/null
@@ -1,72 +0,0 @@
-# Use Case: sveltejs/svelte - The Svelte Compiler
-
-**Repository**: https://github.com/sveltejs/svelte
-**Stack**: TypeScript/JavaScript
-**Test Date**: 2025-12-08
-**Loctree Version**: 0.6.2-dev
-
----
-
-## Overview
-
-Testing loctree on THE Svelte compiler source - the core that powers the Svelte framework.
-
-## Repository Scale
-
-| Metric | Value |
-|--------|-------|
-| **Files Scanned** | 405 |
-| **Analysis Time** | ~30 seconds |
-| **Throughput** | 13.5 files/sec |
-
-## Findings
-
-### Dead Code Detection
-- **High Confidence**: 47 candidates
-- **False Positive Rate**: 70%
-- **True Positives**: 3-4 genuinely dead internal functions
-
-### Confirmed Dead Code
-- `ELEMENTS_WITHOUT_TEXT`
-- `log_reactions`
-- `not_equal`
-- `bind_props`
-
-### False Positive Categories
-1. **TypeScript .d.ts re-exports** (60% of FPs) - easing functions, SSR functions
-2. **Compiler-generated usage** (30% of FPs) - functions used by compiled `.svelte` output
-3. **Dynamic references** (10% of FPs) - runtime lookups, reflection patterns
-
-### Additional Findings
-- **Dead Parrots**: 3,942 (TypeScript definition duplicates)
-- **Circular Dependencies**: 15 (6 architectural, 9 test fixtures)
-
-## Commands Used
-
-```bash
-cd svelte-core
-loct # Create snapshot
-loct dead --confidence high # Dead code analysis
-loct cycles # Circular dependencies
-loct twins # Duplicate detection
-```
-
-## Verdict
-
-**PASSED with caveats** - Excellent for internal dead code, needs `--library-mode` for public API.
-
-## Key Insights
-
-1. **Internal dead code**: 100% accurate (3/3 true positives)
-2. **Public API exports**: 70% FP (expected for library codebases)
-3. **Value delivered**: Identified 3-4 genuinely dead functions for cleanup
-
-## Recommendations
-
-- Use `--library-mode` flag when analyzing framework/library source
-- Focus on internal modules, not public API barrel exports
-- Cross-reference with `package.json` exports field
-
----
-
-*Tested by M&K ⓒ 2025-2026 The Loctree Team*
diff --git a/docs/use-cases/21_tauri.md b/docs/use-cases/21_tauri.md
deleted file mode 100644
index 8ad2d54c..00000000
--- a/docs/use-cases/21_tauri.md
+++ /dev/null
@@ -1,69 +0,0 @@
-# Use Case: tauri-apps/tauri - The Tauri Framework
-
-**Repository**: https://github.com/tauri-apps/tauri
-**Stack**: Rust + TypeScript
-**Test Date**: 2025-12-08
-**Loctree Version**: 0.6.2-dev
-
----
-
-## Overview
-
-Testing loctree on THE Tauri framework itself - the ultimate test for Tauri command bridge analysis.
-
-## Repository Scale
-
-| Metric | Value |
-|--------|-------|
-| **Files Scanned** | 385 |
-| **Analysis Time** | 9.35 seconds |
-| **Throughput** | 41 files/sec |
-
-## Findings
-
-### Dead Code Detection
-- **High Confidence**: 0
-- **False Positive Rate**: 0%
-
-### Tauri Command Bridges
-```
-loct commands --missing # 157 (plugin architecture - expected)
-loct commands --unused # 9 (~22% - HTML usage not detected)
-```
-
-The "missing" commands are expected - Tauri's plugin system registers handlers dynamically.
-
-### Additional Findings
-- **Dead Parrots**: 44 (legitimate unused re-exports)
-- **Twins**: 532 duplicates (standard Rust patterns)
-
-## Commands Used
-
-```bash
-cd Tauri
-loct # Create snapshot
-loct dead --confidence high # Dead code analysis
-loct commands --missing # Missing FE→BE handlers
-loct commands --unused # Unused BE handlers
-```
-
-## Verdict
-
-**PERFECT** - 0% false positives. Tauri command tracking works flawlessly.
-
-## Key Insights
-
-1. **Command Bridge**: Perfect FE↔BE tracking
-2. **Plugin Awareness**: Understands dynamic registration
-3. **Production Ready**: Zero FP on framework itself
-
-## Special Feature: `loct commands`
-
-Loctree's Tauri-specific commands are validated on Tauri's own codebase:
-- Detects handler registration patterns
-- Tracks invoke() calls from frontend
-- Identifies orphaned handlers
-
----
-
-*Tested by M&K ⓒ 2025-2026 The Loctree Team*
diff --git a/docs/use-cases/22_vue.md b/docs/use-cases/22_vue.md
deleted file mode 100644
index 1c54182a..00000000
--- a/docs/use-cases/22_vue.md
+++ /dev/null
@@ -1,72 +0,0 @@
-# Use Case: vuejs/core - The Vue.js Framework
-
-**Repository**: https://github.com/vuejs/core
-**Stack**: TypeScript + Vue SFC
-**Test Date**: 2025-12-08
-**Loctree Version**: 0.6.2-dev
-
----
-
-## Overview
-
-Testing loctree on Vue.js core - validating Vue Single File Component (SFC) parsing.
-
-## Repository Scale
-
-| Metric | Value |
-|--------|-------|
-| **Files Scanned** | ~500 |
-| **Vue Files** | 11 |
-| **Analysis Time** | ~10 seconds |
-
-## Findings
-
-### Dead Code Detection
-- **High Confidence**: 0
-- **False Positive Rate**: 0%
-
-### Vue SFC Support
-- **11/11 Vue files parsed correctly**
-- Import extraction: Perfect
-- Component imports: Recognized
-- Type imports: Handled
-
-### Version History
-
-| Version | FP Rate | Status |
-|---------|---------|--------|
-| 0.5.16 | 86% | NO Vue SFC parser |
-| 0.5.17 | 100% | WORSE |
-| 0.6.1-dev | 0% | HUGE WIN |
-| 0.6.2-dev | 0% | MAINTAINED |
-
-## Commands Used
-
-```bash
-cd VueCore
-loct # Create snapshot
-loct dead --confidence high # Dead code analysis
-loct twins # Duplicate detection
-```
-
-## Verdict
-
-**EXCELLENT** - Vue SFC parsing is production-ready.
-
-## Key Insights
-
-1. **SFC Parsing**: `
+
+
+"#;
+
+ let analysis = analyze_js_file_ast(
+ content,
+ Path::new("src/Counter.svelte"),
+ Path::new("src"),
+ None,
+ None,
+ "Counter.svelte".to_string(),
+ &CommandDetectionConfig::default(),
+ );
+
+ assert!(
+ analysis
+ .exports
+ .iter()
+ .any(|e| e.name == "clicks" && e.kind == "rune_state")
+ );
+ assert!(
+ analysis
+ .exports
+ .iter()
+ .any(|e| e.name == "doubled" && e.kind == "rune_derived")
+ );
+ assert!(
+ analysis
+ .exports
+ .iter()
+ .any(|e| e.name == "title" && e.kind == "rune_props")
+ );
+ assert!(
+ analysis
+ .exports
+ .iter()
+ .any(|e| e.name == "count" && e.kind == "rune_props")
+ );
+ assert!(
+ analysis
+ .exports
+ .iter()
+ .any(|e| e.name == "label" && e.kind == "rune_bindable")
+ );
+ }
+
+ #[test]
+ fn test_svelte5_runes_in_svelte_ts_module_surface_as_exports() {
+ let content = r#"
+export const storeName = "counter";
+let count = $state(0);
+export function increment() {
+ count += 1;
+}
+"#;
+
+ let analysis = analyze_js_file_ast(
+ content,
+ Path::new("src/lib/store.svelte.ts"),
+ Path::new("src"),
+ None,
+ None,
+ "lib/store.svelte.ts".to_string(),
+ &CommandDetectionConfig::default(),
+ );
+
+ assert!(analysis.exports.iter().any(|e| e.name == "storeName"));
+ assert!(analysis.exports.iter().any(|e| e.name == "increment"));
+ assert!(
+ analysis
+ .exports
+ .iter()
+ .any(|e| e.name == "count" && e.kind == "rune_state")
+ );
+ }
+
+ #[test]
+ fn test_svelte5_script_module_and_snippet_exports() {
+ let content = r#"
+
+
+
+
+{#snippet item(label)}
+ {label}
+{/snippet}
+"#;
+
+ let analysis = analyze_js_file_ast(
+ content,
+ Path::new("src/routes/+page.svelte"),
+ Path::new("src"),
+ None,
+ None,
+ "routes/+page.svelte".to_string(),
+ &CommandDetectionConfig::default(),
+ );
+
+ assert!(analysis.exports.iter().any(|e| e.name == "prerender"));
+ assert!(
+ analysis
+ .exports
+ .iter()
+ .any(|e| e.name == "count" && e.kind == "rune_state")
+ );
+ assert!(analysis.exports.iter().any(|e| {
+ e.name == "item"
+ && e.kind == "snippet"
+ && e.export_type == "svelte_template"
+ && e.params.iter().any(|param| param.name == "label")
+ }));
+ }
+
#[test]
fn test_vue_file_full_analysis() {
let content = r#"
@@ -792,4 +1075,181 @@ export default defineComponent({
"MyComponent usage should be tracked"
);
}
+
+ #[test]
+ fn test_sfc_default_export_synthesized_for_svelte() {
+ // Svelte component without explicit `export default` — file IS the component.
+ // Synthetic default export should land with name = file_stem so
+ // `find(name="HeroSectionV2", mode="who-imports")` can resolve it.
+ let content = r#"
+
+
+
+"#;
+ let analysis = analyze_js_file_ast(
+ content,
+ Path::new("src/components/HeroSectionV2.svelte"),
+ Path::new("src"),
+ None,
+ None,
+ "components/HeroSectionV2.svelte".to_string(),
+ &CommandDetectionConfig::default(),
+ );
+
+ let default_match = analysis
+ .exports
+ .iter()
+ .find(|e| e.name == "HeroSectionV2" && e.kind == "default");
+ assert!(
+ default_match.is_some(),
+ "Svelte file should synthesize a default export named after its stem; got exports = {:?}",
+ analysis
+ .exports
+ .iter()
+ .map(|e| (&e.name, &e.kind))
+ .collect::>()
+ );
+ assert_eq!(default_match.unwrap().export_type, "sfc_component");
+ }
+
+ #[test]
+ fn test_sfc_default_export_synthesized_for_astro() {
+ let content = r#"---
+import Card from "../components/Card.astro";
+const title = "Hello";
+---
+
+"#;
+ let analysis = analyze_js_file_ast(
+ content,
+ Path::new("src/pages/HomePage.astro"),
+ Path::new("src"),
+ None,
+ None,
+ "pages/HomePage.astro".to_string(),
+ &CommandDetectionConfig::default(),
+ );
+
+ assert!(
+ analysis.exports.iter().any(|e| e.name == "HomePage"
+ && e.kind == "default"
+ && e.export_type == "sfc_component"),
+ "Astro file should synthesize a default export named after its stem; got exports = {:?}",
+ analysis
+ .exports
+ .iter()
+ .map(|e| (&e.name, &e.kind))
+ .collect::>()
+ );
+ }
+
+ #[test]
+ fn test_sfc_default_export_synthesized_for_vue() {
+ // Vue SFC without classic `export default` (e.g. `
+
+
+
{{ count }}
+
+"#;
+ let analysis = analyze_js_file_ast(
+ content,
+ Path::new("src/widgets/Counter.vue"),
+ Path::new("src"),
+ None,
+ None,
+ "widgets/Counter.vue".to_string(),
+ &CommandDetectionConfig::default(),
+ );
+
+ assert!(
+ analysis.exports.iter().any(|e| e.name == "Counter"
+ && e.kind == "default"
+ && e.export_type == "sfc_component"),
+ "Vue file should synthesize a default export named after its stem; got exports = {:?}",
+ analysis
+ .exports
+ .iter()
+ .map(|e| (&e.name, &e.kind))
+ .collect::>()
+ );
+ }
+
+ #[test]
+ fn test_sfc_synthetic_export_does_not_clobber_explicit() {
+ // Vue file already has `export default class HeroSection {}` from
+ // the AST visitor → ExportSymbol { name: "default", kind: "default" }.
+ // The synthetic helper pushes a DIFFERENT name (file stem), so both
+ // entries coexist. `name: "default"` is the JS-side default-import
+ // anchor; the file-stem entry is the symbol-search anchor.
+ let content = r#"
+
+"#;
+ let analysis = analyze_js_file_ast(
+ content,
+ Path::new("src/HeroSection.vue"),
+ Path::new("src"),
+ None,
+ None,
+ "HeroSection.vue".to_string(),
+ &CommandDetectionConfig::default(),
+ );
+
+ let default_anchor = analysis
+ .exports
+ .iter()
+ .filter(|e| e.name == "default" && e.kind == "default")
+ .count();
+ let stem_anchor = analysis
+ .exports
+ .iter()
+ .filter(|e| e.name == "HeroSection" && e.kind == "default")
+ .count();
+ assert_eq!(
+ default_anchor, 1,
+ "Original `name: \"default\"` export should remain untouched"
+ );
+ assert_eq!(
+ stem_anchor, 1,
+ "Synthetic stem-named export should be pushed exactly once"
+ );
+ }
+
+ #[test]
+ fn test_sfc_synthetic_export_not_emitted_for_rune_module() {
+ // `.svelte.ts` rune modules are TypeScript files using the svelte
+ // co-located convention — they are NOT component files. No synthetic
+ // default export should be added (the file stem would be
+ // "Counter.svelte" which would mis-resolve as a component name).
+ let content = r#"
+let count = $state(0);
+export function getCount() { return count; }
+"#;
+ let analysis = analyze_js_file_ast(
+ content,
+ Path::new("src/Counter.svelte.ts"),
+ Path::new("src"),
+ None,
+ None,
+ "Counter.svelte.ts".to_string(),
+ &CommandDetectionConfig::default(),
+ );
+
+ assert!(
+ !analysis
+ .exports
+ .iter()
+ .any(|e| e.export_type == "sfc_component"),
+ "Rune modules (.svelte.ts) must not get a synthetic sfc_component export"
+ );
+ }
}
diff --git a/loctree-rs/src/analyzer/ast_js/sfc.rs b/loctree-rs/src/analyzer/ast_js/sfc.rs
new file mode 100644
index 00000000..a191ed04
--- /dev/null
+++ b/loctree-rs/src/analyzer/ast_js/sfc.rs
@@ -0,0 +1,523 @@
+//! Single File Component (SFC) script and template extraction.
+//!
+//! This module handles extraction of script and template content from
+//! Svelte (.svelte), Vue (.vue), and Astro (.astro) Single File Components.
+//!
+//! 𝚅𝚒𝚋𝚎𝚌𝚛𝚊𝚏𝚝𝚎𝚍. with AI Agents ⓒ 2025-2026 Loctree Team
+
+use regex::Regex;
+
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub(super) enum RuneKind {
+ State,
+ Derived,
+ Props,
+ Bindable,
+ Effect,
+ Inspect,
+ Host,
+}
+
+impl RuneKind {
+ pub(super) fn export_kind(&self) -> &'static str {
+ match self {
+ Self::State => "rune_state",
+ Self::Derived => "rune_derived",
+ Self::Props => "rune_props",
+ Self::Bindable => "rune_bindable",
+ Self::Effect => "rune_effect",
+ Self::Inspect => "rune_inspect_debug",
+ Self::Host => "rune_host",
+ }
+ }
+}
+
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub(super) struct RuneDeclaration {
+ pub(super) name: String,
+ pub(super) kind: RuneKind,
+ pub(super) line: usize,
+}
+
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub(super) struct SnippetDeclaration {
+ pub(super) name: String,
+ pub(super) line: usize,
+ pub(super) params: Vec,
+}
+
+/// Extract script content from a Svelte file.
+///
+/// Handles both `"#).ok();
+
+ if let Some(re) = script_regex {
+ let mut scripts = Vec::new();
+ for caps in re.captures_iter(content) {
+ if let Some(script_content) = caps.get(1) {
+ scripts.push(script_content.as_str().to_string());
+ }
+ }
+ scripts.join("\n")
+ } else {
+ String::new()
+ }
+}
+
+fn find_astro_frontmatter_bounds(content: &str) -> Option<(usize, usize, usize)> {
+ let mut offset = 0;
+ let mut lines = content.split_inclusive('\n');
+ let first = lines.next()?;
+ if first.trim_end_matches(['\r', '\n']) != "---" {
+ return None;
+ }
+
+ let frontmatter_start = first.len();
+ offset += first.len();
+
+ for line in lines {
+ let trimmed = line.trim_end_matches(['\r', '\n']);
+ if trimmed == "---" {
+ return Some((frontmatter_start, offset, offset + line.len()));
+ }
+ offset += line.len();
+ }
+
+ None
+}
+
+fn extract_tag_blocks(content: &str, tag: &str) -> String {
+ let pattern = format!(r#"<{tag}[^>]*>([\s\S]*?){tag}>"#);
+ let Ok(re) = Regex::new(&pattern) else {
+ return String::new();
+ };
+
+ re.captures_iter(content)
+ .filter_map(|caps| caps.get(1).map(|m| m.as_str().to_string()))
+ .collect::>()
+ .join("\n")
+}
+
+/// Extract template content from a Svelte file (everything outside "#) {
+ result = script_re.replace_all(&result, "").to_string();
+ }
+ if let Ok(style_re) = Regex::new(r#""#) {
+ result = style_re.replace_all(&result, "").to_string();
+ }
+ result
+}
+
+/// Extract template content from a Vue file (everything inside tags).
+pub(super) fn extract_vue_template(content: &str) -> String {
+ let template_regex = Regex::new(r#"]*>([\s\S]*?)"#).ok();
+
+ if let Some(re) = template_regex {
+ let mut templates = Vec::new();
+ for caps in re.captures_iter(content) {
+ if let Some(template_content) = caps.get(1) {
+ templates.push(template_content.as_str().to_string());
+ }
+ }
+ templates.join("\n")
+ } else {
+ String::new()
+ }
+}
+
+pub(super) fn extract_svelte5_runes(script_content: &str) -> Vec {
+ let mut declarations = Vec::new();
+
+ if let Ok(re) = Regex::new(
+ r#"(?m)\b(?:export\s+)?(?:let|const|var)\s+([A-Za-z_$][\w$]*)\s*=\s*\$(state|derived|bindable)(?:\.(raw|snapshot|by))?\s*\("#,
+ ) {
+ for caps in re.captures_iter(script_content) {
+ let Some(name) = caps.get(1) else {
+ continue;
+ };
+ let Some(kind_match) = caps.get(2) else {
+ continue;
+ };
+ let kind = match kind_match.as_str() {
+ "state" => RuneKind::State,
+ "derived" => RuneKind::Derived,
+ "bindable" => RuneKind::Bindable,
+ _ => continue,
+ };
+ declarations.push(RuneDeclaration {
+ name: name.as_str().to_string(),
+ kind,
+ line: line_for_offset(script_content, name.start()),
+ });
+ }
+ }
+
+ if let Ok(re) = Regex::new(
+ r#"(?m)\b(?:export\s+)?(?:let|const|var)\s+([A-Za-z_$][\w$]*)\s*=\s*\$props(?:\.\w+)?\s*\("#,
+ ) {
+ for caps in re.captures_iter(script_content) {
+ if let Some(name) = caps.get(1) {
+ declarations.push(RuneDeclaration {
+ name: name.as_str().to_string(),
+ kind: RuneKind::Props,
+ line: line_for_offset(script_content, name.start()),
+ });
+ }
+ }
+ }
+
+ if let Ok(re) = Regex::new(
+ r#"(?m)\b(?:export\s+)?(?:let|const|var)\s*\{([^}]*)\}\s*=\s*\$props(?:\.\w+)?\s*\("#,
+ ) {
+ for caps in re.captures_iter(script_content) {
+ let Some(bindings) = caps.get(1) else {
+ continue;
+ };
+ let line = line_for_offset(script_content, bindings.start());
+ for name in extract_destructured_names(bindings.as_str()) {
+ declarations.push(RuneDeclaration {
+ name,
+ kind: RuneKind::Props,
+ line,
+ });
+ }
+ }
+ }
+
+ for (rune, kind) in [
+ ("effect", RuneKind::Effect),
+ ("inspect", RuneKind::Inspect),
+ ("host", RuneKind::Host),
+ ] {
+ let pattern = format!(r#"(?m)\${rune}(?:\.\w+)?\s*\("#);
+ let Ok(re) = Regex::new(&pattern) else {
+ continue;
+ };
+ for mat in re.find_iter(script_content) {
+ declarations.push(RuneDeclaration {
+ name: format!("${rune}"),
+ kind: kind.clone(),
+ line: line_for_offset(script_content, mat.start()),
+ });
+ }
+ }
+
+ declarations
+}
+
+pub(super) fn extract_svelte_snippets(template: &str) -> Vec {
+ let Ok(re) = Regex::new(r#"\{#snippet\s+([A-Za-z_$][\w$]*)\s*\(([^)]*)\)\}"#) else {
+ return Vec::new();
+ };
+
+ re.captures_iter(template)
+ .filter_map(|caps| {
+ let name = caps.get(1)?;
+ let params = caps
+ .get(2)
+ .map(|m| {
+ m.as_str()
+ .split(',')
+ .filter_map(|param| {
+ let name = param
+ .trim()
+ .split([':', '=', ' '])
+ .next()
+ .unwrap_or("")
+ .trim();
+ if name.is_empty() {
+ None
+ } else {
+ Some(name.to_string())
+ }
+ })
+ .collect()
+ })
+ .unwrap_or_default();
+
+ Some(SnippetDeclaration {
+ name: name.as_str().to_string(),
+ line: line_for_offset(template, name.start()),
+ params,
+ })
+ })
+ .collect()
+}
+
+fn extract_destructured_names(bindings: &str) -> Vec {
+ bindings
+ .split(',')
+ .filter_map(|part| {
+ let mut raw = part.trim();
+ if raw.is_empty() {
+ return None;
+ }
+ raw = raw.trim_start_matches("...");
+ let raw = raw.split('=').next().unwrap_or(raw).trim();
+ let name = raw.rsplit(':').next().unwrap_or(raw).trim();
+ let name = name.trim_start_matches("...");
+ if is_identifier(name) {
+ Some(name.to_string())
+ } else {
+ None
+ }
+ })
+ .collect()
+}
+
+fn is_identifier(name: &str) -> bool {
+ let mut chars = name.chars();
+ matches!(chars.next(), Some(c) if c.is_ascii_alphabetic() || c == '_' || c == '$')
+ && chars.all(|c| c.is_ascii_alphanumeric() || c == '_' || c == '$')
+}
+
+fn line_for_offset(content: &str, offset: usize) -> usize {
+ content[..offset].bytes().filter(|b| *b == b'\n').count() + 1
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn test_vue_script_extraction_basic() {
+ let vue_content = r#"
+
+
+
+