chore(deps): bump @vitest/mocker and vitest in /ui-v2 - #328
Open
dependabot[bot] wants to merge 539 commits into
Open
dependabot[bot] wants to merge 539 commits into
dependabot[bot] wants to merge 539 commits into
Conversation
Rebuild release binary and Docker image (freepeak/leankg:0.18.1 + :latest). Includes the HNSW path fix, MCP-decoupled lookup, INT8 fast path, and the LeanKG graph workflow fix landed since v0.18.0.
Keep MCP BACKGROUND embed off so HNSW is not dropped, ship offline INT8 embed profile/script, and warm Xenova cache before quantized ONNX. Co-authored-by: Cursor <cursoragent@cursor.com>
Add docker-up.sh and install.sh docker target so users can stand up LeanKG from Hub without Rust; document the flow in README/AGENTS. Co-authored-by: Cursor <cursoragent@cursor.com>
* feat(vector-engine): add Local/Cloud factory (FR-VE-ABS) Static enum dispatch over LocalEngine and CloudEngine selected via LEANKG_VECTOR_ENGINE, matching PRD §5.14 storage abstraction. * feat(vector-engine): add Tier-1 topology store (FR-VE-T1) Persist metadata and HNSW adjacency with Local RocksDB options (mmap off, Zstd, pin L0, BinaryAndHash) per PRD 5.14.1. * feat(vector-engine): add Tier-2 SQ8 RAM cache (FR-VE-T2) Keep INT8/SQ8 vectors fully in RAM for SIMD ANN with no disk I/O on the inner loop (PRD 5.14.1). * feat(vector-engine): add Tier-3 flat payload file (FR-VE-T3) Append-only FP32 + source payload binary store read once at post-filter after ANN (PRD 5.14.1). * feat(vector-engine): add runtime SIMD dispatch (FR-VE-RT-SIMD) Detect AVX-512/AVX2/NEON at runtime with scalar fallback so distance kernels never SIGILL on older CPUs. * feat(vector-engine): auto-tune RocksDB block cache (FR-VE-RT-MEM) Plan block cache from available RAM / 2GB Local survival cgroup so the engine stays under the PRD memory envelope. * feat(vector-engine): dynamic rayon pool sizing (FR-VE-RT-THREADS) Local leaves 2 cores free for OS/IDE; Cloud uses the full machine. * feat(vector-engine): HNSW selectNeighbors with M in 12-16 (FR-VE-HNSW) Heuristic neighbor selection with raised ef_construction defaults to protect recall at efSearch=50. * feat(vector-engine): dual-write Append-fsync-commit-RAM (FR-VE-FS-DW) Enforce safe write order: flat append, fsync, Tier-1 offsets, then SQ8 RAM update per PRD 5.14.3. * feat(vector-engine): crash recovery without dangling ptrs (FR-VE-FS-REC) Truncate uncommitted flat tails on open and assert Tier-1 offsets never point past the payload file. * feat(vector-engine): shadow-page GC when frag > 30% (FR-VE-FS-GC) Compact live records into a shadow flat file and swap offsets under a micro-lock so readers stay unblocked. * test(vector-engine): GC concurrency integrity (FR-VE-TEST-GC) Assert shadow compaction with concurrent readers keeps vector counts intact (FR-VE-TEST-GC). * test(vector-engine): factory env selects Local/Cloud (FR-VE-TEST-FACTORY) Assert EngineKind parse + VectorEngineFactory open for local and cloud. * test(vector-engine): SIMD differential abs error (FR-VE-TEST-SIMD) Require Neon/AVX2/AVX-512/scalar INT8 dots to agree within 1e-6. * test(vector-engine): dual-write crash simulation (FR-VE-TEST-DW) Simulate append-without-commit and assert recovery leaves no dangling Tier-1 offsets. * feat(vector-engine): ANN query P95 bench harness (FR-VE-BENCH-Q) Measure SQ8 in-RAM query P95; full 1M/<50ms gate runs via cargo bench. * feat(vector-engine): I/O reduction vs mmap metric (FR-VE-BENCH-IO) Hot SQ8 path touches zero disk pages; report >=80% reduction vs mmap full-scan baseline. * feat(vector-engine): SQ8 vs FP32 recall harness (FR-VE-BENCH-RECALL) Measure recall at efSearch=50 against FP32 brute-force (>90% target). * feat(vector-engine): 2GB cgroup OOM survival plan (FR-VE-BENCH-OOM) Auto-tune block cache under the Local 2GB survival cap so ANN warm must not OOM-kill. * feat(vector-engine): agent A/B floor hooks (FR-VE-BENCH-AB) Record PRD token/tool/speed floors and optional LEANKG_VE_AB_JSON ingestion for the release gate. * feat(vector-engine): LocalEngine default cutover gate (FR-VE-GATE) Smoke gate keeps ready_for_default=false until full-scale benches and A/B floors pass; Cozo HNSW remains shipped default. * docs: mark vector-engine FR-VE-* progress in task tracker Core storage/runtime/tests DONE; benches/gate/US/REL PARTIAL until full-scale 1M and live agent A/B prove the release floors. * test(vector-engine): full A/B unit suite and cargo bench Add deterministic ≥100-task LocalEngine vs grep/cat simulator with PRD floor checks, wire gate smoke to the suite, and register cargo bench --bench vector_engine_ab. * chore(docker): cap Local MCP at 2GB survival limit Align docker-compose.rocksdb and docker-up MCP with PRD LocalEngine 2GB envelope; keep offline embed on a higher mem_limit. * docs(docker): document Local MCP 2GB mem_limit Keep cold-embed guidance at ≥6g; MCP Local survival is 2g. * docs(docker): add --memory=2g to MCP-only example
* docs(prd): sync v3.7 vector-engine status to origin/main Reflect #79 merge on main (crate 0.19.0): FR-VE core/REL-044..047 DONE; gate, full-scale benches, and live A/B remain PARTIAL. * feat(vector-engine): prove FR-VE-BENCH-Q 1M ANN P95 under 50ms Add Sq8Nsw layer-0 search over in-RAM SQ8 and gate cargo bench/default corpus at 1M. Measured P95=0.065ms (Neon); mark FR-VE-BENCH-Q DONE. * feat(vector-engine): close FR-VE-BENCH-IO/RECALL/OOM gates Prove ≥80% modeled I/O cut vs mmap, SQ8 recall≥90% @ efSearch=50, and 1M corpus under 2GB (live RSS≈567MB). Mark REL-048 DONE. * feat(vector-engine): meet US-VE-01/02 idle RSS and TTC floors Add kpi helpers: warm SQ8 NSW RSS≈89MB (<150MB) and ANN+JSON time-to-context P95≈0.094ms (<100ms). Mark REL-050 DONE. * feat(vector-engine): close FR-VE-BENCH-AB with JSON artifact export In-process ≥100-task suite meets PRD floors; cargo bench writes target/vector_engine_ab_result.json for gate/live injection. * feat(vector-engine): flip FR-VE-GATE ready_for_default on full evidence evaluate_gate sets ready_for_default when LEANKG_VE_GATE_FULL=1 and all Q/IO/RECALL/OOM/AB floors pass; preferred_ann_backend returns local_engine. * test(vector-engine): cover P0 gate paths and record A/B results Add e2e suite, expand unit/bench coverage, reorder RSS KPI before 1M ANN, and sync PRD/tracker with measured gate evidence JSON. * fix(vector-engine): avoid i8 overflow in synth SQ8 patterning CI debug builds panicked on `% 254 as i8 - 127` when the modulo exceeded 127; compute the centered value in i32 before casting. * docs: polish README for clearer project landing page * fix: idle GC trim once per quiet period Stop re-trimming empty caches every 30s while idle; honor LEANKG_GC_POLL_SECS in the watchdog sleep and call trim_heap only after a real cache release. * docs: capture semantic MCP verification as PRD v3.7.1 backlog Record the live Docker MCP probe as GREEN evidence and add US-SEM/FR-SEM enhancements (token honesty, ontology budgets, HTTP resilience, live smoke) for a later sprint without displacing P1. * fix(vector-engine): gate idle RSS on warm delta for CI Absolute process RSS exceeds 150MB under Linux debug `cargo test --lib` (~161MB observed). Measure baseline/delta and assert delta_ok in unit/e2e; keep absolute check for lean bench processes. * docs: polish README to product landing style Restructure around CodeGraph-style get-started, agent badges, why/how, and measured A/B results while keeping LeanKG-accurate install paths. * docs(prd): sync tracker status to PR #80 tip Record open PR, CI hardening (i8 overflow + RSS delta_ok), measured KPI numbers, and awaiting-merge / next-P1 notes in PRD + task tracker. * docs(prd): clarify FR-VE-GATE coexistence on PR #80 Align status banners with open PR #80 (awaiting merge) without pinning a moving tip SHA; keep CI/RSS methodology notes.
…81) * docs(prd): elevate day-2 embed resume to P0 Resume-if-data / cold-if-empty for standalone and all Docker embed-on paths; FR-HNSW-E marked PARTIAL. * feat(embed): resume day-2 with HNSW no-op and hash-aware stale Skip HNSW drop/rebuild and model load when nothing is dirty; stamp fresh per batch for kill/resume; mark stale only when content_hash changes so full index does not force re-embed. * docs(prd): mark embed-resume FRs done after local smoke Sync tracker/PRD gate checklist to implementation evidence (unit, e2e, CLI cold→resume→reindex→resume). * feat(ops,sem): mega-graph 6g/3g/cpus6 + SEM path filter Drop embed/assets and gate benchmark paths in FilterPolicy; honor LEANKG_SKIP_FRESHNESS_CHECK; set compose cpus=6, mem_reservation=3g, MCP mem_limit=6g. Sync PRD/tracker and 3-workspace vector/semantic verification report. * fix(embed): clear Docker PID 1 stale embed.lock on spawn Same-PID leftover locks no longer block LEANKG_EMBED_BACKGROUND after container recreate; only an in-process active embed (or another live PID with status=running) skips spawn.
* feat(mcp): document semantic_search dual-path (FR-SURF-01) Align tools/list description with handler: HNSW+rerank when embeddings exist, else ontology-first safe_discover. Track FR-SURF-01 as DONE. * feat(mcp): add prefer-order schema hints (FR-SURF-02) Document search/semantic tool prefer-order on concept_search, semantic_search, search_code, kg_semantic_context, and kg_context. Sync AGENTS.md mega-graph guidance; mark US-SURF-01 / FR-SURF-02 DONE. * feat(mcp): remove superseded tools (FR-SURF-03) Drop mcp_hello, mcp_impact, and get_doc_for_file from the registry and handlers. Prefer get_impact_radius, find_related_docs, and status/self-test. Add redundant_tools_matrix coverage; mark US-SURF-02 / FR-SURF-03 DONE. * test: add coverage suites and surface analysis docs Land CLI parse coverage, embedding_state unit tests, MCP redundancy smoke suite, test-coverage status refresh, and competitive-analysis docs. * fix(clippy): drop map_identity in threads pool test Also sync instructions prefer-order with FR-SURF-02 search/semantic triples.
* docs: hybrid LSP Go/TS track (FR-LSP-A..D) + init --with-lsp Document prefab lsp bootstrap, typed_resolve indexer wiring, and update tracker session focus ahead of implementation. * feat(lsp): hybrid typed resolve for Go/TS (FR-LSP-A..D) Add in-process TypeRegistry + hybrid resolver, wire indexer to emit resolution_method=typed when typed_resolve=go,ts, and bootstrap prefab lsp servers via init --with-lsp / empty-yaml catalog fallback (REL-039). * feat(mcp): soft-deprecate wake_up and search_by_environment Mark FR-SURF-04/05 replacements in tool schemas, assert in redundancy matrix, and record REL-053 surface counts in a release note. * test(lsp): hybrid LSP e2e + mark FR-LSP/SURF tracker DONE Cover Go/TS typed edges, init --with-lsp prefab yaml, and update the task tracker statuses for the shipped P1/P2 items. * test(cli): cover init --with-lsp flag parsing Update Init match arms for the new with_lsp field and assert the flag is accepted by the CLI parser.
* fix(mcp): do not block search on ontology sync / mega embed Ontology sync at boot could hang for minutes on mega RocksDB and prevent mcp-http from binding (empty health/search). Time out sync by default, skip in-process background embed on mega-graphs unless explicitly forced, and count elements without all_elements(). * docs(agents): note ontology sync timeout and mega embed skip * docs(agents): restore LeanKG-first checklist wording
* feat(graph): US-GF-03 query_graph NL scoped subgraph Add MCP query_graph and CLI graph-query / query --kind subgraph: seed retrieval → BFS/path expand → token-budget trim with provenance labels on every edge (REL-042 / FR-GF-05 / FR-GF-06). * test(mcp): cover query_graph + fix agent_focus fixture Strengthen US-GF-03 MCP assertions (seeds, provenance, budget, empty question), create persona fixture so agent_focus/diary pass, register schema checks, and add scripts/mcp-smoke-tools.py with honest skip labels.
Add MCP embed_control (on/off/status) with idle-gated partial Incremental resume, cooperative cancel, and zero-dirty fast path. Classify all MCP tools in redundant_tools_matrix and document skills/rules removal impact.
* docs: P0 mega HNSW semantic_search OOM (US-SEM-06 / FR-SEM-07) * fix: keyed HNSW seed hydration without all_elements * fix: cheap has_any gate for kg_semantic_context Avoid list_all (~147k embedding_state rows) before HNSW retrieve on mega graphs. * docs: REL-054 mega semantic smoke evidence Mark US-SEM-06 / FR-SEM-07 / REL-054 DONE after keyed hydration Docker smoke.
* fix: mega-safe concept_search, query_graph, get_clusters Keyed code_refs and typed name fallback; frontier-local BFS; serve precomputed cluster_id on mega instead of live Louvain. * fix: mega query_graph latency + REL-055 smoke evidence Avoid unindexed name/edge full scans on mega graphs; close US-MG-TOOL-01 / FR-ONT-MEGA-01 / FR-GF-MEGA-01 / FR-CL-MEGA-01 / REL-055.
Non-strategic same-file Jaccard clone detection is unused by agents and refuses on mega-graphs; prefer semantic_search / concept_search instead.
* feat(ui): add LeanKG UI v2 graph shell (Phase 1) GitNexus-inspired explorer in ui-v2/ with LeanKG REST client, Force/Tree/Circles layouts, mega-graph skip, Vitest/Playwright parity, and screenshot report. * fix(ui-v2): viewport fit, visible types, root expand, screenshots Use Sigma animatedReset for camera fit, skip FA2 on Tree/Circles, show Property/Method by default, normalize expand root path, refresh README and screenshot report for PR #89. * feat(docker): run leankg serve beside MCP for UI v2 Option A: entrypoint starts REST :8080 in the background, then exec mcp-http as PID 1; compose and docker-up publish 8080 alongside 9699. * docs: set PRD version to 3.7.7-ui-v2 after main rebase * docs: show UI v2 screenshots in README Replace legacy graph.jpeg/obsidian shots with the Phase 1 Force/Tree/Circles/search/query/code captures from this PR.
Phase 1 left src/embed on legacy ui/. Bake ui-v2 into rust_embed and rebuild Docker/onrender images from ui-v2 so :8080 ships the new shell.
Canonical using-leankg skill; install.sh refreshes from it, uses Docker container project= default, and drops stale mcp_init/RTK hooks.
Double-click containers expands via expand-service and replaces the canvas; CodePanel skips /api/file for Service/Folder; clearer directory errors on the file API. PRD US-UI2-10 / FR-UI2-12 / REL-057.
Sigma mounted once with kg=null callbacks; use refs so Service/Folder double-click replaces the graph. Refresh src/embed + Dockerfile/render.yaml for onrender UI v2 bake with npm layer cache and health check.
Graph rows can reference relative paths that only exist on a sibling Docker mount; probe those roots, return 404 (not opaque 400), and surface API error bodies in the UI client.
Entrypoint started serve under LEANKG_MCP_PROJECT, and project switch could label /workspace while still serving a sibling RocksDB. Add --project/LEANKG_SERVE_PROJECT, atomic switch, skip auto-reindex, and drop expand ghosts missing on the active root.
Prevents expanding a sibling RocksDB while status still says /workspace. Document RCA for Workspace dblclick → freepeak/multi-repo graph.
* feat: procedural ontology auto-update while serving Watch ontology YAML during MCP/serve, fix boot marker for workflows.yaml, refresh after index, and add ontology_control for sync/status. * fix: replace ontology layer on sync to avoid GID duplicates Cozo :put keys the full code_elements tuple, so YAML renames left duplicate steps. Clear ontology:// rows then batch-insert; serialize sync and retry on SQLite locks. * docs: document procedural ontology auto-update and live correction
Default expand page 500 with Load more (+200) merge; fix hasMore on root all_content; hierarchical Folders & files session tree that survives Overview back and grows after load-more.
…s, identity/perf/data-quality waves (#247) * chore(hackathon): R0 setup log + baseline gates green * test(hackathon): R1 full MCP tool live sweep vs remote PG * fix(mcp): update_knowledge upserts knowledge_entries on id update_knowledge re-puts an existing row through create_knowledge_entry's :put; the PG translator had no pk_for_table entry for knowledge_entries, so it emitted a plain INSERT that died on the knowledge_entries_id_uniq unique index (-32603 'Failed to update knowledge entry: db error', R1 sweep repro 2/2). Register id as the table's PK so the put becomes an ON CONFLICT (id) DO UPDATE upsert. * fix(mcp): mcp_index_docs yields to watchdog + extended bulk-index budget R1 sweep: mcp_index_docs returned 'timed out after 30s' even for a 1-file docs dir while the op completed after the deadline. Two causes: 1. The doc walk/parse/ref-resolve pipeline (~75 sequential DB round- trips for one markdown file) ran synchronously inside the polled future. tokio::time::timeout can only fire between polls, so the watchdog surfaced only AFTER all work drained - response lost and the hot executor thread blocked throughout. Run the pipeline via spawn_blocking so the future yields and deadlines preempt promptly. 2. Budget mismatch: at remote-PG latency (~2s/query) that pipeline is minutes of legitimate work (R1: ~15s/file average). Give mcp_index /mcp_index_docs an extended watchdog floor of 300s; interactive tools keep 30s and an explicit LEANKG_MCP_TOOL_TIMEOUT_SECS above the floor still wins. * fix(mcp): canonical project keys + exports anchored to active project root R1 sweep issues #4/#5: Project identity (issue #5): CLI 'index ./src' keyed the PG schema on the literal string './src' while 'mcp-http --project <abs>' hashed the real path - the server served an EMPTY DB right after a successful index. All project-key derivation now flows through one canonicalization helper (canonical_project_root): existing paths are fs::canonicalize'd so relative/absolute spellings, trailing slashes, . / .. components and symlinks collapse to one physical directory; non-existent paths fall back to lexical normalization, preserving the cross-mount project_path contract in leankg.yaml. A relative project_path now resolves against its own project root, so the documented './src' workaround keys identically from CLI and MCP. Export escape (issue #4): export_graph_snapshot, export_html, get_graph_report and the post-index GRAPH_REPORT auto-write resolved default/relative out paths against LEANKG_MCP_PROJECT or the server process CWD, writing artifacts into a PARENT repo's .leankg/. They are now anchored at the request's active project root derived from the handler's db_path. * fix(mcp): derive project schema keys via base-aware pure helper Follow-up to ea74cd8: the relative-vs-absolute schema test mutated the process CWD, racing pg_url_prefers_env_then_yaml_then_default (another test that chdirs for its own yaml lookup) under parallel test threads. Split canonical_project_root/schema_for_path into pure *_in variants taking an explicit base; the CWD-reading wrappers stay thin. Tests now exercise relative spellings without touching global state. * fix(engine): keep dynamic ontology rows visible across identity drift BUG-B (R1 sweep issue #2): delete_ontology_concept failed with "Element not found" and kg_ontology_status reported dynamic_concepts:0 after a server restart, yet the rows were still in Postgres. Root cause was scoping, not durability: project->PG-schema identity keyed a RELATIVE project_path literally (hex("./src") = leankg_p_2e2f737263), so any boot that resolved the field differently served an empty schema. - schema_candidates_for_path(): resolve relative project_path against the project root and canonicalize both spellings; expose ordered candidates [preferred, legacy literal key] so init adopts a populated legacy schema instead of silently serving an empty project (pick_schema_for_init). - read_only_url(): fix malformed query separator that corrupted URLs with an existing ?sslmode=... param - readonly connections against verified- TLS remote Postgres never connected (E3D000 bogus database name). - Regression tests: cross-instance dynamic concept roundtrip (add -> NEW engine -> lookup by gid -> delete), yaml sync-cycle preservation of source:dynamic rows, identity stability across spellings, legacy candidate shape, live R1-schema gid probe. * fix(engine): batch hang-trio N+1 queries into single round-trips BUG-D (R1 sweep issue #7): get_context hung 150s+ on remote Postgres. Measured pre-fix on the R1 corpus: get_context(./src/mcp/tools.rs) took 72.4s - one ~500ms find_element() round-trip per relationship edge. - get_context_for_file: collect all relationship targets and hydrate them with ONE batched lookup instead of a per-edge query. - get_elements_by_qualified_names: one IN-list query per 500-GID chunk instead of one query per GID; also dedups input. This helper underpins delete_ontology_concept, retrieval seeding, and HNSW hydration. Live probes vs the R1 schema (13,389 elements / 92,030 relationships): get_context 72.4s -> 2.1s; temporal_query 4.5-6.2s (single scan, was compounding under load); check_consistency ~7s. Regression tests assert <10s/<15s budgets and correct results. * fix(engine): agent_focus targeted queries + bounded pool wait BUG-E (R1 sweep issue #1/#9, most critical): with a persona fixture present, agent_focus loaded the ENTIRE graph (all_elements + all_relationships, ~13k rows / ~92k rows per call on the R1 corpus), blew past the 30s tool watchdog, and wedged every subsequent tool until server restart. Blocking work runs under block_in_place and cannot be cancelled by the watchdog, so each poisoned call kept running while holding pooled Postgres connections; once all slots were held, ClientPool::checkout blocked forever on its Condvar and every later tool starved into "timed out after 30s". - GraphEngine::agent_focus: persona filters (element_types / cluster_id / path prefixes) now run inside ONE database query (bound IN-list / equality / anchored-regex clauses); relationships are fetched via one indexed query per 500-GID chunk of the focused set. Same output as before (338 elements / 504 relationships on the R1 fixture), latency 5.8s -> ~3.4s cold and O(1..#chunks) queries instead of two full scans. - ClientPool::checkout: bounded wait (LEANKG_PG_POOL_WAIT_MS, default 10s) - pool starvation now fails fast with a clear error instead of blocking forever, so no single tool can wedge the executor. - Regression tests: agent_focus <5s on the live R1 corpus; focus -> immediate follow-up reads complete normally (<15s for keyed lookup + get_context + check_consistency sequence). * docs(hackathon): R2 log * feat(cli): add leankg connect for one-command MCP client setup * docs(hackathon): cycle-01 report — sweep, 7 fixes, connect feature * feat(audit): append-only hash-chained audit log (FR-ENT-1) Ledger of every MCP tool call and mutating REST call: actor, agent_client, tool, project, args_hash (never raw args), result_status, ts — tamper-evident via SHA-256 chain (prev_hash -> entry_hash, genesis 0x64). - migration 006_audit_log: table + ts/tool indexes + BEFORE UPDATE OR DELETE trigger raising 'audit_log is append-only' - src/audit/mod.rs: AuditRecord/AuditEntry, canonical-JSON chain math with independently verified golden vectors, verify_chain naming the broken seq, JSONL export/import; AuditRecorder = bounded mpsc (1024) + batcher flushing ~100ms/50 rows via ONE multi-row INSERT; fire-and-forget, overflow drops+counts with tracing::warn; missing table disables after one warn - hooks: single MCP choke point execute_tool_audited (rmcp call_tool + raw JSON-RPC arm; agent_client from clientInfo else transport tag), Axum middleware for POST/PUT/PATCH/DELETE /api/* recording route patterns; recorder attached in stdio/mcp-http/web server states and CLI audit commands - CLI: leankg audit export --since --until --format jsonl --out FILE, leankg audit verify [--since --until] (RFC3339 | epoch | relative) - backend: ledger read/write on DbBackend trait (PG multi-row INSERT + windowed reads); readonly opener pins the project ledger schema even while its code index is still empty TDD: unit tests for chain math/tamper evidence/drop counting/overhead (<2ms per call); live-PG suite covers migration, 100-event persistence, append-only enforcement, export round-trip, cross-batch continuity, tamper detection naming the sequence id. * ci(npm): enforce npm/crate version parity * chore(npm): sync wrapper to v0.26.0 * test(quickstart): <5min first-query smoke + CI weekly gate * feat(export): git-committable markdown graph docs (--markdown) * docs(hackathon): session handoff — resume queue, branch map, rules * docs(hackathon): refresh handoff — H11 merged, H9 sole open item * feat(cli): doctor --deep self-diagnosis suite (H9) * docs(hackathon): R3 log — six features landed * test(hackathon): cycle-2 live re-sweep vs remote PG * fix(identity): preserve leankg.yaml user fields across index Cycle-2 R2a sweep finding N1: every leankg.yaml writer serialized a freshly generated ProjectConfig over the existing file, and ProjectSettings.project_path carried #[serde(skip_serializing)] so even a fresh init never emitted the schema identity anchor. The next server boot then resolved a different PG schema and served an empty DB (database_exists: false) while Postgres held the indexed rows. - serialize project_path when set (skip only when None) - merge generated configs UNDER existing files (serde_yaml Value read-modify-write): existing keys win, missing keys are filled, unmodeled custom keys survive; applies to leankg init, the mcp_init tool, and the setup pipeline (fill-missing instead of skip-if-exists) - index-init self-heal: refill a MISSING anchor with the canonical index target before deriving the schema * fix(identity): legacy schema adopted only when preferred empty Cycle-2 R2a sweep finding N2: pick_schema_for_init adopted any existing legacy candidate unconditionally, so a stale 13k-row legacy schema pinned over a freshly indexed preferred schema (relative project_path spellings produce both candidates). - extract the decision into a pure 4-input predicate: adopt legacy ONLY when the preferred schema is missing or has no code_elements rows AND the legacy candidate is populated - replace the misnamed schema_exists (which actually probed rows) with a precise SchemaState {exists, populated} probe; zero extra probes on the populated-preferred fast path - prefer the .leankg/leankg.yaml store over the stale root-level leankg.yaml duplicate when the two anchors diverge, and cover the launcher-CWD identity invariants with pure regression tests * fix(identity): canonicalize --project before schema derivation Cycle-2 R2a sweep finding N3: mcp-http passed the raw --project value down, and relative spellings plus yaml project_path/root joins were resolved against the launcher's CWD further down — the byte-identical relaunch from a different directory pinned an unrelated populated PG schema. - canonicalize --project (and the find_project_root fallback) via canonical_project_root at the mcp-http entrypoint, before any schema derivation - canonicalize MCPServer::resolve_project_root's result so relative values inside leankg.yaml cannot re-key identity per launch - add tests/regression_identity_cluster.rs: live-PG regression driving leankg index twice across a yaml-anchor corruption window, asserting user fields survive and a fresh init_db reopens the same schema * perf(engine): batch consistency/temporal graph scans Root cause of the R2 hang trio (check_consistency >150s, temporal_query >120s, agent_focus >60s on the 93k-edge corpus; ~6s empty) was not the graph engine — engine-level scans already finish in ~5s. The wedge was the response path: TokenBudget::truncate_value cloned and re-serialized the whole array once per popped item (O(n^2)), burning a tokio worker for minutes on 24k findings / 93k relationships with no await point, so timers and sibling requests starved (N4 cascade). - token_budget: single-pass prefix-sum truncation for arrays and running-size key removal for objects (O(n^2) -> O(n)); primary payload keys (findings/relationships/elements) survive truncation. - agent_focus: relationship chunk fetch 500 -> 10k QNs per IN-list query (~27 sequential round trips -> 1-2 on a 13k-element focus). - server: 120s watchdog floor for full-graph scan tools (check_consistency/temporal_query/timeline/find_tunnels/agent_focus/ get_impact_radius/query_graph/shortest_path); their old 30s expiry never released the pooled connection (sync scan continues inside block_in_place), it only discarded the finished response. tests/perf_c2.rs pins wall-clock budgets through the handler-shaped path (engine scan + TokenBudget::apply): corpus consistency <15s, temporal <15s, agent_focus <30s; live before/after in the R2b report. * fix(pool): recover slots after watchdog expiry Regression coverage for the R2 N4 starvation path: when a slow query holds every pool slot, concurrent checkout must fail fast (bounded by LEANKG_PG_POOL_WAIT_MS, with a clear error) and slots must come back promptly once the holder drains or its future is cancelled at an await point — exactly what tokio::time::timeout does when a tool watchdog expires between PG calls. No pool-code change required: PooledClient RAII already releases on drop; the observed wedge was CPU starvation from the response-path O(n^2) truncation plus premature 30s expiry on graph-scan tools, fixed in the preceding commit. These tests lock the recovery guarantees: - fail-fast under full occupancy (< POOL_WAIT + slack), instant recovery after release (~3us measured) - cancelled holder returns its slot within 2s * fix(indexer): eliminate dangling edges and duplicate file rows at generation doctor --deep on the hackathon corpus flagged 432/1000 sampled edges referencing missing elements. Classification of all 24,431 orphans: - calls (23,340): unresolved bare-name targets persisted after inline resolution failed (std/minified-bundle callees). resolve_call_edges_inline now drops edges it knows are unresolvable instead of storing them. - emits/listens_on (230): bare receiver identifiers as sources and synthetic event::<name> targets that were never written as elements. Channel edges are now anchored on the containing file element and every distinct event gets a synthetic event element with a URI file_path. - extends (31): __unresolved__ minified-JS class targets, plus imports/ contains/explained_by/tested_by stragglers. A full-index safety valve (prune_dangling_relationships) drops any edge whose endpoints are absent from the element set; service_calls is exempt. - file rows (6 dup QNs): sql/swift/objc/sfc extractors emit a lowercase "file" node AND the physical pass emits an uppercase "File" row for the same path; summary synthesis enriched only the first and silently kept the second. Extra rows are now collapsed in phase 2. Unit tests cover each generator fix. * fix(doc_indexer): unique heading QNs and resolvable docs hierarchy doctor --deep flagged 10 duplicated qualified_names topped by docs/analysis/perf-memory-cpu-issues.md::Fix x8: every repeated markdown heading in a document produced an identical {doc}::{heading} section QN. Section QNs now get an occurrence counter per document (#2, #3, ...), keeping the first occurrence canonical for key stability. The dir -> document contains edges sourced raw filesystem paths that were never written as elements (207 orphans). Directory elements are now synthesized per ancestor under docs_root, and edge targets use the document graph QN (docs/<rel>) instead of the raw child path. Repeated index_docs runs also left stale section elements and their relationships behind (the x5 duplicates). Delete-before-insert now sweeps stale relationships by endpoint (new GraphEngine:: remove_relationships_by_endpoint_bulk covers documented_by, whose doc QN is the target), and directory rows join the element deletion keys. The mcp_index_docs wire contract still counts real documents only. * test: live-PG data-quality regression for fresh index Indexes a fixture (two md files with repeated headings + one ts file with event channels and an unresolvable call) against a scratch PG schema, runs the docs phase twice to exercise re-index idempotency, then asserts zero duplicate qualified_names and zero orphaned relationships across the whole graph. Skipped when LEANKG_PG_URL is unset or unreachable. * docs(hackathon): cycle-2 log — re-sweep green, identity/perf/data-quality waves * chore(npm): sync wrapper to v0.26.1
…bels, tool consolidation (#249) * docs(hackathon): open cycle 3 * feat(mcp): stable tool contract doc + CI drift guard (PLG-5) * docs(readme): quickstart reflects one-command connect + timed smoke * feat(graph): single confidence_label helper (ENT-9) Extract Relationship::derive_confidence_label into graph::provenance::confidence_label_for so every serializer derives identical EXTRACTED/INFERRED/AMBIGUOUS labels from raw confidence + resolver metadata. Adds element synthetic/ontology provenance helpers. * feat(graph): confidence_label on all graph responses (ENT-9) Thread the provenance label into every remaining edge serializer: get_dependencies (DependencyInfo + l1 cache), get_dependents, get_review_context relationships, and find_tunnels (Tunnel). Element rows in impact/review responses carry synthetic:true when derivable (synthetic/summary/event types, ontology:// and event:// paths). Contract test tests/provenance_labels.rs asserts every edge object in graph-returning tool output carries a valid label against a live-PG scratch fixture. * docs(hackathon): c3 batches 1-2 log * chore(mcp): deprecate 4 consolidation candidates * refactor(mcp): consolidate tool surface 76->73 (H6) * docs(hackathon): c3 h6 log
…RE-6) (#251) * feat(cli): usage dashboard from context_metrics (PLG-8) * docs(hackathon): c4 h10 log * test(perf): deterministic perf regression gate + CI workflow (CORE-6) scripts/perf_gate.sh compare/update modes; scripts/run_perf_workload.sh median-of-3 collector; gen_perf_fixture.py deterministic 20-module rust fixture; perf-gate.yml CI (pg16+pgvector service); baseline from live remote-PG run: index 18315ms, boot 19ms, search_code 13ms. * bench: record initial baseline * docs(hackathon): c4 h8 log
* docs(plan): adopt SQL-first datalog removal plan (W8) * feat(db): SQL-first seam adoption (W8 P0) * refactor(keys,content-hash): convert to parameterized SQL (W8 wave 1) * docs(hackathon): c5 w8-p0+wave1a log
…s-only naming) (#246) * refactor: purge residual legacy-engine and vendor references (Postgres-only naming) - rename internal identifiers: cozo_to_pg→datavalue_to_sql, unescape_cozo_string→unescape_datalog_string_literal, convert_cozo_vec_literals→convert_legacy_json_array_literals, strip_cozo_vec_literals→strip_legacy_vec_literals, tracing field cozo→script - rewrite comments/docstrings/tool descriptions/UI labels to PostgreSQL + pgvector-present phrasing across src, tests, docs, configs - remove dead LEANKG_COZO_ROCKS_BULK no-op check in embeddings/build.rs - update ui-v2 QueryFAB title to 'Raw graph query' (+ test expectations) - add tests/no_legacy_terms_test.rs guard: zero legacy terms outside allowlisted historical records (531 violations fixed to 0) No logic changes: mechanical diff audit proves every changed line is a comment, string literal, approved identifier rename, or the documented dead-code removal. 1043 lib tests + clippy CI gate + fmt green; live MCP tool matrix against remote Postgres matches pre-change baseline profile. * test(removal): fix embeddings-gated suites for remote PG + env-var robustness Follow-up to the CozoDB removal waves: make the full --features embeddings matrix pass against managed remote Postgres (WAN RTT, tight connection caps) without losing local-latency guarantees. Test infra fixes: - batch_delete_stress: 1M-edge variant skips on remote LEANKG_PG_URL (budget is local-calibrated); 10k resolve-time assertion is opt-in via LEANKG_TEST_RESOLVE_SECS so matrix contention can't flake it - overview_mega_tests: chunked batch seed (15k single inserts were WAN-bound minutes) + LEANKG_TEST_OVERVIEW_SECS budget override - concurrent_mcp_during_embed: >=1 RO success per kind during worker hold (>=2 assumed local-latency round trips) - full_index_wipe_test: unique scratch db_path per engine (fixed path shared one schema across tests -> cross-test row bleed); restore caller's LEANKG_PG_URL instead of removing (later tests fell back to dead localhost default); drop leaked admin connections (role cap E53300) - multi_model_smoke_live: gate behind LEANKG_MULTI_MODEL_LIVE=1 so a bare LEANKG_PG_URL can't silently aim live embeds at shared PG; BuildOptions initializer updated for summary-primary fields Stale assertions updated for current behavior: - lib.rs: 'c' resolves via registry grammars now (was asserted None) - mcp/tools.rs tool-count test: 76 base / 79 with embeddings feature - retrieval::pipeline: merged 4 resolve_ef tests into one sequential test (they raced each other's set/remove of LEANKG_HNSW_EF) - pg_regression_tools: add missing deterministic vector_for helper + quote embedded_at epoch (TEXT column) - embed_doc_inventory: trigger deferred inventory refresh after direct index_file_sync call
* fix: index .tsx/.jsx files and route them to the TSX grammar .tsx/.jsx files were silently producing zero extracted elements in every recent release, despite commit 2d47635 ("index *.tsx/*.jsx files") having fixed this once before. Root-caused via a Postgres- backed multi-project setup where .ts files in the same directory tree indexed correctly (confirmed via direct DB inspection: 0 rows for any .tsx file vs. hundreds of correct rows for sibling .ts files) while .tsx never produced a single element, for any project, regardless of project config, project_path, or cache state. Two independent regressions combined to fully break this: 1. `find_files_sync`'s extension whitelist in src/indexer/mod.rs (the walker `mcp_index` actually calls) dropped "tsx"/"jsx" in commit 6210ef0 (PR #40, unrelated web UI/UX rework, 2026-04-12, 3 days after 2d47635 added them). Several other extensions removed in that same commit were restored later; tsx/jsx were not, so affected files were never even discovered by the walker. 2. Even once discovered, src/indexer/lang/registry.rs's LanguageSpec table never had a dedicated tsx/jsx entry — only "typescript" (extensions: ts/mts/cts) existed, using tree_sitter_typescript::LANGUAGE_TYPESCRIPT, which cannot parse JSX syntax. tree_sitter_typescript::LANGUAGE_TSX (the JSX-aware grammar variant, bundled in the same crate) was never referenced anywhere in the codebase. Fix: - Add "tsx"/"jsx" back to the find_files_sync extension list. - Add a new "tsx" LanguageSpec entry (extensions: tsx/jsx) using LANGUAGE_TSX, so get_language()/get_parser_for_language() route these files to a grammar that actually understands JSX. Verified against a real-world Next.js App Router codebase: indexed file count went from 166 to 261 (the missing .tsx/.jsx files), producing 178 correctly extracted elements (functions, classes, methods) from .tsx files that previously yielded zero, across every release tested (v0.19.33 through v0.24.0). * test(indexer): regression tests for tsx/jsx routing + JSX parse Adds the test coverage PR #237 lacked: - tsx_and_jsx_route_to_tsx_spec: .tsx/.jsx resolve to the tsx spec, plain .ts still routes to typescript. - tsx_grammar_parses_jsx_without_errors: the LANGUAGE_TSX grammar parses JSX with no error nodes (LANGUAGE_TYPESCRIPT could not). Full lib suite: 1216 passed, 0 failed. * docs: tracker reflects post-#246 reality (W8 in-progress, W12 done, v2 roadmap pointer) - W8: P0/P1 + wave-1a/1b + PR #246 merged; 223 run_script sites remain. - W12: npm wrapper already at 0.26.1; release.yml publish-npm job syncs on tag. - Companion docs: point at roadmap-2027-v2.md (operational) + the SQL-migration plan doc (now on main, not a worktree branch). * feat(w8): wave-2 SQL-first code_elements reads with typed backend seam W8 wave-2 converts three element-lookup reads in graph/query.rs (find_element, find_element_by_name, get_elements_by_qualified_names) from Datalog run_script to a typed backend seam. The trait now owns find_element_by_key / find_element_by_name_col / elements_by_qualified_names with PostgresBackend impls; the engine calls those directly. FakeBackend gains matching in-memory parity so the unit-test surface (which uses init_db() under cfg(test)) stays green. Live-PG parity covered by tests/pg_sql_wave2_test.rs (#[ignore]-gated, runs against LEANKG_PG_URL). Unit tests: 1216 pass / 0 fail. * docs: W8 wave-2 landed + FR-HEA-01..05 track opened - prd.md: §3.31 (US-HEA) + §5.36 (FR-HEA-01..05) added; version bumped to 3.8.7-harness-era-positioning - prd-task-tracker.md: P1 Harness-era repositioning track (FR-HEA-01..05, US-HEA-01..05, all NOT_DONE) - roadmap-2027-v2.md: punch list rows 13-14 (FR-HEA-01 alias metric, FR-HEA-02 fallback hint); §4.1/§4.3 harness-era repositioning bullet - roadmap-tracker.md: W14 (Harness-era live-probe fixes) added as PENDING/hackathon owner Cross-references the 2026-08-30 live-probe assessment; total tracked 546 → 560. * feat(mcp): streamable-HTTP SSE envelope + Mcp-Session-Id on initialize POST /mcp responses now wrap the JSON-RPC payload in a single 'event: message' SSE frame (text/event-stream + cache-control: no-cache) so streamable-HTTP clients honoring 'Accept: application/json, text/event-stream' get a spec-shaped response either way. initialize additionally allocates a Mcp-Session-Id (UUIDv4) per the MCP streamable-HTTP spec; the server remains stateless across requests, so follow-ups accept any session id (including none) — issuing one is the minimum needed to stop clients from tearing the transport down on first reconnect. Live-verified handshake: initialize -> 200 + session id + SSE frame; notifications/initialized -> 204; tools/call (mcp_status) with echoed session id -> 200 + SSE frame, no session-id header on non-initialize. * fix(ontology): backfill workflow_step aliases + apply YAML step aliases (FR-HEA-01) get_ontology_status.nodes_missing_aliases counted every YAML-loaded workflow_step as missing an alias: WorkflowStepMetadata::new seeded `aliases: vec![]` (unlike WorkflowMetadata::new / FailureModeNode::new, which seed normalize_alias(name)), and the YAML loader parsed WorkflowStepDef.aliases but never applied it. - WorkflowStepMetadata::new now takes `name` and seeds the name-derived alias (parity with the other two node kinds) - New WorkflowStepMetadata::with_aliases / WorkflowStepNode::with_aliases builders - loader.rs applies YAML step aliases via .with_aliases before the rest of the chain - handler.rs dynamic path forwards step_name (drops manual re-assignment) Live probe on leankg mcp-http (:9699): nodes_missing_aliases 57 -> 0 (workflow_steps 57 -> 0). Unit + integration tests green: 1216 lib / 12 r2. --------- Co-authored-by: Daniel Buona <danielbuona@gmail.com>
…MA-01..06), FR-SM-04/05 re-grounded (#261)
* chore: gitignore local secret files, certs/, tooling state; add gitleaks config * docs: move 66 historical docs to docs/archive/, single SoT = prd.md + tracker * refactor: load CA bundles via rustls-pki-types (pem_file_iter), hermetic TLS tests; bump notify to 8 * chore: untrack certs/ (local Aiven CA bundle stays on disk, now gitignored) * docs: prd v4.1.1 — OMP memory-backend audit (roots/list cwd channel, mnemopi contract) + zvec-grep embedding-correctness audit (FR-ZCP-11)
… contract (#267) * docs: prd v4.3.0 — one-tool degradation ladder (FR-ZCP-03 rewrite), first-run setup contract (FR-ZCP-13), FR-ZCP-05 bridge tier; v4.2.0 measured-simplicity contract (FR-ZCP-12) * docs: tracker sync — implementation sprint FR-ZCP-01/02, 03, 05-bridge, 12-T1, 13 DONE (35 open) * docs: restore mcp-tool-contract.md (drift-guard diff target lost in docs/archive cutover) * docs(tracker): add FR-ZCP-05/12 tier-remainder live rows; reconcile counts to 36 open (9 live) * docs(tracker): DONE count 7→9 (6 sprint + 3 prior rows); footer tally clarified
…project-less URLs, register-cwd scope (#269) Expand section 3.4 from a stub into the full contract: - per-target config writers table (claude/cursor/codex/gemini exist; opencode/omp are the new writers) with exact file paths and entry shapes - URL contract: no ?project= by default (FR-ZCP-01 clauses 1-2); --project escape hatch; Docker is the single documented exception - --register-cwd = session-start hook running 'leankg add <cwd>' (FR-ZCP-13); persistent cwd->project table stays FR-ZCP-01 clause 3 - zero dead ends, env inventory table (FR-ZCP-12 T1), byte-identical config-block snapshot tests, --remove, idempotency - tracker FR-ZCP-04 row gains the matching scope note
… in-review (PR #268), not landed (#270) The initial §3.4 expansion cited 87e1828 (roots/list) and b251046 (leankg add) as 'landed', but both are on the v4.3.0 sprint branch, not main. Reworded to 'in review on PR #268' so main's PRD makes no claim about behavior main's code does not have (§3.4's own zero-unverifiable-claims AC).
The '116 names: 88 runtime + 28 script-only + 1 docs-only' parenthetical summed to 117 and matched no honest derivation of main's actual inventory (src literals: 94 unique; scripts-only: 32; union: 185). The sentence already makes the generated, CI-pinned table the source of truth, so the manual figure beside it was drift bait — removed per §3.4's own zero-unverifiable-claims AC.
…3.x router (#268) * feat(mcp): server-initiated roots/list for HTTP project resolution (FR-ZCP-01 clause 2) HTTP MCP clients that advertise the roots capability now answer a server-to-client roots/list request at initialize; the first file:// root becomes the connection's working directory for DB routing. - new src/mcp/roots.rs: wire-shaped roots/list request builder, file:// URI parsing (non-file schemes and remote hosts rejected), response payload parsing (first usable root wins), and a SessionRootCache keyed by Mcp-Session-Id (pending -> answered lifecycle, settle expiry, listChanged invalidation) - the probe rides the initialize SSE response as a second event: message frame; the client answers with an ordinary POST /mcp echoing the session id, so no bidirectional channel is required - resolution order per request: session root (roots/list) first, then the legacy ?project= query param, then the existing FS walk fallback - notifications/roots/list_changed invalidates the cached root for clients that declared roots.listChanged; others cache for the connection lifetime - clients without the roots capability (OMP sends capabilities: {}) are never probed and resolution is unchanged (graceful degradation) * feat: first-run setup contract + leankg add command (FR-ZCP-13) - src/setup_config.rs: typed read/write of <project>/.leankg/config.json {setup: auto|manual, embed: bool}; missing file = NotConfigured, corrupt file degrades to default (never errors the flow); pure resolve_setup_mode precedence: flag > LEANKG_SETUP_MODE env > stored > TTY-gated prompt > manual default (non-interactive never blocks) - leankg add [path] [--auto|--manual] [--embed]: canonicalize path, run the de-facto .leankg init, persist the resolved choice, print an mcp_status-shaped JSON summary (project root, schema, freshness, counts). AUTO kicks indexing as a detached child (returns <2s; no PG required); --embed chains a background embed after indexing via LEANKG_ADD_CHAIN_EMBED - leankg setup --reset clears the stored setup choice so the next add re-asks - leankg status lists every known project (LEANKG_PROJECT_DIRS + current) with freshness + element/relationship/vector counts when Postgres is reachable (--json for one machine-readable document) - leankg install prints the leankg add hint - db::backend::pg_reachable(): block_in_place-guarded PG probe (no nested block_on on the CLI tokio runtime) - single-flight: process-local ADD_AUTO_SPAWNED flag + existing per-project PG advisory lock in index_codebase + embed.lock PID check for chained embeds * feat: FR-ZCP-05 pg_trgm fuzzy bridge tier for the L2 keyword rung Migration 007_trgm_fuzzy.sql (per-schema ledger): best-effort CREATE EXTENSION pg_trgm wrapped in EXCEPTION with a NOTICE — absence degrades to ILIKE-only recall instead of failing. GIN trgm indexes on code_elements(name), code_elements(qualified_name), knowledge_entries(title), knowledge_entries(content) plus one b-tree text_pattern_ops index on code_elements(name) for anchored-prefix LIKE. schema.sql mirrors all five indexes for fresh installs (code_elements indexes beside its table, knowledge_entries indexes after its table). Query seam on DbBackend (no MCP handler changes): - fuzzy_find_elements(query, limit) -> Vec<CodeElement>: ranks by GREATEST(similarity(name,$1), similarity(qualified_name,$1)), unioned with a literal-substring ILIKE OR-match (LIKE-escaped needle), rows carry the standard 11-column element projection plus score; degrades to ILIKE-only with constant score. - suggest_element_names(query, limit) -> Vec<String>: did-you-mean via word_similarity($1, name) with <% indexable operator. - trgm_available() probes similarity() resolution once per URL (LazyLock-cached) to pick the trgm or degraded path. Live tests own a throwaway database (leankg_trgm_test_<pid>) with a localhost-only guard — never schemas in the shared dev database; pure-contract unit tests cover LIKE escaping, limit clamping, bind shapes, and parameterization. 007 documents the ordering invariant (001 creates the base tables it indexes). Seam contract for the wave-2 FR-ZCP-03 router: DbBackend::fuzzy_find_elements(&self, query: &str, limit: usize) -> Result<Vec<CodeElement>, Box<dyn Error>> DbBackend::suggest_element_names(&self, query: &str, limit: usize) -> Result<Vec<String>, Box<dyn Error>> * feat(mcp): lazy auto-attach + background first index, kill silent fallback (FR-ZCP-02) - Kill the silent wrong-project fallback: an unresolved project no longer routes to the server-default schema (execute_tool routing + engine-path resolution). Structured LEANKG_ERROR_UNKNOWN_PROJECT errors carry cause + runnable fix (leankg add / mcp_init), naming LEANKG_AUTO_ATTACH=0 when auto-attach is opted out. - LEANKG_AUTO_ATTACH (default ON): first query in a repo without a .leankg marker attaches the nearest marker or de-facto-inits the nearest repo root (mkdir + default config, mcp_init merge semantics), serves the query cold, and kicks a single-flight background first index. Read-only servers never create project state; unresolved projects error there too. - Background indexing: ensure_project_indexed no longer runs inline in the request path. spawn_background_index runs parser init, incremental-or-full index, call edges, docs parity and ontology refresh in a spawned task with file-progress atomics (RunGuard clears state on exit); on completion the per-project engine + L1 caches are invalidated so the next query sees the populated graph. mcp_status-injected kick hook kick_background_index() is the integration seam for the FR-ZCP-03 router L0 preamble. - Never fail with 'not initialized': mcp_status reports state (freshness: fresh|possibly_stale|cold|unknown + indexing {state: idle|indexing, files_done, files_total}) instead of erroring; empty-graph auto-attach responses are zero-verbosity successes with freshness:cold + indexing provenance. Auth/param errors unchanged. - Watcher stays single-project-per-process (multi-project = FR-ZCP-09). * feat(mcp): leankg_context capability router with L0-L3 degradation ladder (FR-ZCP-03) - New src/mcp/router.rs: one default tool whose params express intent (semantic|lexical|impact|graph|files, auto-classified from query shape). Per-project capability probe (embedding_state limit-1, ::relations HNSW scaffold, index_inventory.total_vectors, has_elements) selects the rung: L3 vector -> semantic_search pipeline; L2 keyword -> DbBackend fuzzy_find_elements + ontology discover fusion; L1 exact -> search_by_name_typed + suggest_element_names; L0 cold -> non-error guidance + background-index kick hook. Zero-result rungs fall down the ladder instead of serving empty pages or errors. Every response shape embeds retrieval {rung, reason, freshness} (FR-ZCP-06 strings). - kg_semantic_context no longer hard-errors without vectors: degrades to the L2 fusion with a structured hint + retrieval block. - Handler: leankg_context dispatch arm; vectors_missing_hint / low-confidence / no-corpus hints now point at leankg_context. - tools.rs: leankg_context registered; every tool description carries a 'Tier:' marker (core 12 / setup 5 / advanced) for FR-ZCP-12 T3. - safe_discover recommended_tools: drop pruned find_function/query_file, leankg_context is the single source of next-tool recommendations. - DbBackend::trgm_available moves to the trait (default false) so the L2 rung degrades honestly; FakeBackend implements the fuzzy seam + a test-flippable trgm flag; test-only 3s PG connect timeout so live-PG tests skip instead of hanging when the dev database is down. * feat(mcp): wire router L0 index-kick to auto-attach dispatch state (FR-ZCP-03/02 integration) * fix(mcp): skip auto-attach full index pass under test FakeBackend (FR-ZCP-02) The background full-pass populated the cwd-ancestor repo through the test-only FakeBackend, turning unrelated audit-dispatch tests (which share the process cwd) into minutes-long tree-sitter walks. Guard the full pass on a real Postgres URL; incremental and cold-attach behavior are unchanged. * fix: FR-ZCP-05 live tests migrated the shared database, not the scratch one CREATE DATABASE does not switch an existing connection: the admin client kept targeting the base URL's database, so run_migrations applied 001..007 to the shared database's public schema (harmless no-op there) while the scratch database stayed empty — trgm_available() then correctly reported false and the test failed, leaving the empty scratch DB behind. Reconnect the admin client to the scratch database (via a shared swapped_db_url helper) before migrating. Verified: both live tests pass against the local pgvector:pg18 container, pg_trgm lands in the scratch DB, teardown leaves zero leankg_trgm_test_* databases, and the shared database's public schema is untouched. * feat(mcp): error catalog with stable codes, causes, runnable fixes (FR-ZCP-12 T1) Add src/errors.rs: a dependency-free catalog (ErrorCode { code, cause, fix, doc_anchor }) with lookup()/all()/render() and a const entry per stable code: LEANKG_ERROR_PG_UNREACHABLE, LEANKG_ERROR_PG_URL_MALFORMED, LEANKG_ERROR_PROJECT_NOT_INITIALIZED, LEANKG_ERROR_UNKNOWN_PROJECT, LEANKG_ERROR_AUTO_ATTACH_FAILED, LEANKG_ERROR_UNAUTHORIZED, LEANKG_ERROR_UNKNOWN_TOOL, LEANKG_ERROR_NO_VECTORS, LEANKG_ERROR_TRGM_UNAVAILABLE, LEANKG_ERROR_METHOD_NOT_FOUND, LEANKG_ERROR_READ_ONLY, LEANKG_ERROR_UNKNOWN_ACTION, LEANKG_ERROR_MISSING_PARAM, LEANKG_ERROR_PERMISSION_DENIED CI lint (4 tests in errors.rs): entries complete (non-empty code/ cause/fix/doc_anchor), every LEANKG_ERROR_* literal in src/ resolves to a catalog entry (100% coverage), every entry referenced by a live use site (no dead entries), lookup/render behavior. Migrate the top error sites to the canonical '<CODE>: <cause>. Fix: <fix> (docs: <anchor>)' format: HTTP/SSE Unauthorized bodies (now name --auth / MCP_HTTP_AUTH), unknown tool (suggests nearest registry match + leankg_context hint), missing params, permission denied, method not found, read-only enforcement, unknown embed/ontology_control actions, auto-attach failures, not-initialized/unknown-project paths, pg_trgm degrade notice, malformed LEANKG_PG_URL, semantic no-vector degrade hint, status Postgres-unreachable line, unknown --format. No success-path behavior changes: same errors, same failures, now with stable codes and runnable fixes. * docs(readme): exact tool count, router-first prefer-order (FR-ZCP-12 T1) Replace the '85+ MCP tools' claim with the code-verified count (77 registered: 77 with embeddings / 74 without — pinned by the exact-count test in src/mcp/tools.rs) in both the Enterprise table and the capability matrix. MCP prefer-order: lead with leankg_context (the FR-ZCP-03 router) and drop the pruned find_function/query_file references; exact-symbol row now points at search_code. All Get Started / CLI verbs verified against src/cli/mod.rs subcommands (init, migrate, index, connect, mcp-http, serve, impact, path, explain, graph-query, embed, mcp-stdio, ontology sync/trace, status, update) — all exist, no changes needed. * docs: regenerate mcp-tool-contract.md for the 77-tool surface (drift-guard target) * feat(mcp): hard one-tool cutover — leankg_context serves ~76 capabilities via verb envelope (FR-ZCP-03 end-state, v4.3.1) - ToolRegistry: exactly 1 registered tool; every former tool name is a verb (verb namespace = legacy namespace; resolve_envelope unwraps {verb}, hard-refuses unknown names with LEANKG_ERROR_UNKNOWN_TOOL + nearest verb) - Envelope resolved BEFORE read-only gate, write-lock, RBAC check_permission, and audit recording (audit records the effective capability; refusals recorded under the raw name) - JSON-RPC tools/call arm: envelope before RBAC + tool_timeout_for + TOON wrap keyed on capability; rmcp call_tool + audited choke point likewise - verb_catalog(): 74 feature-independent + 2 embeddings-gated capabilities - tests: registry-length==1 invariant, envelope contract suite, server-level dispatches migrated to verb_args helper; removed stale test pinning pruned get_callers; docs/mcp-tool-contract.md regenerated (1 tool); README claim updated; PRD v4.3.1 + tracker (FR-ZCP-03 end-state DONE, T3 re-scoped) * docs(tracker): v4.3.1 cutover note + repo hygiene (dependabot backlog, pre-existing test hangs) * fix(mcp): single envelope resolution on the JSON-RPC tools/call arm The arm resolved the envelope (for RBAC-before-gate) and then passed the resolved verb into execute_tool_audited, which resolved AGAIN and hard-refused the verb as an unregistered legacy name — every verb call over streamable HTTP failed with LEANKG_ERROR_UNKNOWN_TOOL. New execute_capability_audited dispatches a pre-resolved capability with the same audit guarantees (capability-keyed ledger, refusal path unchanged for outer-boundary callers via execute_tool_audited). Caught by the live smoke test, not by the suite; lib tests 1302/0. * docs: AGENTS.md storage wording — local Docker Postgres only (remote configs removed 2026-09-05) * test(scale): nested-repo + mega-graph live harness wired into perf-gate CI Adds a Tier-2 harness that proves mega-workspace behaviour on a deterministic nested-repo fixture without touching the real index: scratch DB, dedicated port with stale-server guard, and mega-graph mode engaged by auto-deriving LEANKG_MAX_CACHE_ELEMENTS below the fixture's element count (same code path a 50k repo takes, in seconds). - gen_scale_fixture.py: nested repos at depth 1+3, noise dirs, cross-file edges, Rust+TS; emits .fixture-manifest so coverage iterates real repos (no hardcoded names); refuses --repos >8 unique slots. - scale_harness.sh: docker (local) + direct (CI) PG modes; psql URI-vs-d conflict avoided via pg_admin/pg_scratch split; numeric element-count guard prevents vacuous mega passes; check_consistency refusal asserted deterministically; truncation-safe impact assertion. - perf-gate.yml: scale-harness job (pgvector service, LEANKG_BIN set). Verified 13/13 in docker default, docker --repos 2, and direct mode. * test(scale): refuse vacuous mega pass when threshold derives to 0 (ELEMENTS=0 is numeric) * feat(db): SQLite storage backend — cozo-sqlite engine, sqlite session default (v4.4.0 dual-backend) * docs(prd): v4.4.0-three-tools-dual-backend — 3-tool surface + SQLite backend (FR-3T-01..04, M9) * feat(mcp): 3-tool registry — set / get / status (FR-3T-01, v4.4.0) - registry: exactly 3 tools with per-tool action namespaces; legacy verb names accepted as actions (zero-loss migration); get with no action = multi-layer NL router (L0-L3) - resolve_3tool replaces resolve_envelope at all three dispatch sites (server execute_tool, audited choke point, JSON-RPC arm) — security ordering preserved: resolution before RO-gate/write-lock/RBAC/audit - server tests migrated from one-tool envelope to 3-tool surface; tools.rs tests rewritten for the 3-tool contract (len==3, tier counts, descriptions); cli_tests Status pattern updated for struct variant * docs: regenerate tool contract for 3-tool surface (set/get/status) * fix(test): schema-derivation test uses symlink-resolved base (macOS /tmp); pg_regression doc comments The relative_and_absolute_spellings_derive_same_schema test was env-dependent: TempDir paths under /tmp resolve to /private/tmp on macOS, and the test compared schemas derived from literal vs symlink-resolved spellings. Both flows now use the symlink-resolved dir as the base, making the test deterministic on any platform. Also un-gated PathBuf import (needed by SqliteBackend under release builds). * fix(db): search_knowledge_entries — use environment filter parameter * fix(mcp): 3-tool dispatch on every transport — rmcp arm + RO listing execute_tool_audited (the rmcp call_tool arm: stdio + streamable HTTP) still resolved through the one-tool envelope and hard-refused set/get/status; only the raw JSON-RPC HTTP arm had been rewired. Both transports now share resolve_3tool: - resolve_3tool accepts the legacy leankg_context verb envelope (back-compat) plus action/verb aliases on set/get/status - resolve_envelope deleted (dead one-tool gate) - read-only servers hide the set tool from tools/list (is_ro_hidden_tool) instead of advertising it and failing at dispatch - SQLite backend: embedding-state tables now ensured in SqliteBackend::open (needs a DbBackend handle; fixes --all-features build) instead of init_schema (raw CozoDb) - drop uncompilable benches/redundant_tool_overhead.rs (criterion unlinked; benchmarks removed tools) - ontology_e2e: WorkflowStepMetadata::new gained the name arg Live smoke (SQLite engine): stdio RO tools/list=[get,status], set refused as LEANKG_ERROR_READ_ONLY at resolved mcp_index, NL router + legacy envelope dispatch OK; writable stdio+HTTP list 3 tools, set add_knowledge + mcp_index succeed on SQLite. * fix(status): storage_engine reflects actual backend (sqlite|postgres) mcp_status hardcoded storage_engine:"postgres" — the status tool description promises sqlite|postgres and the live 3-tool smoke showed sqlite:// paths labeled postgres. DbBackend gains engine_name() (default derived from redacted_url) and mcp_status reads it.
…289) * docs(prd): v4.4.1 — live-tested 3-tool SQLite server, issues #286-#288 Changelog entry + tracker rows for the live 3-tool SQLite validation (this repo: 581 files, 9522 vectors, L1/L2/L3 verified) and the Datalog repairs that landed with #285. Open follow-up bugs #286/#287/#288. * bench: leankg 3-tool surface vs grep baseline — 16-question dataset + runners Dataset (benchmark/grep_vs_leankg/questions.json): exact / concept / structure / impact questions over this repo with file-level ground truth. Baseline: scripts/grep_vs_leankg.sh (grep -rn, top-5 files, no ranking). Subject: scripts/leankg_vs_baseline.py (router get, top-5 elements) against the live sqlite server. First-run results (report.md): grep 6/16, leankg 6/16 hit@5 (3-3 in direct wins) but grep is 100x faster. Defects filed: #290 (identifier queries not classified to L1 exact), #291 (minified JS pollutes ANN), #292 (embedder reloaded per request ~18s/query). * bench v2: exclusions + rg ranking + impact-via-search_code; report + issues #293/#294 * bench: limitations — impact-row protocol asymmetry; embeddings not validated by this run * bench: summary correction — exact rows ran via router, not search_code
…n recorded (#318) Syncs the PRD and tracker to the merged state: all 8 fix PRs (#298/#301/ #307/#304/#311/#312/#313/#305/#315) landed on main with fanout review; live validation on this repo (578 files, 10,202 elements, 12,984 vendor-free vectors, router 2.31s warm); open items and follow-ups listed with owners.
…ove Docker/Postgres triggers (#326) Per repo direction: sqlite is the default engine; nothing in the default flow may require or trigger Postgres or Docker. Removed (docker/PG-only tooling): - scripts/docker-up.sh, docker-reload.sh, docker-sync-binary.sh - scripts/embed-all-workspaces-then-mcp.sh, test-cold-embed-perf.sh, test-live-embed-no-stop.sh (docker-compose orchestration) - Dockerfile, Dockerfile.embed-worker, docker-compose.yml, docker-compose.embed.yml, .dockerfile.example - install.sh: the 'docker' subcommand + stale Docker MCP help text (default MCP project= is now the checkout directory) Workflows (all CI now runs sqlite, no service containers): - perf-gate.yml: both PG services + pgvector step removed - quickstart.yml: PG service removed - leankg-update.yml: PG service removed (LEANKG_DB_ENGINE=sqlite) Scale harness rewritten for sqlite: fixture-local .leankg instead of a scratch PG database; engine-aware counting via 'leankg status --json'; per-repo coverage via get_impact_radius on each repo's m01.rs (ranked- search probes raced the boot auto-index and were flaky); auto-index settle wait; RSS gate widened to 3 GB (mega-mode peaks ~1-2 GB). Root cause of the week-long perf-gate red: the harness still asserted the pre-#283 one-tool registry — read-only now exposes {get, status}. quickstart_smoke.sh + start-mcp.sh: sqlite pinned as default engine. status CLI: reads counts from the sqlite db directly (no PG probe, no PG-unreachable error on the default path); JSON output gains 'engine'. User-facing PG hint text no longer suggests docker compose. README/AGENTS.md: storage docs rewritten (sqlite default, PG opt-in). Local verification: - scale harness on sqlite: 12/12 PASS (fixture 3333 elements, nested discovery, noise skip, incremental reindex, RO tool contract get+status, search/impact verbs, mega-mode refusal, RSS bounded) - status on this repo (sqlite): elements 13842 / relationships 76804 / vectors 12984 without any PG probe - bonus: the #322 signal logger captured SIGTERM with name during harness shutdown — silent-death attribution works as designed
Bumps [@vitest/mocker](https://github.com/vitest-dev/vitest/tree/HEAD/packages/mocker) to 5.0.0 and updates ancestor dependency [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest). These dependencies need to be updated together. Updates `@vitest/mocker` from 3.2.7 to 5.0.0 - [Release notes](https://github.com/vitest-dev/vitest/releases) - [Changelog](https://github.com/vitest-dev/vitest/blob/main/docs/releases.md) - [Commits](https://github.com/vitest-dev/vitest/commits/v5.0.0/packages/mocker) Updates `vitest` from 3.2.7 to 5.0.0 - [Release notes](https://github.com/vitest-dev/vitest/releases) - [Changelog](https://github.com/vitest-dev/vitest/blob/main/docs/releases.md) - [Commits](https://github.com/vitest-dev/vitest/commits/v5.0.0/packages/vitest) --- updated-dependencies: - dependency-name: "@vitest/mocker" dependency-version: 5.0.0 dependency-type: indirect - dependency-name: vitest dependency-version: 5.0.0 dependency-type: direct:development ... Signed-off-by: dependabot[bot] <support@github.com>
linhdmn
force-pushed
the
dependabot/npm_and_yarn/ui-v2/multi-00f7b83f97
branch
from
September 14, 2026 05:06
d87a753 to
82e0c83
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Bumps @vitest/mocker to 5.0.0 and updates ancestor dependency vitest. These dependencies need to be updated together.
Updates
@vitest/mockerfrom 3.2.7 to 5.0.0Release notes
Sourced from @vitest/mocker's releases.
... (truncated)
Commits
f441c6fchore: release v5.0.0 (#11130)897f51fchore: release v5.0.0-rc.4 (#11107)7db80dcchore: release v5.0.0-rc.3 (#11089)732df2cfix(deps): update all non-major dependencies (#11043)1e9f80eperf(vm): don't prewarm modules the worker never requests (#11033)af83d1bchore: release v5.0.0-rc.2 (#10976)8ff9b9afix(mocker): restrict redirect mocks to the fs allowlist (#10972)65263d7fix(deps): update all non-major dependencies (#10966)a7fa111chore: release v5.0.0-rc.1 (#10920)0553851chore: add Knip checks (#10847)Updates
vitestfrom 3.2.7 to 5.0.0Release notes
Sourced from vitest's releases.
... (truncated)
Commits
f441c6fchore: release v5.0.0 (#11130)d46a747fix: treat test.describe as a suite during static collection (#11128)584cf30fix: add a warning if inline project has duplicate plugins due to unexpected ...f08ce4bfix: apply queued mocks from doMock() in queue order (fixes #10706) (#11127)897f51fchore: release v5.0.0-rc.4 (#11107)1339b06chore(deps): update all non-major dependencies (#11104)51e9494feat!: parse files statically in vitest list by default (#11088)2122ffdfix: propagate --maxWorkers to projects (#11102)dc10f5ffix(browser): report the action error when a task times out (#11101)d4fe198feat: promote clearCache out of experimental (#11086)Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting
@dependabot rebase.Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR:
@dependabot rebasewill rebase this PR@dependabot recreatewill recreate this PR, overwriting any edits that have been made to it@dependabot show <dependency name> ignore conditionswill show all of the ignore conditions of the specified dependency@dependabot ignore this major versionwill close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)@dependabot ignore this minor versionwill close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)@dependabot ignore this dependencywill close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)You can disable automated security fix PRs for this repo from the Security Alerts page.