Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/dwarves

crates/nornir-warehouse-embed/proto/mimir.proto

// A TRIMMED copy of nornir-server's `Mimir` service — EVERY lens verb nornir
// answers (the 18 of `mimir_lens::LENSES`, `tests/mimir_verbs.rs` holds the list)
// plus the dependency verbs the forge's release plan reads. Until 2026-10-16 it
// carried 12 lenses, so the forge answered `Unimplemented` for DataReach, Trust,
// NameCollision, SymbolIdentity, UndocApi and ReachableVuln.
// Package `nornir.v1` so the generated method paths (`/nornir.v1.Mimir/ChangeRisk`
// …) match the live `nornir-server` — dwarves speaks it as a THIN client WITHOUT
// linking the `nornir` crate (a `dwarves → nornir` edge would be a dependency
// cycle; the `nornir-funnel-embed` / telemetry / warehouse pattern). Field numbers
// and method signatures are byte-identical to `nornir/proto/nornir.proto` (the
// `Mimir` service + `LensQuery`/`GenericCostQuery`) so the wire is compatible —
// `tests/proto_drift.rs` re-derives that contract from nornir's canonical proto and
// fails if a message or method here drifts from it.
//
// ARCHITECTURE (L5a): the QUERY half of every lens belongs in nornir, which owns
// the warehouse, exposed as an RPC so korp's UI and nornir's own viz can reach it
// too. Each method returns the SAME JSON the lens report's `state_json()` emits
// (the observable surface: ranked findings + an `evidence_note` naming missing
// feeds by table) carried as a string, so the wire stays schema-light. A thin
// dwarves pane RENDERS that returned finding set rather than folding a warehouse it
// does not have.
//
// The `JsonResponse` carrier is the one already declared in `workspaces.proto`
// (same `nornir.v1` package) — imported here rather than re-declared, so the whole
// stub set compiles to ONE FileDescriptorSet without a duplicate symbol.
syntax = "proto3";
package nornir.v1;

import "workspaces.proto";

// Mimir LENSES — a READ over the warehouse returning ranked findings as JSON.
// Every response carries an `evidence_note` naming missing feeds by table; an empty
// ranked list and an unfed table must never draw the same.
service Mimir {
  rpc GenericCost    (GenericCostQuery) returns (JsonResponse); // symbol_sizes × binary_facts (× scip_occurrences)
  rpc ZombieFeatures (LensQuery)        returns (JsonResponse); // feature_gate_facts × call_edges × symbol_sizes
  rpc ChangeRisk     (LensQuery)        returns (JsonResponse); // git_heat_facts × call_edges × coverage × semver_diffs
  rpc SimilarCode    (LensQuery)        returns (JsonResponse); // embeddings × symbol_facts (× scip_occurrences)
  // SimilarCode's AND-gate INVERTED: high cosine + LOW structural agreement, i.e.
  // independent RE-implementations. The two PARTITION the high-cosine pair space —
  // a pair is one lens's finding or the other's, never both. Trimmed in 2026-08-25
  // when the lens joined the chain; the server verb (nornir.proto:791) predates it.
  rpc SemanticClones (LensQuery)        returns (JsonResponse); // embeddings × symbol_facts × call_edges — Type-4
  rpc WeakTests      (LensQuery)        returns (JsonResponse); // test_outcomes × git_heat_facts × coverage_fn
  rpc BenchGaps      (LensQuery)        returns (JsonResponse); // git_heat_facts × call_edges × coverage_fn × bench_results
  rpc Villa          (LensQuery)        returns (JsonResponse); // call_edges × symbol_facts — IMPURE/shell-out heresy (std::process::Command, exec/system, external tools)
  // The SOURCE-door lens: sub-item clone regions of ONE repo's checkout, folded from
  // source text with the code room's item spans (`nornir::mimir_lens::subclone`).
  // `repo = ""` is a REFUSAL by design that names the askable repos. nornir's
  // `mimir_lens::answer()` dispatches "subclone" like any lens, but the canonical
  // nornir.proto carries no `Subclone` verb yet (the MCP tool is its live door) — so a
  // live upstream answers `Unimplemented` on this path and the pane shows THAT as the
  // one lens's error, never as "no findings". Declared here so the client, the proxy
  // forward and the pane row exist the moment the server verb lands.
  rpc Subclone       (LensQuery)        returns (JsonResponse); // source text × room item spans — sub-item clone regions, PER-REPO by construction
  // The second SOURCE-door lens (2026-10-20): the same semantic GROUP of statements in two
  // functions of ONE repo (`nornir::mimir_lens::group_twins`), PER-REPO like Subclone —
  // repo="" answers the refusal that names the askable repos.
  rpc GroupTwins     (LensQuery)        returns (JsonResponse); // source text × room item spans × embeddings_groups — group twins, PER-REPO by construction

  // ── the CHANGE / ANOMALY lens family (over the TEMPORAL graph) ───────────
  rpc Churn          (ChurnQuery)      returns (JsonResponse); // git_heat_facts × symbol_facts — frequency filter (high/low/band-pass), churn×complexity hotspot rank
  rpc Anomaly        (AnomalyQuery)    returns (JsonResponse); // git_heat_facts (all snapshots) — z-score/EWMA outliers on the change-series
  rpc WorldImpact    (LensQuery)       returns (JsonResponse); // semver_diffs × call_edges × dep_graph_edges — changes ranked by world + constellation downstream
  rpc BinaryDrift    (LensQuery)        returns (JsonResponse); // symbol_sizes × binary_facts − symbol_facts × call_edges (+ dwarf_* edges): compile-time-injection detector / source↔binary attestation

  // ── the six lenses the trim lacked until 2026-10-16 (same wire as nornir.proto) ──
  rpc DataReach      (LensQuery)        returns (JsonResponse); // TOUCHES_TABLE × reversed CALLS: which code reaches which warehouse table
  rpc Trust          (TrustQuery)       returns (JsonResponse); // bottleneck trust from the entry surface: act / hold / refuse
  rpc NameCollision  (LensQuery)        returns (JsonResponse); // CALLS landing on merged ids vs the leaf-name baseline
  rpc SymbolIdentity (LensQuery)        returns (JsonResponse); // own definitions whose id the fold merged, by cause
  rpc UndocApi       (UndocApiQuery)    returns (JsonResponse); // undocumented public API ranked by churn
  rpc ReachableVuln  (LensQuery)        returns (JsonResponse); // advisories × sbom, refuse only when own code CALLS the crate

  // ── the clone signals (2026-10-17, same wire as nornir.proto): clones by what a function DOES ──
  rpc ExactClones      (LensQuery)      returns (JsonResponse); // the same normalised body (names → roles)
  rpc NearClones       (LensQuery)      returns (JsonResponse); // MinHash/LSH over the normalised bodies
  rpc StructuralClones (LensQuery)      returns (JsonResponse); // IDF-weighted types / fields / callees
  rpc RoleNeighbours   (LensQuery)      returns (JsonResponse); // FastRP role vectors, nearest by role
  rpc SameIntent       (LensQuery)      returns (JsonResponse); // raw-text model, NAME-DRIVEN
  // The twins × DEPENDS_ON (2026-10-22): crate A imports crate B and holds a copy or twin
  // of a B function — call the library's (`nornir::mimir_lens::room_feed::reuse`).
  rpc ReimplementsShared (LensQuery)    returns (JsonResponse); // semantic_twins + similar_code pairs × DEPENDS_ON × CALLS
  rpc SemanticTwins    (LensQuery)      returns (JsonResponse); // Type-3 copies (cos ≥ 0.92 AND structural ≥ 0.50) + Type-4 twins (cos ≥ 0.882 AND structural ≤ 0.35, mutual kNN k=8)

  // ── the cross-repo DEPENDENCY verbs the 🚀 Mímir release plan is read from ──
  // (2026-10-15). The forge's `MimirRelease.Plan` job asks these of the embedded
  // nornir — the release order, each repo's dependencies, what moved since the last
  // recorded release and what that affects. Same wire as nornir.proto's `Mimir`.
  rpc DepsOf           (DepQuery)      returns (JsonResponse);
  rpc DependentsOf     (DepQuery)      returns (JsonResponse);
  rpc AffectedByChange (AffectedQuery) returns (JsonResponse);
  rpc BuildOrder       (Empty)         returns (JsonResponse);
  rpc ChangedSinceLastRelease (Empty)  returns (JsonResponse);
}

message DepQuery      { string repo = 1; bool transitive = 2; }
message AffectedQuery { repeated string repos = 1; }

// A Mimir-lens query: optional `repo` filter (""=all repos) + a result `limit`
// (0 = a per-lens default).
message LensQuery        { string repo = 1; uint32 limit = 2; }
// GenericCost also takes the instantiation floor below which a generic is not
// bloat (0 = default of 2).
message GenericCostQuery { string repo = 1; uint32 min_instantiations = 2; uint32 limit = 3; }
// Churn frequency-filter query: `band` is "high"/"low"/"band"; `cutoff_low`/`cutoff_high`
// are change-frequency (commits_90d) thresholds.
message ChurnQuery       { string repo = 1; string band = 2; int64 cutoff_low = 3; int64 cutoff_high = 4; uint32 limit = 5; }
// Anomaly query: `z_threshold` 0 = the 3.0 (three-sigma) default.
message AnomalyQuery     { string repo = 1; double z_threshold = 2; uint32 limit = 3; }
// Trust query: `act_at` / `hold_at` 0 = the server's bounds.
message TrustQuery       { string repo = 1; double act_at = 2; double hold_at = 3; uint32 limit = 4; }
// UndocApi query: `min_commits_90d` 0 = the server's floor.
message UndocApiQuery    { string repo = 1; int64 min_commits_90d = 2; uint32 limit = 3; }