cli: clarify darkChromaTaper support for Neutral palette regeneration
Neutral's palette config and saved receipt include darkChromaTaper, but the generator drops it during normalization. It is also absent from TonalPaletteGenerationInput.
I ran the saved config through the unmodified generator on Node 24.20.0 at f138ed997b88e4dc4361e73b388bd4b1d8a47bf4. Removing darkChromaTaper makes no difference to the output. Compared with the committed palette, 99 of 420 family/mode/stop colors differ, all in the nine chromatic dark ramps at stops 5–55. The light and neutral ramps, endpoints, and stops 60–100 match.
For example, blue.dark[25] comes out as #003978 rather than the committed #253c5a; yellow.dark[25] is #4b3900 rather than #453a1c.
Reproduction
Run from a checkout of the revision above, without the local patch:
node --input-type=module <<'NODE'
import {readFileSync} from 'node:fs';
import {isDeepStrictEqual} from 'node:util';
import {generateTonalPalette, normalizeGenerationRequest} from './packages/cli/api/theme/palette/generate/generator.mjs';
import {palette as committed} from './packages/themes/neutral/src/neutralPalettes.generated.ts';
const config = JSON.parse(readFileSync('packages/themes/neutral/palette.config.json', 'utf8'));
const {darkChromaTaper, ...withoutTaper} = config;
const candidate = generateTonalPalette(config);
let compared = 0;
let different = 0;
for (const [id, family] of Object.entries(committed)) {
for (const mode of ['light', 'dark']) {
for (const [stop, color] of Object.entries(family[mode])) {
compared++;
if (candidate.palette[id][mode][stop] !== color) different++;
}
}
}
console.log({
taperRetained: Object.hasOwn(normalizeGenerationRequest(config), 'darkChromaTaper'),
sameWithoutTaper: isDeepStrictEqual(candidate, generateTonalPalette(withoutTaper)),
compared,
different,
generatedBlueDark25: candidate.palette.blue.dark[25],
committedBlueDark25: committed.blue.dark[25],
});
NODE{
taperRetained: false,
sameWithoutTaper: true,
compared: 420,
different: 99,
generatedBlueDark25: '#003978',
committedBlueDark25: '#253c5a'
}Neutral DEC-3 approves the muted dark colors, not a shared generator option. AST-008 FR7 allows edits to accepted palettes, but edited data must not claim exact regeneration. I'm not proposing changes to the approved colors; I'm trying to understand how the saved config and receipt should account for this adjustment.
Should the generator support darkChromaTaper, or should this remain a separate authoring step? I have a local patch that matches all 420 saved colors. If generator support is the intended direction, I'd be happy to submit it with types, validation, docs, and regression tests, keeping output unchanged when the option is omitted. I'd coordinate with #6168 on the overlapping types and docs. The selected-stop refs work in #6305 would stay separate.
Source: facebook/astryx