index

package
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 30, 2026 License: AGPL-3.0 Imports: 23 Imported by: 0

Documentation

Index

Constants

View Source
const SchemaVersion = 4

SchemaVersion bumps whenever schema.sql changes shape. The index is a derived, deletable artifact (the markdown vault is the source of truth), so a version mismatch drops and rebuilds rather than running a migration. This is why Mesh uses no goose/golang-migrate: there is no irreplaceable data to migrate. Note: the source-code tables (code_files/code_symbols/code_edges/code_search) were added additively via CREATE TABLE IF NOT EXISTS, so they appear on existing databases without a destructive rebuild and the version stays 2. Bump this only for a shape change to an existing table, which requires the drop+rebuild below. v3: notes gained review_by + source columns (provenance / lifecycle, Phase A). v4: notes gained a scope column (access-control partition; absent = dev).

Variables

View Source
var SchemaSQL string

SchemaSQL is the SQLite DDL applied when the store is created (used by the store step; embedded now so the schema travels with the binary).

Functions

func ChunkText

func ChunkText(pn *ParsedNote) []string

ChunkText splits a note into retrieval units. Chunk 0 is the header (title + the flywheel fields do/dont/why + tags, the institutional memory that lives in frontmatter, not the body); the rest are one chunk per heading section, each carrying the title as context so an isolated chunk is still self-describing. The default embed path joins these into one whole-note vector; `mesh embed --per-section` stores them separately and scores a note by its best-matching section (max-pool). Per-section showed no recall or answer@1 lift on the Hive corpus at ~18x the cost, so whole-note is default (see the dogfood decision note), but the structured join is itself a better text representation than the collapsed search body.

func ContentHash

func ContentHash(parts ...string) string

ContentHash is the sha256 (hex) of the embedding input parts, NUL-joined so distinct splits cannot collide. The cache keys reuse on this: an unchanged embedding input (same prefix + same chunk text) yields the same hash, so the chunk is not re-sent to the endpoint.

func ParseFiles

func ParseFiles(paths []string, workers int) ([]*ParsedNote, []FileError)

ParseFiles parses paths concurrently with a bounded worker pool and returns the notes in the original path order, so the graph it feeds is deterministic regardless of worker count. Parsing (read + scan) is the dominant, I/O-bound cost and is embarrassingly parallel.

BuildGraph stays serial on purpose: it is a fast id-resolving merge into one shared graph, where mutex contention from N goroutines would cost more than the work it parallelizes.

workers <= 0 means runtime.NumCPU().

func PendingID

func PendingID(noteType, title string) string

PendingID derives a stable id from type+title so re-extracting the same session (or the same learning from two sessions) does not create duplicate review items.

func Reindex

func Reindex(s *Store, root string) (*graph.Graph, error)

Reindex walks the vault, parses it, builds the graph + communities, persists everything, and returns the freshly DB-loaded in-memory graph. Used by the CLI index path; long-running watchers use ReindexFull + ReconcileIncremental instead.

func RetrievalHash

func RetrievalHash(pn *ParsedNote) string

RetrievalHash is the exported retrieval hash for a parsed note: it is what the notes table stores in retrieval_hash, and the embedder stamps onto each vector (note_hash) so a later content change can be detected and the stale vector excluded from retrieval.

func VecKey

func VecKey(nodeID string, chunkIx int) string

VecKey is the stable cache key for a chunk (node id + chunk index).

Types

type CachedVec

type CachedVec struct {
	Hash string
	Vec  []float32
}

CachedVec is a stored embedding plus the content hash it was computed from.

type ClusterInfo

type ClusterInfo struct {
	ID      int
	Size    int
	Members []ClusterMember
}

ClusterInfo is a cluster that needs a map: its members, most-connected first, so the map can lead with the anchors.

type ClusterMember

type ClusterMember struct {
	Title  string
	Path   string
	Type   string
	Degree int
}

ClusterMember is one note in a cluster, for building a map from.

type CodeHit

type CodeHit struct {
	ID        string
	Name      string
	Kind      string
	Lang      string
	Path      string
	Line      int
	Signature string
	Doc       string
	Snippet   string
	Score     float64 // negated bm25, higher is more relevant
}

CodeHit is one FTS5 result over the symbol corpus: enough to render a card and a file:line deep link without a second lookup.

type CodeRef

type CodeRef struct {
	ID        string
	Name      string
	Kind      string
	Path      string
	Line      int
	Signature string
}

CodeRef is a neighbor in the call graph (a caller or callee).

type CodeStats

type CodeStats struct {
	Files   int
	Symbols int
	Edges   int
}

CodeStats reports what a code reindex wrote, for the CLI and orient output.

func ReindexCode

func ReindexCode(s *Store, roots []string, langs map[string]bool) (CodeStats, error)

ReindexCode walks the configured code roots, parses every source file in parallel, and writes a full code index. Returned symbol paths are prefixed with the root's basename (e.g. "automations/dockyard/...") so several repos coexist and the path reads like graphify's src= locator.

type Drift

type Drift struct {
	Added   []string // files present on disk but not in the index
	Changed []string // files whose retrieval-critical content changed since indexing
	Removed []string // files in the index but gone from disk
}

Drift describes how the vault on disk has diverged from the persisted index.

func (Drift) Any

func (d Drift) Any() bool

Any reports whether the index is stale in any way.

type DriftDelta

type DriftDelta struct {
	Upserts    []*ParsedNote // Added + Changed, parsed, vault-relative Path
	RemovedIDs []string      // ids whose files are gone, plus retired old ids
	Drift      Drift         // the path lists, for logging/reporting
}

DriftDelta is DriftReport plus the parsed notes for Added+Changed (so an incremental reconcile does not re-parse them) and the resolved ids of removed notes (so it can target the DELETEs). RemovedIDs also carries the OLD id of a note whose frontmatter id changed under the same path.

type FileError

type FileError struct {
	Path string
	Err  error
}

FileError pairs a path with the error that stopped it from parsing.

type FlywheelStats

type FlywheelStats struct {
	Authored           int64   `json:"authored"`              // write-backs being tracked
	Reused             int64   `json:"reused"`                // how many got >=1 cross-session reuse
	ReuseRatePct       float64 `json:"reuse_rate_pct"`        // reused / authored
	TotalReuses        int64   `json:"total_reuses"`          // sum of qualifying fetches
	MedianHoursToReuse float64 `json:"median_hours_to_reuse"` // over reused notes (0 if none)
	WritesPer100Reads  float64 `json:"writes_per_100_reads"`  // input-health proxy (writes / (queries+fetches))
}

FlywheelStats is the headline answer to "does the flywheel compound?".

type GotchaRow

type GotchaRow struct {
	ID         string `json:"id"`
	Title      string `json:"title"`
	Do         string `json:"do"`
	Dont       string `json:"dont"`
	Why        string `json:"why"`
	Confidence string `json:"confidence"`
}

GotchaRow is a gotcha's guidance, for turning institutional rules into enforcement (the gotcha->guard feature). Only gotchas with a concrete "dont" (an anti-pattern to detect) are candidates; judgment-only notes are not mechanically checkable.

type Heading

type Heading struct {
	Level  int
	Text   string
	Anchor string
	Line   int
}

type HealthFinding

type HealthFinding struct {
	NoteID string `json:"note_id"`
	Path   string `json:"path"`
	Issue  string `json:"issue"`  // dead_ref | overdue | contradiction
	Detail string `json:"detail"` // the missing ref / overdue date / partner note
}

HealthFinding is one lifecycle issue against a note.

type Issue

type Issue struct {
	Path string
	Kind string // missing-id|duplicate-id|broken-link
	Msg  string
}

Issue is a non-fatal problem found while parsing or building the graph.

func BuildGraph

func BuildGraph(notes []*ParsedNote) (*graph.Graph, []Issue)

BuildGraph resolves a set of parsed notes into the in-memory graph. Node identity is the frontmatter id (falling back to the filename, with an issue raised so `mesh migrate` can fix it). Wikilinks resolve by basename to the target note's id, so edges survive a file rename (spec section 3.6).

type Link struct {
	Target string
	Alias  string
	Line   int
}

type LiveIndexer

type LiveIndexer struct {
	// contains filtered or unexported fields
}

LiveIndexer bundles a NoteCache with the seed-then-incremental policy a single long-running watcher needs. The first Reconcile (or any Full) does a complete reindex and seeds the cache; subsequent Reconciles are incremental. It is safe for one watcher goroutine plus occasional Full() calls (its own mutex serializes them); the MCP server uses its own cache under reloadMu instead.

func NewLiveIndexer

func NewLiveIndexer(store *Store, root string) *LiveIndexer

NewLiveIndexer returns a LiveIndexer for the given store + vault root.

func (*LiveIndexer) Full

func (li *LiveIndexer) Full() (*graph.Graph, error)

Full forces a complete reindex and (re)seeds the cache. Used after a write-back that bypassed the watcher.

func (*LiveIndexer) Reconcile

func (li *LiveIndexer) Reconcile(authoritative bool) (Reconciliation, error)

Reconcile brings the index up to date. The first call does a full reindex to seed the cache; later calls are incremental (parse only changed files, targeted note/FTS writes, in-memory graph rebuild). authoritative=false enables the mtime fast path (skip parsing mtime-unchanged files); pass true for the periodic safety tick so a mtime-preserving edit is still caught.

type NoteCache

type NoteCache struct {
	// contains filtered or unexported fields
}

NoteCache holds the last-parsed notes for a long-running indexer (the watcher / MCP server) so an incremental reconcile can rebuild the in-memory graph without re-parsing the whole vault from disk. Keyed by effectiveID; byPath maps a vault-relative path back to its id so a removed file (which can no longer be parsed) resolves to the id it was indexed under.

func NewNoteCache

func NewNoteCache() *NoteCache

NewNoteCache returns an empty cache.

func (*NoteCache) Apply

func (c *NoteCache) Apply(upserts []*ParsedNote, removedIDs []string)

Apply mutates the cache for a delta: removedIDs drop their entries; upserts replace/insert by id and refresh the path index, retiring a stale path (rename) or a stale id (frontmatter id changed under the same path).

func (*NoteCache) Seed

func (c *NoteCache) Seed(notes []*ParsedNote)

Seed replaces the cache contents with the given notes (a full-reindex result).

func (*NoteCache) Snapshot

func (c *NoteCache) Snapshot() []*ParsedNote

Snapshot returns the cached notes. Order is unspecified: BuildGraph resolves by id and DetectCommunities sorts ids internally, so the resulting graph is order-invariant.

type NoteCodeRef

type NoteCodeRef struct {
	NoteID   string `json:"note_id"`
	Title    string `json:"title"`
	Path     string `json:"path"`
	Type     string `json:"type"`
	SymbolID string `json:"symbol_id,omitempty"`
	Symbol   string `json:"symbol,omitempty"`
}

NoteCodeRef is a note linked to a symbol (either direction).

type NoteDate

type NoteDate struct {
	Updated  string // frontmatter updated/when (YYYY-MM-DD)
	ReviewBy string // frontmatter review_by (YYYY-MM-DD), if any
}

NoteDate carries the lifecycle dates retrieval needs for freshness decay.

type NoteFile

type NoteFile struct {
	NodeID string
	Path   string
}

NoteFile pairs a note's graph node id with its vault-relative path.

type NoteRef

type NoteRef struct {
	ID    string `json:"id"`
	Path  string `json:"path"`
	Type  string `json:"type"`
	Mtime int64  `json:"mtime"`
}

NoteRef is a lightweight note descriptor for delta/listing queries.

type ParsedNote

type ParsedNote struct {
	Path     string
	Key      string // lowercased basename without extension; the wikilink key
	FM       *vault.Frontmatter
	Raw      map[string]any
	Body     string
	Headings []Heading
	Links    []Link
	Tags     []Tag
	Mtime    int64 // file modification time (unix seconds); set by ParseFile from the on-disk file, 0 for byte-only Parse
}

ParsedNote is the deterministic structure extracted from a single markdown file: frontmatter, headings, wikilinks, and tags. No reasoning AI involved.

func Parse

func Parse(path string, data []byte) (*ParsedNote, error)

Parse extracts the deterministic structure of a markdown document. Wikilinks and tags inside fenced code blocks and inline code spans are ignored.

func ParseFile

func ParseFile(path string) (*ParsedNote, error)

func ReindexFull

func ReindexFull(s *Store, root string) (*graph.Graph, []*ParsedNote, error)

ReindexFull walks the vault, parses every note, builds the graph + communities, persists everything, and returns BOTH the in-memory graph and the parsed notes (so a long-running caller can seed its NoteCache without a second parse). It does NOT re-read the graph from the DB: the returned graph is the one just built, so a caller that already holds the graph in memory skips the LoadGraph round-trip.

type PendingNote

type PendingNote struct {
	ID         string `json:"id"`
	Type       string `json:"type"`
	Title      string `json:"title"`
	Do         string `json:"do"`
	Dont       string `json:"dont"`
	Why        string `json:"why"`
	Confidence string `json:"confidence"`
	Source     string `json:"source"`
	CreatedAt  int64  `json:"created_at"`
}

PendingNote is an auto-extracted write-back candidate awaiting human review. It mirrors the mesh_append_note fields so a promoted candidate becomes a note with no remapping. It is NOT in retrieval until promoted.

type Reconciliation

type Reconciliation struct {
	Added     int
	Changed   int
	Removed   int
	Reindexed bool
	Graph     *graph.Graph // non-nil only when Reindexed
	Dur       time.Duration
}

Reconciliation reports what a Reconcile did: the drift it found and, when it rebuilt, the freshly loaded graph so a long-running server can swap it in.

func Reconcile

func Reconcile(s *Store, root string) (Reconciliation, error)

Reconcile brings the index up to date with the vault on disk, but only does the expensive rebuild when retrieval-relevant content actually changed. It runs the same content-hash DriftReport `mesh doctor` uses; if a file's mtime moved but its retrieval hash did not (a cosmetic edit, a touch), DriftReport reports no drift and Reconcile skips the reindex. This is the convergent, idempotent core the watcher calls on every file event and on its periodic safety tick: run it twice in a row with no edits in between and the second is a cheap no-op.

func ReconcileIncremental

func ReconcileIncremental(s *Store, root string, cache *NoteCache, mtimeFast bool) (Reconciliation, error)

ReconcileIncremental is the incremental sibling of Reconcile for a long-running watcher that holds a NoteCache. It parses only the changed files (DriftDeltaReport retains that parse), rebuilds the graph in memory from the cache (CPU-only, no disk re-parse), and applies targeted note/FTS writes plus a full nodes/edges rewrite from the rebuilt graph. The DB is always left authoritative for a concurrent `mesh search` reader. The returned Graph is the in-memory one, so the caller can swap it directly without a LoadGraph round-trip.

func (Reconciliation) Any

func (r Reconciliation) Any() bool

Any reports whether the vault had drifted from the index.

type SearchHit

type SearchHit struct {
	NodeID  string // note:<id>
	Title   string
	Path    string  // vault-relative path of the owning note
	Snippet string  // bracketed match excerpt from the body
	Score   float64 // normalized so higher is more relevant (negated bm25)
}

SearchHit is one FTS5 result over the note corpus.

type Store

type Store struct {
	// contains filtered or unexported fields
}

Store is the SQLite index. Concurrency model (spec section 3.2): the database is opened in WAL mode with two pools. All writes funnel through a single writer goroutine over a channel, so there is never a second writer and no "database is locked" contention. Reads use a separate pool, which WAL serves concurrently with the writer. This is the foundation the fsnotify watcher (later) needs: it can stream upserts while mesh_search reads, with no deadlock.

func Open

func Open(vaultRoot string) (*Store, error)

Open creates (or opens) <vaultRoot>/.mesh/mesh.db, applies the schema, and starts the writer goroutine.

func OpenAt

func OpenAt(vaultRoot, meshDir string) (*Store, error)

OpenAt is like Open but stores the index in an explicit directory instead of <vaultRoot>/.mesh. The hub uses this to index its served vault into a dir OUTSIDE the git repo, so the index is never synced to clients.

func (*Store) AddPending

func (s *Store) AddPending(p PendingNote) error

AddPending stores a candidate for review. Idempotent on (type,title): a duplicate extraction updates the existing row rather than piling up review items.

func (*Store) BackfillWritebacks

func (s *Store) BackfillWritebacks() (int, error)

BackfillWritebacks seeds note_reuse from existing agent-authored notes, so the flywheel measurement reflects the whole accumulated corpus on day one instead of only notes written after this shipped. Idempotent (ON CONFLICT DO NOTHING); uses the note's mtime as authoring time, which makes any later fetch of an old note count as genuine cross-session reuse. Returns the number of notes newly tracked.

func (*Store) CachedVectors

func (s *Store) CachedVectors(model string) (map[string]CachedVec, error)

CachedVectors returns the stored embeddings keyed by VecKey, but ONLY when the stored canonical model equals the requested model. A different model invalidates the whole cache (vectors from another model are not reusable), so callers get an empty map and re-embed everything. This is the content-hash cache's read side: a re-embed reuses any chunk whose hash matches, calling the endpoint only for the changed or new ones.

func (*Store) ChangedSince

func (s *Store) ChangedSince(since int64) ([]NoteRef, error)

ChangedSince returns notes whose file mtime is newer than the given unix timestamp, newest first. Lets an agent resuming a session pull only deltas.

func (*Store) Close

func (s *Store) Close() error

Close stops the writer goroutine and closes both pools. It waits for the writer to drain any in-flight transaction before closing the pools, so a write racing shutdown completes cleanly instead of hitting a closed DB.

func (*Store) CodeIndexed

func (s *Store) CodeIndexed() bool

CodeIndexed reports whether the source-code index holds any symbols, so orient and status can mention code search only when it is populated.

func (*Store) CodeNeighbors

func (s *Store) CodeNeighbors(id string) (callers, callees []CodeRef, err error)

CodeNeighbors returns the call-graph neighbors of a symbol: callees (what it calls) and callers (what calls it). Empty for languages without a call graph.

func (*Store) ComputeContradictions

func (s *Store) ComputeContradictions(now time.Time) ([]HealthFinding, error)

ComputeContradictions flags pairs of tier-0 notes that share a tag where one note's `do` strongly overlaps the other's `dont` (one recommends what the other forbids). Dependency-free heuristic (token Jaccard, high threshold to stay high-precision); the curator can later confirm with an LLM. Writes contradiction rows. Returns the findings.

func (*Store) ComputeHealth

func (s *Store) ComputeHealth(vaultRoot string, now time.Time) ([]HealthFinding, error)

ComputeHealth runs the dead-ref + overdue passes over the vault and replaces the note_health rows for those two issue types (it leaves contradiction rows, which the curator owns). Returns the findings it wrote. vaultRoot is the notes vault.

func (*Store) ContributorCounts

func (s *Store) ContributorCounts() (map[string]int, error)

ContributorCounts tallies authored notes per author (from provenance frontmatter).

func (*Store) Count

func (s *Store) Count(table string) (int, error)

Count returns the row count of a table (read pool). The table name is a fixed internal identifier, never user input.

func (*Store) DeletePending

func (s *Store) DeletePending(id string) error

DeletePending removes a review item (on promote or discard).

func (*Store) DriftDeltaReport

func (s *Store) DriftDeltaReport(root string, mtimeFast bool) (DriftDelta, error)

DriftDeltaReport is DriftReport that retains the parse work it must do anyway: it returns the parsed Added+Changed notes and the ids of removed notes, so the incremental reconcile path never parses a file twice. It uses the same authoritative retrieval_hash comparison, so a cosmetic edit (mtime moved, hash unchanged) yields no drift.

mtimeFast trades a little safety for speed on the watcher's hot path: a file whose on-disk mtime equals the stored mtime is trusted unchanged and NOT parsed, so a single edit parses one file instead of the whole vault. The blind spot is an edit that does not move mtime (rare: a mtime-preserving write, or a second edit within the same one-second mtime resolution as the index); the watcher's periodic tick calls this with mtimeFast=false (parse-all, hash-authoritative), which catches any such case within one interval. Pass false for a correctness pass (the tick, `mesh doctor`, startup).

func (*Store) DriftReport

func (s *Store) DriftReport(root string) (Drift, error)

DriftReport compares the current vault files against the persisted notes using the same retrieval_hash the indexer stores, so `mesh doctor` can tell the operator exactly which files need a reindex instead of guessing.

func (*Store) FlywheelStats

func (s *Store) FlywheelStats() (FlywheelStats, error)

FlywheelStats computes the reuse picture from note_reuse plus the usage counters.

func (*Store) GetPending

func (s *Store) GetPending(id string) (PendingNote, error)

GetPending fetches one review item by id.

func (*Store) Gotchas

func (s *Store) Gotchas(highOnly bool) ([]GotchaRow, error)

Gotchas returns gotcha notes that have an anti-pattern (non-empty dont). When highOnly is set, only confidence=high ones (the safest to turn into a guard).

func (*Store) HealthCounts

func (s *Store) HealthCounts() (map[string]int, error)

HealthCounts returns issue -> count for the dashboard.

func (*Store) IncrMetric

func (s *Store) IncrMetric(key string, n int64) error

IncrMetric adds n to a counter (upsert). Best-effort at call sites.

func (*Store) IndexCodeFull

func (s *Store) IndexCodeFull(files []*code.CodeFile) (CodeStats, error)

IndexCodeFull writes the parsed source files as a full reindex in one transaction: wipe the code tables, insert files + symbols + FTS rows, then rebuild the call-graph edges from the freshly written symbols. Returns counts.

func (*Store) IndexVault

func (s *Store) IndexVault(notes []*ParsedNote, g *graph.Graph) (int, error)

IndexVault writes the parsed notes and graph into the store as a full reindex in a single transaction (M0: wipe + insert; incremental upsert lands with the watcher). Returns the number of notes written.

func (*Store) IndexVaultIncremental

func (s *Store) IndexVaultIncremental(upserts []*ParsedNote, removedIDs []string, g *graph.Graph) (int, error)

IndexVaultIncremental applies a drift delta: targeted INSERT OR REPLACE / DELETE for the changed notes + their FTS rows, a full rewrite of the (globally rebuilt) nodes/edges tables from the in-memory graph, and the orphan-vector prune, all in one writer-goroutine transaction so a concurrent reader sees an all-or-nothing WAL snapshot. upserts are Added+Changed notes (vault-relative Path); removedIDs are ids whose files are gone (and old ids retired on an id change). Returns the number of upserted notes.

func (*Store) LinkNotesToCode

func (s *Store) LinkNotesToCode(vaultRoot string) (int, error)

LinkNotesToCode rebuilds note_code_links from note titles + bodies + the code index. A distinctive token links to a symbol when it equals the symbol name or its last segment (so a bare `RecordReuse` matches `Store.RecordReuse`). Titles are scanned in full (high signal); bodies only inside backticks (prose would be too noisy). Capped per token so a common name does not fan out. No-op when the code index is empty.

func (*Store) ListHealth

func (s *Store) ListHealth(issue string) ([]HealthFinding, error)

ListHealth returns current findings (optionally filtered by issue, "" = all).

func (*Store) ListPending

func (s *Store) ListPending() ([]PendingNote, error)

ListPending returns review items, newest first.

func (*Store) LoadGraph

func (s *Store) LoadGraph() (*graph.Graph, error)

LoadGraph reconstructs the in-memory graph from the persisted nodes + edges tables. The CLI uses this for retrieval without re-parsing the vault; the long-running daemon (MCP) keeps the graph in memory instead.

func (*Store) LoadVectors

func (s *Store) LoadVectors() (model string, dim int, byNode map[string][][]float32, err error)

LoadVectors returns the canonical model and every LIVE chunk vector grouped by node id. A note's relevance is later scored as the max cosine over its chunks (best-matching section). "Live" means the JOIN to notes excludes both orphans (a vector whose note was deleted) and stale vectors (a vector whose note_hash no longer matches the note's current retrieval_hash because the note was edited since the last embed). This is the fix for the reindex-drift bug: an edited or deleted note never contributes a stale semantic signal; it simply falls back to the lexical + graph signals until the next `mesh embed` refreshes its vector.

func (*Store) MeshDir

func (s *Store) MeshDir() string

MeshDir returns the vault's .mesh directory (where mesh.db and the solo config.toml live).

func (*Store) Metric

func (s *Store) Metric(key string) (int64, error)

Metric reads one counter (0 if absent).

func (*Store) NoteCountForSymbol

func (s *Store) NoteCountForSymbol(symbolID string) int

NoteCountForSymbol returns how many notes reference a symbol (for result badges).

func (*Store) NoteDates

func (s *Store) NoteDates() (map[string]NoteDate, error)

NoteDates returns id -> lifecycle dates for every note, for freshness decay.

func (*Store) NoteDocs

func (s *Store) NoteDocs(ids []string) (map[string]string, error)

NoteDocs returns the rerankable text (title + indexed body) for the given note node ids, keyed by node id. Missing ids are simply absent from the map. The text is the same searchText Mesh indexes into FTS, so the reranker scores the query against exactly what made the note a candidate.

func (*Store) NoteFiles

func (s *Store) NoteFiles() ([]NoteFile, error)

NoteFiles lists every note's node id + path so the embedder can read and chunk the source file.

func (*Store) NotePath

func (s *Store) NotePath(id string) (string, error)

NotePath resolves a note id to its vault-relative path (read pool).

func (*Store) NoteRetrievalHash

func (s *Store) NoteRetrievalHash(nodeID string) (string, error)

NoteRetrievalHash returns the stored retrieval_hash for a note node id (e.g. "note:a"), or "" if the note is absent. It is the value the embedder stamps onto a vector's note_hash; retrieval compares the two to detect staleness.

func (*Store) NoteScope

func (s *Store) NoteScope(id string) ([]string, error)

NoteScope returns a note's access scope(s) by id. Used to scope-check a direct fetch (which resolves id -> path -> file, bypassing the retriever's card filter). A missing scope falls back to the fail-safe default (dev-only).

func (*Store) NotesByType

func (s *Store) NotesByType() (map[string]int, error)

NotesByType returns type -> count for coverage.

func (*Store) NotesForSymbol

func (s *Store) NotesForSymbol(symbolID string) ([]NoteCodeRef, error)

NotesForSymbol returns the notes that reference a given code symbol id.

func (*Store) NotesForSymbolName

func (s *Store) NotesForSymbolName(name string) ([]NoteCodeRef, error)

NotesForSymbolName returns notes linked to any symbol matching a name (exact, or as the type/receiver or last segment), so "Verifier" surfaces notes about Verifier, Verifier.Configured, or x.Verifier, regardless of which symbol id FTS ranked first.

func (*Store) Path

func (s *Store) Path() string

func (*Store) PendingCount

func (s *Store) PendingCount() (int, error)

PendingCount returns the number of review items (for the dashboard badge).

func (*Store) RecordHealth

func (s *Store) RecordHealth(issue string, findings []HealthFinding, now time.Time) error

RecordHealth upserts contradiction (or any) findings without touching the dead_ref/overdue rows. Used by the curator's contradiction pass (C3).

func (*Store) RecordReuse

func (s *Store) RecordReuse(noteID string, gapSec int64) error

RecordReuse records a fetch of a tracked note as reuse, but only when it happens at least gapSec after the note was authored. A no-op for untracked notes (those not written back through Mesh) and for fetches inside the authoring burst. Best-effort.

func (*Store) RecordWriteback

func (s *Store) RecordWriteback(noteID, source string) error

RecordWriteback stamps a note as a write-back at authoring time so its reuse can be measured. Idempotent: re-writing the same id keeps the original authored_at (the flywheel cares about when the knowledge first existed). Best-effort at call sites.

func (*Store) ReplaceVectors

func (s *Store) ReplaceVectors(model string, rows []VectorRow) error

ReplaceVectors wipes the vectors table and stores the given chunk embeddings under one canonical model (homogeneity: a vault holds exactly one embedding model so cosine stays meaningful). Runs in the writer goroutine.

func (*Store) Search

func (s *Store) Search(query string, limit int) ([]SearchHit, error)

Search runs an FTS5 MATCH over search_index and returns the most relevant notes. User input is sanitized into quoted literal tokens so FTS5's reserved grammar (NEAR/OR/NOT/AND/*/parens) can never break the parser or inject.

func (*Store) SearchCode

func (s *Store) SearchCode(query string, limit int, langs []string) ([]CodeHit, error)

SearchCode runs an FTS5 MATCH over the symbol corpus, ranking name matches well above signature and doc (the bm25 weights). Display fields come from the canonical code_symbols (joined on the symbol id), not the FTS row, whose name column holds the split-identifier search text. It over-fetches and re-ranks with a test-code penalty so a real symbol (DeployHandler) outranks the many verbose test names that also mention the query terms. langs optionally restricts to a set of language tags. Shares buildFTS5Query with note search so both tokenize alike.

func (*Store) SymbolsForNote

func (s *Store) SymbolsForNote(noteID string) ([]NoteCodeRef, error)

SymbolsForNote returns the code symbols a note references.

func (*Store) TopFetched

func (s *Store) TopFetched(limit int) ([]struct {
	NoteID string `json:"note_id"`
	Count  int64  `json:"count"`
}, error)

TopFetched returns the most-fetched notes (id, count), highest first.

func (*Store) VectorMeta

func (s *Store) VectorMeta() (model string, dim int)

VectorMeta returns the stored canonical model and dim from meta. It is lightweight: it does not load the vector blobs. Zero values when none stored.

func (*Store) VectorStats

func (s *Store) VectorStats() (total, live, staleOrOrphan int, err error)

VectorStats reports vector freshness for status / mesh://stats: total stored rows, how many are live (note exists and unchanged since embed), and how many are stale or orphaned (note edited or deleted since embed). A re-embed clears the stale count.

func (*Store) Write

func (s *Store) Write(fn func(*sql.Tx) error) error

Write runs fn inside a transaction on the single writer goroutine.

type StructureFinding

type StructureFinding struct {
	Severity string // high | med | low
	Kind     string // untyped | unknown-type | orphan | weak-link | hub-only | mapless-cluster
	Path     string
	Detail   string
}

StructureFinding is one organization problem on one note (or cluster).

type StructureReport

type StructureReport struct {
	Notes           int
	Score           int // 0-100
	Grade           string
	ByType          map[string]int
	Tier0           int
	Orphans         int
	Unparseable     int // notes whose frontmatter/markdown fails to parse (invisible to the graph)
	Clusters        int
	Mapless         int
	Findings        []StructureFinding
	MaplessClusters []ClusterInfo // members of each mapless cluster, to author its map
}

StructureReport is the vault's organization grade plus the itemized findings.

func AnalyzeStructure

func AnalyzeStructure(g *graph.Graph, parsed []*ParsedNote, parseErrs []FileError) StructureReport

AnalyzeStructure grades the organization of a parsed vault against its built graph (run DetectCommunities first so cluster checks work). parseErrs are the files Walk found but ParseFiles could not parse: they are the worst structural failure (a note that fails to parse is invisible to search and the graph, with no other signal), so they are surfaced as high-severity and counted against the grade. Pure; no I/O.

type Tag

type Tag struct {
	Name string
	Line int
}

type VectorRow

type VectorRow struct {
	NodeID      string
	ChunkIx     int
	Vec         []float32
	ContentHash string // sha256 of the embedding input; lets a re-embed skip unchanged chunks
	NoteHash    string // the note's retrieval_hash when embedded; lets retrieval exclude this vector once the note changes
}

VectorRow is one stored chunk embedding (a note can have several: one per heading section, so a query matches the relevant section, not a blurry whole-note average).

Directories

Path Synopsis
Package code parses source files into a lightweight symbol graph so Mesh can answer "where does this function live / what calls it" without a separate code indexer.
Package code parses source files into a lightweight symbol graph so Mesh can answer "where does this function live / what calls it" without a separate code indexer.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL