Documentation
¶
Overview ¶
Package finders processes domain query structs into results. Finders encapsulate the actual read logic and hold injected dependencies. Pure reads — no side effects of their own (though injected dependencies may perform IO, e.g. the LLM call behind the pre-flight runner).
Index ¶
- Constants
- func MultiSearch(ctx context.Context, local *SearchFinder, q query.SearchQuery) (*query.SearchResult, error)
- type Finder
- func (f *Finder) CurrentGraph(dir string) (*model.Graph, error)
- func (f *Finder) EffectiveConfig(q query.EffectiveConfigQuery) (*query.EffectiveConfigResult, error)
- func (f *Finder) IndexLint(q query.IndexLintQuery, result *query.LintResult)
- func (f *Finder) Info(_ query.InfoQuery) (*query.InfoResult, error)
- func (f *Finder) Lint(q query.LintQuery) (*query.LintResult, error)
- func (f *Finder) LoadGraph(dir string) (*model.Graph, error)
- func (f *Finder) LoadWIPMarkers(graphDir string) ([]*model.WIPMarker, error)
- func (f *Finder) NewGraphSource(dir string) *GraphSource
- func (f *Finder) Preflight(ctx context.Context, q query.PreflightQuery) (*query.PreflightResult, error)
- func (f *Finder) ReadAttachment(q query.ReadAttachmentQuery) (*query.ReadAttachmentResult, error)
- func (f *Finder) SchemaStatus(ctx context.Context, q query.SchemaStatusQuery) (*query.SchemaStatusResult, error)
- func (f *Finder) Show(q query.ShowQuery) (*query.ShowResult, error)
- func (f *Finder) SkillStatus(ctx context.Context, q query.SkillStatusQuery) (*query.SkillStatusResult, error)
- func (f *Finder) Stats(q query.StatsQuery) (*query.StatsResult, error)
- func (f *Finder) SyncStatus(ctx context.Context, q query.SyncStatusQuery) (model.SyncStatus, error)
- func (f *Finder) View(q query.ViewQuery) (*query.ViewResult, error)
- func (f *Finder) WIPList(q query.WIPListQuery) (*query.WIPListResult, error)
- type GitSyncer
- type GraphSource
- type Options
- type SearchFinder
- type SearchFinderOptions
- type TopicFilter
Constants ¶
const DefaultStalledThreshold = 1.0
DefaultStalledThreshold is the score below which a focus target is classified as stalled when actors are assigned. Default 1.0 is "fewer than one fresh ref-equivalent post-14d-decay" — under exp-14d, a single ref two weeks old contributes 0.5, so a target needs more than two weeks of inactivity (or fewer than ~two recent refs) to drop below. Configurable via the `stalled(value)` modifier per d-tac-uww §6.
The default landed during slice 7 implementation as a starting point; the slice 8 closing findings attachment compares this default against alternatives on the live graph.
const GraphCommitGrepPattern = "^sdd:"
GraphCommitGrepPattern is the commit-message prefix emitted by every SDD handler (handler_new_entry, handler_summarize, handler_wip_start, handler_wip_done, handler_lint_fix, handler_rewrite, handler_init). The sync finder counts commits matching this pattern on either side of the local/upstream divergence to report graph activity.
Variables ¶
This section is empty.
Functions ¶
func MultiSearch ¶ added in v0.15.0
func MultiSearch(ctx context.Context, local *SearchFinder, q query.SearchQuery) (*query.SearchResult, error)
MultiSearch is the cross-graph search read: it runs the query against the local finder and against every repo the query selects, merging all hits into one list by comparable score with remote hits repo-tagged. Pure read — cache freshness and per-repo index fill are the handler's job (Handler.PrepareCrossRepoSearch), run before this like the local lazy-fill precedes a plain Search.
Members resolve internally: the member graph comes from the query graph's cross-graph assembly, the per-repo index opens read-only from the repo's cache, and every member shares the local finder's embedder — the single vector space that makes cosine scores comparable. A selected repo whose graph is unavailable is skipped with a warning (its absence is visible, not silent); a member graph that fails to load is an error.
Embedded (binary-scoped) entries surface exactly once: the local search covers them, and member hits on embedded entries are dropped (remote indexes exclude them; the guard here also covers text mode, which greps the member graph directly).
Types ¶
type Finder ¶
type Finder struct {
// contains filtered or unexported fields
}
Finder holds dependencies and config shared across query methods. Config is a snapshot taken at construction time — short-lived CLI means a single read at the composition root is sufficient. Nil means no config is available (fresh repo, read-only commands, tests); finder methods degrade gracefully.
func (*Finder) CurrentGraph ¶ added in v0.14.1
CurrentGraph sources the current graph once — the one-shot read every short-lived consumer uses instead of calling LoadGraph directly, so all reads share the one GraphSource seam. No memo is retained across calls (each call is its own scope), so a fresh command or request always loads fresh.
func (*Finder) EffectiveConfig ¶ added in v0.15.0
func (f *Finder) EffectiveConfig(q query.EffectiveConfigQuery) (*query.EffectiveConfigResult, error)
EffectiveConfig resolves the config overlay layer by layer and reports each effective value with the layer that supplied it. The finder reads the layers itself (rather than using the merged construction-time snapshot) because provenance is exactly the information merging discards.
func (*Finder) IndexLint ¶ added in v0.15.0
func (f *Finder) IndexLint(q query.IndexLintQuery, result *query.LintResult)
IndexLint fills the index-side fields on a LintResult when an embedding provider is configured. Loading the manifest and building an embedder are both pure operations against config — no graph mutation, no embedding calls (only the fingerprint is read). Errors degrade silently to "index not configured" so a missing dependency in lint doesn't block graph-side validation.
func (*Finder) Info ¶ added in v0.5.2
Info gathers session framing for the `sdd info` command — the session header surface that skill session-start injections read. Pure config inspection — no graph access required.
func (*Finder) Lint ¶
Lint returns every entry in the graph that has at least one warning, alongside the total warning count. Pure read — graph validation runs at graph-construction time, this just collects the results. Also flags entries that are missing a summary.
func (*Finder) LoadGraph ¶
LoadGraph reads all .md files from dir (hierarchical YYYY/MM/ layout), joins the base procedure entries embedded in the binary, and builds the graph. Base entries are always loaded — a project graph never contains them on disk, but its entries may supersede them (procedure customization). On the unlikely ID collision, the disk entry wins: a project owns its graph directory.
func (*Finder) LoadWIPMarkers ¶
LoadWIPMarkers reads all marker files from the wip/ subdirectory of graphDir.
func (*Finder) NewGraphSource ¶ added in v0.14.1
func (f *Finder) NewGraphSource(dir string) *GraphSource
NewGraphSource builds a memoizing source over dir. Held by long-lived readers (the engine session); one-shot readers use CurrentGraph.
The loaded graph is assembled into a model.MultiGraph here — the single insertion point for cross-repo reads. Member graphs load lazily from the connected-repos caches (pure reads; clone/pull side effects run in handlers that invalidate this source), so a graph with no cross-repo touch pays nothing.
func (*Finder) Preflight ¶
func (f *Finder) Preflight(ctx context.Context, q query.PreflightQuery) (*query.PreflightResult, error)
Preflight runs the pre-flight validator against the given query. Runs Go-side mechanical checks first (see mechanicalPreflight), then delegates to the llm package for rubric-based checks, merging the findings so callers see a unified view. Returns an error only for infrastructure failures.
Mechanical checks cover participant coverage (AC 6), actor canonical write-once (AC 5), and role canonical-match + refs-head (AC 7) per plan d-cpt-d34. The former LLM-judged participant-drift check is retired in favor of the mechanical canonical check.
The language-drift check receives the configured graph language from config (see Finder.language). Empty means no language check (English default); a locale code activates the check against description prose.
func (*Finder) ReadAttachment ¶ added in v0.14.0
func (f *Finder) ReadAttachment(q query.ReadAttachmentQuery) (*query.ReadAttachmentResult, error)
ReadAttachment reads one page of an entry's attachment through the shared accessor: the entry's frontmatter-listed attachments are the only readable set, so callers never touch the on-disk layout (d-tac-d21). Pure read.
func (*Finder) SchemaStatus ¶ added in v0.2.0
func (f *Finder) SchemaStatus(ctx context.Context, q query.SchemaStatusQuery) (*query.SchemaStatusResult, error)
SchemaStatus reads .sdd/meta.json (if present) and evaluates its compatibility fields against the calling binary's version and schema version. Pure read; no side effects.
When meta.json is absent the result reports MetaExists = false and Compatible = true — an uninitialised graph is the init command's responsibility, not the write gate's.
func (*Finder) Show ¶
Show resolves the entries named in q and returns groups with upstream and downstream chains. The heavy lifting (tree traversal, dedup, depth limiting) is delegated to model.Graph.BuildShowTree.
func (*Finder) SkillStatus ¶ added in v0.2.0
func (f *Finder) SkillStatus(ctx context.Context, q query.SkillStatusQuery) (*query.SkillStatusResult, error)
SkillStatus loads the embedded skill bundle for the query's target, then walks each entry to compare its embedded content against the file on disk. Classification happens in model.ComputeSkillStatus — the finder only supplies inputs.
func (*Finder) Stats ¶ added in v0.9.0
func (f *Finder) Stats(q query.StatsQuery) (*query.StatsResult, error)
Stats reads the local LLM/embedding stats sink, applies the query's range and field filters, and aggregates the result. Pure read — the only side effect is the underlying file read in the reader. SinkEmpty reflects whether the sink held any records at all, before filtering.
func (*Finder) SyncStatus ¶ added in v0.3.0
func (f *Finder) SyncStatus(ctx context.Context, q query.SyncStatusQuery) (model.SyncStatus, error)
SyncStatus processes a SyncStatusQuery into a SyncStatus. Cooldown is read from the finder's Config; callers supply SDDDir for the last-fetch marker. The finder touches last-fetch on every successful attempt and on terminal failure states (no remote, no upstream, fetch failure) so transient environment issues don't re-poll on every command.
func (*Finder) View ¶ added in v0.5.0
View executes the layout pipeline in q.Layout against q.Graph and returns one SectionResult per section in source order. Per the design, every section must terminate in a render function (e.g. as-list); render is always the pipeline's terminus.
Sourcing dispatches on the first `source(<name>)` call in the section (default `graph` when absent): graph sections walk q.Graph through the filter chain; wip sections use q.WIPMarkers, falling back to f.LoadWIPMarkers(q.GraphDir), as a disjoint data set rendered by as-wip-list. The two paths share the section-walking shell but apply distinct primitive vocabularies; cross- path mixing (e.g. kind() over wip markers) errors with a source-aware message.
WIP markers are resolved once when any section in the layout uses source(wip), then the same slice is handed to every wip section. A nil marker slice and empty GraphDir errors at section evaluation; non-wip layouts ignore both inputs.
Unknown function names return an error listing the valid set so users (and future-slice tests) get a clear signal.
func (*Finder) WIPList ¶
func (f *Finder) WIPList(q query.WIPListQuery) (*query.WIPListResult, error)
WIPList loads every active WIP marker from the wip/ subdirectory of q.GraphDir. Returns an empty result (not an error) when no markers exist.
type GitSyncer ¶ added in v0.3.0
type GitSyncer interface {
// InRepo reports whether the process is inside a git working tree.
InRepo(ctx context.Context) bool
// HasRemote reports whether the repository has at least one remote configured.
HasRemote(ctx context.Context) bool
// UpstreamRef returns the upstream ref name for the current branch
// (e.g. "origin/main"). Empty string + nil error means the branch has
// no upstream configured.
UpstreamRef(ctx context.Context) (string, error)
// Fetch runs `git fetch` with no args. A non-nil error means the fetch
// attempt failed (network, auth, etc.).
Fetch(ctx context.Context) error
// CountCommits counts commits in rangeSpec whose messages match the
// given grep pattern (ERE). rangeSpec is a git log range such as
// "HEAD..@{u}" or "@{u}..HEAD".
CountCommits(ctx context.Context, rangeSpec, grepPattern string) (int, error)
// MergeTreePredict simulates a three-way merge in memory and returns
// the list of paths that would conflict. An empty slice means clean.
// The merge base is computed by git internally from (ourRef, theirRef)
// — this keeps the surface compatible with git 2.38 (the explicit
// --merge-base flag was added in 2.40).
MergeTreePredict(ctx context.Context, ourRef, theirRef string) ([]string, error)
}
GitSyncer is the git surface consumed by the sync finder. Production shells out via exec.Command; tests inject stubs. Methods return errors only for unexpected failures — missing-repo / missing-remote / missing-upstream are expressed through the dedicated boolean / string predicates (InRepo, HasRemote, UpstreamRef) so the finder can report distinct SyncStates rather than collapsing everything into errors.
type GraphSource ¶ added in v0.14.1
type GraphSource struct {
// contains filtered or unexported fields
}
GraphSource is the read side's owner of "what the current graph is": a memoizing read-through over the single IO loader (LoadGraph), with an Invalidate hook that drops the memo after a write. It is the one seam every graph read flows through, so cross-repo assembly (model.MultiGraph) has exactly one insertion point — behind Current — with the side-effectful cache clone/pull staying handler-side, invalidating the source on completion.
One source per read scope. A long-lived reader that reads many times within one scope and mutates the graph mid-scope (the engine session across an advance) holds a source and invalidates it post-write. Short one-shot readers (a CLI command, an MCP free read, a handler validating before a write) call Finder.CurrentGraph, which sources once — no retained cache, matching the prior per-command / per-call lifetime.
func (*GraphSource) Current ¶ added in v0.14.1
func (gs *GraphSource) Current() (*model.Graph, error)
Current returns the current graph, loading it on first call and reusing the memoized value until Invalidate drops it. Concurrency-safe: the read side now owns this state, so a source shared across an engine advance is guarded.
func (*GraphSource) Invalidate ¶ added in v0.14.1
func (gs *GraphSource) Invalidate()
Invalidate drops the memo so the next Current reloads. Called after a write mutates the graph, so post-write reads in the same scope see the change.
type Options ¶ added in v0.3.0
type Options struct {
PreflightRunner llm.Runner
Config *model.PerRepoConfig
GitSyncer GitSyncer
// Repos is the pure read surface over the connected repos — the only
// cross-repo capability a finder holds (no clone, no pull). Nil means no
// connected-repos support: cross-repo refs stay unresolved.
Repos *repos.Registry
}
Options configures a new Finder. Zero-valued fields mean "not available" — methods that need a dependency fall back to empty/nil behaviour rather than failing.
type SearchFinder ¶ added in v0.4.0
type SearchFinder struct {
// contains filtered or unexported fields
}
SearchFinder is the read-side handler for sdd search. It composes three retrieval modes — text (live grep over .sdd/graph/), vector (chromem-go cosine search over chunks), and hybrid (RRF fusion when both are present) — and returns ranked entries with citation chunks.
Pure read: no side effects. The lazy-fill that precedes a query is the IndexHandler's job; this finder consumes the index as-is.
func NewSearchFinder ¶ added in v0.4.0
func NewSearchFinder(opts SearchFinderOptions) *SearchFinder
NewSearchFinder constructs a SearchFinder.
func (*SearchFinder) Search ¶ added in v0.4.0
func (f *SearchFinder) Search(ctx context.Context, q query.SearchQuery) (*query.SearchResult, error)
Search dispatches the query to the appropriate mode.
func (*SearchFinder) VectorAvailable ¶ added in v0.4.0
func (f *SearchFinder) VectorAvailable() bool
VectorAvailable reports whether the configured dependencies allow vector or hybrid mode. Used by the CLI to render the `Search: text` vs `Search: vector,text` capability line in `sdd info`'s header.
type SearchFinderOptions ¶ added in v0.4.0
type SearchFinderOptions struct {
GraphDir string
Embedder llm.Embedder
IndexStore *index.Index
Repos *repos.Registry
}
SearchFinderOptions configures NewSearchFinder. GraphDir is required (used by text mode to resolve attachment paths). Embedder + IndexStore are required for vector and hybrid modes; their absence makes those modes return an error. Repos is required for cross-repo search (MultiSearch).
type TopicFilter ¶ added in v0.5.0
TopicFilter selects entries whose effective topic set contains a label matching the given prefix path component-wise (case-insensitive).
"Effective topics" of an entry combine inline `topics:` declared on the entry's own frontmatter with topics declared by `kind: annotation` entries whose refs (or per-topic members sub-selection) include the entry. This merge is what makes annotations a first-class clustering mechanism — an entry is "in topic X" whether it tagged itself or some annotation tagged it.
Owned by Plan 1 (d-tac-gvn) per the augmenting directive d-tac-9q1; Plan 2 (d-tac-uww, sdd view) consumes this primitive for its `topic(L)` filter vocabulary in the pipeline grammar.
func (TopicFilter) ExcludeEntries ¶ added in v0.5.1
ExcludeEntries returns the subset of entries whose effective topic set does NOT match the prefix. Mirror of FilterEntries for the not(topic(...)) negation primitive (d-tac-e1s). A zero prefix is treated as "no exclusion" — every entry passes through unchanged.
func (TopicFilter) FilterEntries ¶ added in v0.5.0
FilterEntries returns the subset of entries whose effective topic set matches the prefix. Order is preserved; nil input returns nil.
func (TopicFilter) MatchEntry ¶ added in v0.5.0
MatchEntry reports whether the entry has any effective topic with prefix. Pure — uses the graph's reverse index for annotation lookups, no I/O.