Bridge MinerGoalSpec (the parsed .gittensory-miner.yml) to the ranker's laneFit input: a pure function that, given a candidate issue's labels/paths and a repo's MinerGoalSpec, produces a 0-1 laneFit score — 1.0 when the candidate matches every preferredLanes entry, 0 when it touches a blockedPaths entry, and a smooth interpolation between. This is the "goal model" the task description calls for: what a miner looks for, tied directly to MinerGoalSpec from Phase 0.
Deliverables
References
src/signals/focus-manifest.ts:1142 (matchesManifestPath) — the existing glob-matching helper to reuse
src/signals/focus-manifest.ts FocusManifestGateConfig (line 20) — blockedPaths-takes-precedence convention to mirror
packages/gittensory-engine/lib/miner-goal-spec.ts (from the MinerGoalSpec parser issue) — the MinerGoalSpec type this consumes
packages/gittensory-engine/lib/opportunity-ranker.ts (from the ranker issue) — the laneFit input this feeds
Bridge
MinerGoalSpec(the parsed.gittensory-miner.yml) to the ranker'slaneFitinput: a pure function that, given a candidate issue's labels/paths and a repo'sMinerGoalSpec, produces a 0-1laneFitscore — 1.0 when the candidate matches everypreferredLanesentry, 0 when it touches ablockedPathsentry, and a smooth interpolation between. This is the "goal model" the task description calls for: what a miner looks for, tied directly toMinerGoalSpecfrom Phase 0.Deliverables
packages/gittensory-engine/lib/goal-model.ts—export type GoalModelInput = { candidatePaths: string[]; candidateLabels: string[]; goalSpec: MinerGoalSpec }andexport function computeLaneFit(input: GoalModelInput): number, returning0immediately if anycandidatePathsentry matches agoalSpec.blockedPathsglob (short-circuit, mirrors theblockedPathsprecedence insrc/signals/focus-manifest.ts's gate config), else a ratio ofpreferredLanesmatches (label or path-glob) over totalpreferredLanescount, defaulting to a neutral0.5whenpreferredLanesis empty (no stated preference ⇒ don't penalize or favor).matchesManifestPath(src/signals/focus-manifest.ts:1142) for glob matching rather than reimplementing path-glob logic — import it directly (or, if it's not exported for external package use yet, note the import gap explicitly in a comment and use an equivalent minimal glob helper scoped to this file).preferredLanesyields exactly0.5; ablockedPathshit always yields0regardless ofpreferredLanesmatches (short-circuit precedence test); a full-match candidate yields1.0; a partial match yields the correct fractional ratio; label-based and path-based lane matches are both exercised.rankOpportunityScore'slaneFitparameter (from the ranker issue) so the two files' contracts stay obviously paired.References
src/signals/focus-manifest.ts:1142(matchesManifestPath) — the existing glob-matching helper to reusesrc/signals/focus-manifest.tsFocusManifestGateConfig(line 20) —blockedPaths-takes-precedence convention to mirrorpackages/gittensory-engine/lib/miner-goal-spec.ts(from the MinerGoalSpec parser issue) — theMinerGoalSpectype this consumespackages/gittensory-engine/lib/opportunity-ranker.ts(from the ranker issue) — thelaneFitinput this feeds