Skip to main content

Module resolve

Module resolve 

Source
Expand description

Resolve & search (decided resolve, decided find) — a port of src/asdecided/services/resolve.py (+ the index construction in src/asdecided/services/index.py), per PORT-CONTRACT.d/06.

Landmines reproduced here (contract §15):

  • ASCII-only tokenizer (§1) vs full-Unicode casefold/strip in exact resolution (§3) and the --tag facet (§5.2).
  • Corpus statistics are corpus-global (all types, unknowns included) even under --type/--tag; ranks are over the matched set only (§6).
  • Duplicate query tokens are NOT deduped: df increments per occurrence and the per-term score adds per occurrence (§7.1).
  • BM25F float operation ORDER is normative (§7): weighted_tf accumulates in id, title, path, heading, body, tags field order with zero-tf fields skipped; score accumulates in query-token order; idf = ln(1 + (n - d + 0.5)/(d + 0.5)) via plain f64 ops (not ln_1p).
  • Competition ranks share on EXACT f64 equality (§8).
  • Sort key is (-py_round(fused, 12), path); the stored fused value stays unrounded; evidence carries py_round(., 6) (§9–10).

Structs§

CorpusStats
Corpus-global BM25 statistics (all entries, unknowns included).
Evidence
The --explain evidence object plus the unrounded score components (bm25_raw/fused_raw are not serialized; they exist so conformance tests can assert exact f64 bit equality against the oracle).
FieldTokens
Flat per-field token vectors, one per scorable field.
IndexEntry
One searchable row of the repository index.
Recency
The git-derived recency join (Staleness.to_dict() shape).
ResolutionResult
Outcome of one exact-ID lookup (ResolutionResult).
ResolvedArtifact
One resolved artifact / search match (ResolvedArtifact).
SearchResult
Outcome of one repository search (SearchResult).

Constants§

OUTCOME_DUPLICATE
OUTCOME_NOT_FOUND
OUTCOME_RESOLVED

Functions§

artifact_status
agent_rules.artifact_status: first non-empty stripped line of ## Status.
build_index
build_repository_index(directory, recursive).artifacts — the searchable index in corpus-walk (sorted-path) order, inbound counts included.
entry_is_retired
entry_is_retired(entry) — the live_only facet (ADR-113): re-read the entry’s ## Status from its file and test it against the type’s retired_status set (is_retired_status). Unreadable/unknown ⇒ live.
find_artifacts
find_artifacts(directory, query, artifact_type, recursive, tags, live_only).
find_decisions
find_decisions(directory, topic, recursive): the type-restricted tiered search, post-filtered to live decisions (ranks keep their gaps — evidence is computed over all matched decisions including non-live ones).
index_from_items
is_retired_status
agent_rules.is_retired_status(artifact_type, status) (ADR-113): spec-driven retirement for every typed artifact. An unknown type retires nothing; an empty status is never retired.
resolve_artifact
resolve_artifact(directory, artifact_id, recursive). The oracle’s identity-only walk (_identity_index) leaves sections/graph/tags at their empty defaults; resolve output reads only id/type/title/path, so those fields never surface (resolve JSON never gains a “tags” key).
resolve_in_index
resolve_in_index(entries, artifact_id): full-Unicode strip + casefold on the query, casefolded exact equality against every alias.
search_index
search_index(entries, query, artifact_type, tags) — matching, corpus stats, BM25F + RRF ranking, and the (-round(fused,12), path) sort.
search_index_filtered
search_index(..., live_only=...) (ADR-113, additive): with live_only, retired artifacts of every type are dropped from the matched set BEFORE scoring, so competition ranks are computed among the live survivors. With live_only=false the result is byte-identical to search_index.
stats_for
Corpus-global statistics for one query over entries — the conformance vector surface (gen_vectors_resolve.py pins n/df/avglen).
tokenize
tokenize(text): split on runs of non-[0-9A-Za-z] (every non-ASCII char is a separator), split each piece at ASCII lowercase→uppercase seams, then casefold (pure-ASCII pieces: exactly A-Z -> a-z).