(dims: Record<Dimension, number>)
| 163 | * Returns FALLBACK_ARCHETYPE if no defined archetype is within threshold. |
| 164 | */ |
| 165 | export function matchArchetype(dims: Record<Dimension, number>): Archetype { |
| 166 | let best: Archetype = FALLBACK_ARCHETYPE; |
| 167 | let bestScore = Infinity; // lower is better |
| 168 | // Threshold: if no archetype scores below this, return Polymath. |
| 169 | // Max possible distance in [0,1]^5 is sqrt(5) ≈ 2.236. 0.55 = ~half the space. |
| 170 | const THRESHOLD = 0.55; |
| 171 | for (const arch of ARCHETYPES) { |
| 172 | const dist = euclidean(dims, arch.center); |
| 173 | // Scale by tightness — tighter archetypes require smaller actual distance. |
| 174 | const scaled = dist / (arch.tightness || 1); |
| 175 | if (scaled < bestScore && scaled <= THRESHOLD) { |
| 176 | bestScore = scaled; |
| 177 | best = arch; |
| 178 | } |
| 179 | } |
| 180 | return best; |
| 181 | } |
| 182 | |
| 183 | /** All archetype names, useful for tests and /plan-tune stats. */ |
| 184 | export function getAllArchetypeNames(): string[] { |
no test coverage detected