69 lines
3.4 KiB
JavaScript
69 lines
3.4 KiB
JavaScript
/**
|
|
* SHADES / HARD YARDS — Lane E owns this file.
|
|
*
|
|
* The runtime end of the factory's anchor ratings (SPRINT15 gate 1.2).
|
|
*
|
|
* THE BUG THIS CLOSES: `adoptAnchor` is the only place a baked `rating_hint`
|
|
* ever reached an anchor, and it only runs for anchors that name a GLB `node`.
|
|
* Every shipped sail post is a plain JSON entry with no `node`, so the
|
|
* factory's bake never arrived and `?? 1` won — the factory said 0.90, the sim
|
|
* played 1.00, and nothing anywhere could see the disagreement. Gate 1.1 ruled
|
|
* the shipped 1.00 canon (every measured number stands on it), and this module
|
|
* is the mechanism half of that ruling: the same silent divergence is now
|
|
* impossible for the whole extras family (`rating_hint`, `collateral`, and by
|
|
* exclusion `tie_off`) on ANY node-less JSON anchor whose type the factory
|
|
* rates.
|
|
*
|
|
* HOW: the factory emits `anchor_ratings.gen.js` from the re-imported GLBs —
|
|
* per anchor TYPE, the baked extras, but only where every rated node of that
|
|
* type in the palette agrees (`types`). Types whose nodes disagree (tree:
|
|
* 1.0 → 0.4 down the trunk) are listed under `ambiguous`, and this module
|
|
* REFUSES to guess for them — a node-less anchor of an ambiguous type keeps
|
|
* the default hint and warns loudly, and e.test.js pins that no shipped site
|
|
* declares one. Three-way agreement is pinned in e.test.js:
|
|
* GLB === manifest === runtime, so a re-bake that skips regeneration, a
|
|
* hand-edit to the gen file, or a future adoptAnchor-shaped gap all go red.
|
|
*
|
|
* WHO CALLS IT: world.js, at the JSON-anchor creation sites, as
|
|
* `Object.assign(makeStaticAnchor(...), ..., a.node ? null : factoryExtras(type))`
|
|
* — node-carrying anchors keep their graybox default and are corrected by
|
|
* adoptAnchor at dress time, exactly as before; node-less ones take the
|
|
* factory's word at construction, because dress will never reach them.
|
|
*/
|
|
|
|
import { FACTORY_ANCHOR_RATINGS } from './anchor_ratings.gen.js';
|
|
|
|
/** Warn once per type, not once per anchor — a site with four posts of a
|
|
* future ambiguous type should not print four identical warnings. */
|
|
const warned = new Set();
|
|
|
|
/**
|
|
* The factory's baked extras for an anchor TYPE, in runtime (camelCase) field
|
|
* names, ready to `Object.assign` onto an Anchor.
|
|
*
|
|
* @param {string} type An ANCHOR_TYPE string (contracts.js).
|
|
* @returns {{ratingHint: number, collateral?: string}|null}
|
|
* The extras when the factory rates this type unambiguously; null when it
|
|
* doesn't rate it at all (caller keeps its default) or rates it ambiguously
|
|
* (caller keeps its default AND this is almost certainly a site bug — a
|
|
* node-less anchor of an ambiguous type has no honest rating; declare a
|
|
* `node` instead. e.test.js refuses it in shipped sites).
|
|
*/
|
|
export function factoryExtras(type) {
|
|
const t = FACTORY_ANCHOR_RATINGS.types[type];
|
|
if (t) {
|
|
const out = { ratingHint: t.rating_hint };
|
|
if (t.collateral !== undefined) out.collateral = t.collateral;
|
|
return out;
|
|
}
|
|
if (FACTORY_ANCHOR_RATINGS.ambiguous[type] && !warned.has(type)) {
|
|
warned.add(type);
|
|
console.warn(
|
|
`[ratings] anchor type "${type}" is factory-AMBIGUOUS (its GLB nodes carry `
|
|
+ `different rating_hints) — a node-less "${type}" anchor falls back to the `
|
|
+ `default hint, which is the exact silent-divergence bug gate 1.2 buried. `
|
|
+ `Declare a \`node\` on the anchor so adoptAnchor can carry the real bake.`);
|
|
}
|
|
return null;
|
|
}
|