mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-15 07:36:50 +03:00
Call them compositions; single-source WELL_TIERS
The data layer has said compositions since the catalog was split, while the
code, the model-facing text, and the UI still said stagings. The rename was
held back by the selection logic existing twice; it exists once now, so this
is one pass instead of two coordinated ones.
Renamed: selectApprovedStagings, selectApprovedStaging, renderStaging, and
the model-facing STAGING GRAMMAR / STAGING CHALLENGERS / FIRST-SURFACE
STAGING INPUTS headings. The block that introduces them now states what
they are for rather than only what they are not: what is the cleverest way
to present, organize, or make interactive the problem in front of you.
Three places keep the old word on purpose:
- The rank salt, `${scope}:${key}:staging`. It is hash input, so renaming
it would re-deal every roll anyone has ever reproduced by key. Verified:
240 seeder rolls and 252 API rolls reproduce exactly.
- `Staging/hierarchy:`, the first composition grammar prefix. Inside a
composition, staging names one of its four aspects, which is a different
word-sense from staging as the name for the whole artifact. It is also a
schema constant that 317 catalog entries are validated against.
- The wire fields. The API keeps emitting `stagings` and `staging` beside
`compositions`, because the wire is the one place a rename cannot be
coordinated with already-installed skills. Clients prefer the new field
and fall back through both old ones.
Separately, WELL_TIERS had two definitions after the extraction.
roll-selection.mjs owns it now and concept-catalog.mjs imports it, in that
direction because concept-catalog reads the filesystem and a Pages Function
must not pull node:fs into its bundle. Imported and re-exported rather than
re-exported alone: a bare `export { X } from` does not bind X locally, and
validateConceptCatalog needs it, which cost one round of red tests.
Dropped concept-catalog's synchronous deterministicRank. Nothing imports it
since selection moved out, and leaving a second ranking implementation
around is how the first drift started.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
71d7b5e310
commit
a92ba5f2b0
@@ -97,7 +97,7 @@ function compositionTickets(pool) {
|
||||
export function* selectApprovedChallengers({ scope, key, reroll = 0, minRating = null, concepts }) {
|
||||
const approved = concepts.filter(concept => concept.status === 'approved');
|
||||
// Direction chooses a durable identity, so it draws worlds; surface designs
|
||||
// one page inside a committed identity, so it draws stagings. Duals serve
|
||||
// one page inside a committed identity, so it draws compositions. Duals serve
|
||||
// both. A tier with no matching-strength approvals falls back to its full
|
||||
// approved pool rather than starving the roll.
|
||||
const wanted = scope === 'direction'
|
||||
@@ -176,12 +176,12 @@ export function* selectApprovedChallengers({ scope, key, reroll = 0, minRating =
|
||||
}
|
||||
|
||||
/**
|
||||
* Three identity-free staging inputs from an explicit approved pool.
|
||||
* Three identity-free composition inputs from an explicit approved pool.
|
||||
* Drive with runSyncSelection or runAsyncSelection.
|
||||
*
|
||||
* One input was too weak a counterweight to a model's habitual page skeleton:
|
||||
* it became a single optional flourish beside six identity challengers rather
|
||||
* than a real search over composition. Distinct staging families are preferred
|
||||
* than a real search over composition. Distinct composition families are preferred
|
||||
* so a roll tests materially different hierarchy, sequence, and interaction
|
||||
* laws. Cross-mode fallback would make the input misleading, so an absent mode
|
||||
* returns nothing rather than borrowing. Re-rolls exclude every earlier set
|
||||
@@ -196,11 +196,11 @@ export function* selectApprovedChallengers({ scope, key, reroll = 0, minRating =
|
||||
* @param {number} [options.count]
|
||||
* @returns {Generator<string[], Array, string[]>}
|
||||
*/
|
||||
export function* selectApprovedStagings({ scope, key, reroll = 0, mode = null, compositions, count = 3 }) {
|
||||
// Stagings honour the same breadth gate as worlds: one too specific to serve
|
||||
export function* selectApprovedCompositions({ scope, key, reroll = 0, mode = null, compositions, count = 3 }) {
|
||||
// Compositions honour the same breadth gate as worlds: one too specific to serve
|
||||
// an arbitrary build stays approved for direct briefs and leaves the
|
||||
// challenger pool. Falls back to the full approved set rather than returning
|
||||
// nothing if every approved staging is niche.
|
||||
// nothing if every approved composition is niche.
|
||||
let approved = compositions.filter(composition => composition.status === 'approved');
|
||||
const broad = approved.filter(composition => composition.review?.breadth !== 'niche');
|
||||
if (broad.length > 0) approved = broad;
|
||||
@@ -218,15 +218,17 @@ export function* selectApprovedStagings({ scope, key, reroll = 0, mode = null, c
|
||||
const base = available.length >= Math.min(count, approved.length) ? available : approved;
|
||||
// Rating weights the draw as it does for worlds. It matters more here
|
||||
// because the per-surface pools are small, so an unweighted shuffle repeats
|
||||
// a weak staging far more often. Each ticket carries its index so the rank
|
||||
// a weak composition far more often. Each ticket carries its index so the rank
|
||||
// sees a distinct key per ticket: ranking bare duplicates would hash
|
||||
// identically and the pick loop's id-dedupe would silently discard the
|
||||
// second copy, making the weighting a no-op.
|
||||
let tickets = compositionTickets(base);
|
||||
// A pool of nothing but 1-star keeps still has to yield stagings.
|
||||
// A pool of nothing but 1-star keeps still has to yield compositions.
|
||||
if (tickets.length === 0) tickets = base.map(composition => ({ composition, ticket: 0 }));
|
||||
const ranked = (yield* rank(
|
||||
tickets,
|
||||
// The salt keeps the word "staging" deliberately. It is hash input, so
|
||||
// renaming it would re-deal every roll anyone has ever reproduced by key.
|
||||
round === 0 ? `${scope}:${key}:staging` : `${scope}:${key}:staging:reroll-${round}`,
|
||||
entry => `${entry.composition.id}#${entry.ticket}`
|
||||
)).map(entry => entry.composition);
|
||||
|
||||
Reference in New Issue
Block a user