mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-22 02:56:52 +03:00
Add the mode and area axes to the roll
Two gaps, both reported from real use. Worlds were drawn with no mode awareness at all: selectApprovedChallengers never received the mode, so a build asking for an app UI could draw six worlds that only make sense on a landing page. And surface alone is too coarse for compositions, because "operate" spans onboarding, dashboards, editors and settings, so an onboarding flow could legitimately be dealt a settings composition. Worlds gain `allowedModes` on the review record, beside breadth and rating, because it is a reviewer judgment rather than authored content. Absent means eligible in every mode, so nothing needs backfilling and no existing roll changes. Applied per tier and skipped where it would empty one, matching how minRating and strength already degrade. It is a ceiling the reviewer lowers, not a category they assign: a world is an identity, and identities transfer across modes further than compositions do. Compositions gain an optional `area`, one level below surface, with a taxonomy per surface (COMPOSITION_AREAS). Area is a preference rather than a filter: a request reorders the ranking to put area matches first and tops up from the rest of the surface, because the per-area pools are small and dealing one on-target composition would be worse than three good ones. A stable partition of an already deterministic ranking stays deterministic. `--area` on the CLI requires `--mode`, since areas are scoped to a surface, and is validated against that surface's list so a wrong-surface area fails loudly instead of silently matching nothing. Also validated `breadth`, which selection has honoured for a while with nothing checking it, so a typo read as "general" and quietly returned a narrow world to the pool. Four new tests: worlds excluded from a mode stay out, absent allowedModes stays eligible everywhere, a tier whose every world excludes the mode falls back instead of starving, and an area-scoped deal prefers its area, tops up to three, and reproduces from its key. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
7c32d42055
commit
a94331baf0
@@ -465,4 +465,124 @@ describe('init gate', () => {
|
||||
assert.equal(result.status, 0);
|
||||
assert.doesNotMatch(result.stdout, /NO_PRODUCT_MD/);
|
||||
});
|
||||
|
||||
// Mode eligibility on worlds. Before this, selectApprovedChallengers never
|
||||
// received the mode at all, so a build asking for an app UI could draw six
|
||||
// worlds that only make sense on a landing page.
|
||||
it('keeps worlds out of modes their reviewer excluded, and treats absent as all modes', () => {
|
||||
const make = (id, tier, allowedModes) => ({
|
||||
id,
|
||||
familyId: `${id}-family`,
|
||||
wellTier: tier,
|
||||
strength: 'world',
|
||||
status: 'approved',
|
||||
form: `${id} form`,
|
||||
spark: `${id} spark`,
|
||||
system: [],
|
||||
webLeverage: `${id} web`,
|
||||
review: { status: 'approved', ...(allowedModes ? { allowedModes } : {}) },
|
||||
});
|
||||
const pool = [
|
||||
make('persuade-only', 'graphic', ['persuade']),
|
||||
make('anywhere', 'graphic'),
|
||||
make('operate-capable', 'graphic', ['operate', 'read']),
|
||||
make('radar', 'interaction'),
|
||||
make('cavern', 'atmosphere'),
|
||||
];
|
||||
|
||||
for (let index = 0; index < 25; index += 1) {
|
||||
const operate = selectApprovedChallengers({
|
||||
scope: 'direction', key: `mode-gate-${index}`, mode: 'operate', sourceConcepts: pool,
|
||||
}).picks.map(pick => pick.id);
|
||||
assert.equal(operate.includes('persuade-only'), false, `persuade-only dealt for operate at ${index}`);
|
||||
}
|
||||
|
||||
// Absent allowedModes stays eligible in every mode.
|
||||
const seen = new Set();
|
||||
for (let index = 0; index < 25; index += 1) {
|
||||
for (const mode of ['persuade', 'operate', 'read', 'experience']) {
|
||||
for (const pick of selectApprovedChallengers({
|
||||
scope: 'direction', key: `mode-any-${index}`, mode, sourceConcepts: pool,
|
||||
}).picks) seen.add(pick.id);
|
||||
}
|
||||
}
|
||||
assert.equal(seen.has('anywhere'), true, 'a world with no allowedModes must stay eligible');
|
||||
});
|
||||
|
||||
it('falls back rather than starving a tier whose every world excludes the mode', () => {
|
||||
const make = (id, tier, allowedModes) => ({
|
||||
id,
|
||||
familyId: `${id}-family`,
|
||||
wellTier: tier,
|
||||
strength: 'world',
|
||||
status: 'approved',
|
||||
form: `${id} form`,
|
||||
spark: `${id} spark`,
|
||||
system: [],
|
||||
webLeverage: `${id} web`,
|
||||
review: { status: 'approved', ...(allowedModes ? { allowedModes } : {}) },
|
||||
});
|
||||
// The whole interaction tier is persuade-only. Selection must degrade to it
|
||||
// rather than throw or deal fewer than six.
|
||||
const pool = [
|
||||
make('graphic-any', 'graphic'),
|
||||
make('graphic-two', 'graphic'),
|
||||
make('radar-persuade', 'interaction', ['persuade']),
|
||||
make('cavern-any', 'atmosphere'),
|
||||
];
|
||||
const picks = selectApprovedChallengers({
|
||||
scope: 'direction', key: 'starve', mode: 'operate', sourceConcepts: pool,
|
||||
}).picks;
|
||||
assert.equal(picks.some(pick => pick.id === 'radar-persuade'), true, 'an emptied tier must fall back to its full pool');
|
||||
});
|
||||
|
||||
// Areas of concern under a surface. Surface alone is too coarse: an onboarding
|
||||
// flow and a settings page are both operate and want different compositions.
|
||||
it('prefers compositions in the requested area and tops up from the surface', () => {
|
||||
const make = (id, area) => ({
|
||||
id,
|
||||
familyId: `${id}-family`,
|
||||
surface: 'operate',
|
||||
status: 'approved',
|
||||
...(area ? { area } : {}),
|
||||
review: { status: 'approved' },
|
||||
});
|
||||
const pool = [
|
||||
make('onboard-one', 'onboarding-and-setup'),
|
||||
make('onboard-two', 'onboarding-and-setup'),
|
||||
make('settings-one', 'settings-and-account'),
|
||||
make('dash-one', 'dashboard-and-overview'),
|
||||
make('untagged', null),
|
||||
];
|
||||
const picks = selectApprovedCompositions({
|
||||
scope: 'surface', key: 'area-pref', mode: 'operate', area: 'onboarding-and-setup', sourceCompositions: pool,
|
||||
});
|
||||
assert.equal(picks.length, 3, 'a thin area must top up rather than deal fewer');
|
||||
const ids = picks.map(pick => pick.id);
|
||||
assert.equal(ids.includes('onboard-one') && ids.includes('onboard-two'), true, 'both area matches must be dealt first');
|
||||
|
||||
// Without an area the deal is unchanged, which is what keeps this additive.
|
||||
const plain = selectApprovedCompositions({
|
||||
scope: 'surface', key: 'area-pref', mode: 'operate', sourceCompositions: pool,
|
||||
});
|
||||
assert.equal(plain.length, 3);
|
||||
});
|
||||
|
||||
it('reproduces an area-scoped deal from the same key', () => {
|
||||
const make = (id, area) => ({
|
||||
id, familyId: `${id}-family`, surface: 'read', status: 'approved',
|
||||
...(area ? { area } : {}), review: { status: 'approved' },
|
||||
});
|
||||
const pool = [
|
||||
make('article-one', 'long-form-article'),
|
||||
make('article-two', 'long-form-article'),
|
||||
make('docs-one', 'reference-and-docs'),
|
||||
make('index-one', 'index-and-archive'),
|
||||
];
|
||||
const args = { scope: 'surface', key: 'area-stable', mode: 'read', area: 'long-form-article', sourceCompositions: pool };
|
||||
assert.deepEqual(
|
||||
selectApprovedCompositions(args).map(pick => pick.id),
|
||||
selectApprovedCompositions(args).map(pick => pick.id)
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user