Documentation
¶
Overview ¶
Package ranking implements Prism's 4-signal composite scoring and the budget-aware greedy selector that decides which symbols to deliver and at what fidelity.
A 5th signal, SemanticSimilarity (TF-IDF/Model2Vec cosine similarity to the task string), was removed 2026-08-01. Measured on 15 hand-verified concept queries across 5 real corpora: an agent guessing ONE keyword and using lexical substring search already wins or ties embedding-based discovery in 12/15 cases, often by a wide margin (rank 1 vs rank 19+). Embeddings earned their keep in exactly one case (a query with no single-word guess at all), and even there landed at rank 3, not rank 1. Given that, a heuristic signal contributing up to 25% of the delivery score — with its own persisted reinforcement loop nudging its weight from real usage — was outweighing evidence that it barely helps. The remaining 4 signals are unchanged in relative meaning; weights below are the original per-profile weights renormalized to sum to 1.0 after dropping SemanticSimilarity, so each profile's RELATIVE emphasis is preserved.
Index ¶
- Constants
- Variables
- func ClampLines(src string) string
- func DetectFeedbackSource(repoRoot string) string
- func EstimateTokens(text string) int
- func IsTrivialBody(sym grove.SymbolRecord) bool
- func Render(sym grove.SymbolRecord, lvl DisclosureLevel) string
- func Score(s SignalValues, p Profile) float64
- func ShapeForPhase(phase Phase) (profileHint string, budgetMultiplier float64)
- type BudgetedSymbol
- type Candidate
- type Category
- type DisclosureLevel
- type LearnedWeights
- type Phase
- type Profile
- type SignalComputer
- type SignalValues
Constants ¶
const MaxRenderedLineChars = 1200
Render returns the textual representation of a symbol at the given level. Used by both the selector (cost estimate) and the compressor (output). MaxRenderedLineChars bounds ONE line of rendered symbol source. Generated files embed whole stylesheets or bundles as a single string literal; a symbol containing an 85,462-char line was emitted verbatim and the host rejected the entire tool response. Seeds bypass the token budget by design, so the budget alone cannot prevent this — the clamp has to live at the point of rendering.
const RelevanceThreshold = 0.15
RelevanceThreshold is the minimum composite score below which symbols are downgraded to DisclosureSignature instead of DisclosureFull.
const ScoreCliffFactor = 0.6
ScoreCliffFactor is the multiplier applied to the highest candidate score seen so far to derive the cutoff for subsequent candidates. When a candidate's score drops below (peakScore * ScoreCliffFactor), selection stops — the remaining candidates are noise relative to the top of the list. 0.6 means: stop when score falls more than 40% below the peak.
Variables ¶
CategoryTarget: 0.35, CategoryDependency: 0.25, CategoryTest: 0.20, CategoryDoc: 0.10, CategorySummary: 0.10, }
CategoryShares maps the budget fraction per category.
var Profiles = map[string]Profile{
"implement_feature": {
Name: "implement_feature", GraphDistance: 0.40,
Recency: 0.20, TestRelevance: 0.20, EditFrequency: 0.20,
},
"fix_bug": {
Name: "fix_bug", GraphDistance: 0.2222,
Recency: 0.2778, TestRelevance: 0.2778, EditFrequency: 0.2222,
},
"code_review": {
Name: "code_review", GraphDistance: 0.25,
Recency: 0.1875, TestRelevance: 0.25, EditFrequency: 0.3125,
},
"default": {
Name: "default", GraphDistance: 0.3333,
Recency: 0.2667, TestRelevance: 0.20, EditFrequency: 0.20,
},
}
Profiles is the predefined set of ranking profiles. Looked up by name in SelectProfile; falls back to "default" on unknown names.
Functions ¶
func ClampLines ¶ added in v0.38.5
ClampLines truncates pathologically long lines, saying so in-band. Normal source passes through byte-for-byte: the verbatim contract holds for every line a human would actually read.
func DetectFeedbackSource ¶ added in v0.5.0
DetectFeedbackSource returns the best available signal source for the repo. Priority: Provasign (.provasign/provasign.yaml or legacy .provasign.yaml present) > git (any .git dir) > none.
func EstimateTokens ¶
EstimateTokens is the ~4 chars/token approximation also used by Grove.
func IsTrivialBody ¶ added in v0.5.0
func IsTrivialBody(sym grove.SymbolRecord) bool
IsTrivialBody reports whether a symbol's body carries no additional information beyond its signature. Trivial symbols (short one-liners, passthrough wrappers, getters) are always rendered at DisclosureSignature regardless of their relevance score — the agent needs the signature but gains nothing from seeing the implementation.
A symbol is trivial when ALL of:
- span is populated (End > Start) and spans ≤ 8 lines
- no outgoing calls (CallSites is empty)
- kind is function, method, or constructor
func Render ¶
func Render(sym grove.SymbolRecord, lvl DisclosureLevel) string
func Score ¶
func Score(s SignalValues, p Profile) float64
Score returns the weighted composite score for the given signals + profile.
func ShapeForPhase ¶ added in v0.5.0
ShapeForPhase returns the budget multiplier and suggested profile for a phase. If the phase is unknown (or the caller already supplied an explicit profile), this is a no-op (multiplier 1.0, empty profile).
Types ¶
type BudgetedSymbol ¶
type BudgetedSymbol struct {
Symbol grove.SymbolRecord
Score float64
Category Category
Disclosure DisclosureLevel
TokenCost int
}
BudgetedSymbol is the output of the selector for one chosen symbol.
func Select ¶
func Select(seeds []grove.SymbolRecord, candidates []Candidate, totalBudget int) []BudgetedSymbol
Select runs the budget-aware greedy selector.
- Seeds are always included at DisclosureFull and are NOT charged against the budget (they ARE the targets).
- Remaining candidates are sorted by score desc and assigned a disclosure level that fits each per-category budget.
- Candidates below RelevanceThreshold are forced to DisclosureSignature even if a higher level would fit.
- Previously-seen items are demoted by confidence.
- Selection stops when a candidate's score drops more than ScoreCliffFactor below the peak score seen so far (score cliff cutoff).
type Candidate ¶
type Candidate struct {
Symbol grove.SymbolRecord
Score float64
Category Category
// PreviouslySeen indicates the symbol's file has already been delivered
// in this session at the given confidence.
PreviouslySeen bool
Confidence string // "high" | "medium" | "low"
}
Candidate is one input symbol with a precomputed score and category.
type DisclosureLevel ¶
type DisclosureLevel string
DisclosureLevel controls how much of a symbol is rendered.
const ( DisclosureFull DisclosureLevel = "full" DisclosureSignature DisclosureLevel = "signature" DisclosureReference DisclosureLevel = "reference" )
type LearnedWeights ¶ added in v0.5.0
type LearnedWeights struct {
// contains filtered or unexported fields
}
LearnedWeights stores per-repo adjustments layered on top of base Profiles. Each weight is a nudge in [-1, +1] applied multiplicatively to the base profile weight. Positive = reinforce, negative = suppress.
Keys are Profile.Name (e.g. "fix_bug"), values are per-signal adjustments.
func LoadLearnedWeights ¶ added in v0.5.0
func LoadLearnedWeights(repoRoot string) *LearnedWeights
LoadLearnedWeights loads the per-repo weight adjustments from disk. Returns an empty (non-nil) store on any error so callers never get nil.
func (*LearnedWeights) Apply ¶ added in v0.5.0
func (lw *LearnedWeights) Apply(base Profile) Profile
Apply blends learned adjustments into a base profile. Each signal weight is nudged by the stored delta, then clamped to [0.05, 1.0] so no signal is entirely silenced.
func (*LearnedWeights) RecordOutcome ¶ added in v0.5.0
func (lw *LearnedWeights) RecordOutcome(profileName string, citedPaths, deliveredPaths []string, missingTestSignal bool)
RecordOutcome updates stored weights from one completed task's evidence.
- citedPaths: file paths that appeared in the final diff/commit.
- deliveredPaths: all file paths Prism delivered for this query.
- missingTestSignal: true when a test gate fired (tests were needed but absent).
- profileName: the Profile used for the query (e.g. "fix_bug").
Uses a small learning rate (0.02) so weights converge over ~50 tasks.
type Phase ¶ added in v0.5.0
type Phase string
Phase represents the inferred agent work phase, used to shape the token budget and ranking profile automatically when the caller does not specify one.
func DetectPhase ¶ added in v0.5.0
DetectPhase infers the agent work phase from a free-text task description. It uses a keyword-voting approach: each list casts votes, the winner wins; ties use action-oriented precedence so mixed tasks still get a useful shape.
NOT WIRED IN as of v0.54.0. prism_query used to route the task string through here to pick a ranking profile, a budget multiplier and a delivery mode, which made the phrasing of a request change which files came back. That is a natural-language retrieval key, and this surface does not have one; retrieval keys on terms, sizing on budget, ranking on profile, all caller-set. Nothing in production calls DetectPhase or ShapeForPhase now.
Kept, with its tests, because the phase vocabulary is the starting point if the shaping is ever re-introduced as something the CALLER asks for (e.g. profile="fix_bug") rather than something inferred behind their back. Do not re-attach it to a free-text field.
type Profile ¶
type Profile struct {
Name string
GraphDistance float64
Recency float64
TestRelevance float64
EditFrequency float64
}
Profile defines per-signal weights for a task type. Weights should sum to 1.0 but the implementation tolerates any non-negative weights.
func SelectProfile ¶
SelectProfile returns the profile by name; falls back to "default" if the name is unknown or empty.
type SignalComputer ¶
type SignalComputer struct {
WorkspaceRoot string
// contains filtered or unexported fields
}
SignalComputer computes individual signal values for a symbol relative to a task and a workspace root.
func NewSignalComputer ¶
func NewSignalComputer(workspaceRoot string) *SignalComputer
NewSignalComputer constructs a computer rooted at workspaceRoot.
func (*SignalComputer) Compute ¶
func (c *SignalComputer) Compute(ctx context.Context, task string, sym grove.SymbolRecord, bfsDistance int, hasTestEdgeToSeed bool, sameFileAsTest bool) SignalValues
Compute returns the SignalValues for one symbol given seed symbol IDs and the BFS distance from any seed (0 means seed itself, math.MaxInt = unreachable).