mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-12 06:06:37 +03:00
Let a concept record its aesthetic axis values
Three of the six axes cannot be read from a world's prose, and widening their keywords manufactures signal rather than finding it. Depth's probe matched worlds that said "no cast shadow anywhere" and "without perspective or depth"; motion and colour strategy describe properties the system rules never state, so they place 28% and 7%. An optional axes object on the concept records the value instead. Absent means inferred from the rules as before, so nothing needs backfilling. Validated against the axes definition when the caller supplies it, because a typo would read as "unrecorded" and fall back to a probe already known not to work, which is the quietest way for this to fail. This is what makes an assigned wave measurable. If a wave draws "drenched" and "simulated physics" before designing anything, the world it produces has to carry those values or the assignment is lost the moment it lands, and occupancy goes back to guessing at prose. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
f72fcad7d6
commit
166e4481e1
@@ -50,9 +50,36 @@ export function normalizeConceptForm(value) {
|
||||
.trim();
|
||||
}
|
||||
|
||||
export function validateConceptEntry(concept, { existingForms = new Map() } = {}) {
|
||||
export function validateConceptEntry(concept, { existingForms = new Map(), axes = null } = {}) {
|
||||
const errors = [];
|
||||
const id = concept?.id || '(unknown)';
|
||||
|
||||
// Recorded aesthetic axis values. Optional, and absent means the value is
|
||||
// inferred from the system rules instead. Some axes cannot be inferred at all:
|
||||
// depth's keyword probe matched worlds that said "no cast shadow anywhere",
|
||||
// and motion and colour strategy describe properties the rules never state, so
|
||||
// a wave that assigns those has to record them or the assignment is lost.
|
||||
// Validated against the axes definition when the caller supplies it, because a
|
||||
// typo would read as "unrecorded" and silently fall back to a probe that is
|
||||
// known not to work.
|
||||
if (concept?.axes !== undefined && concept.axes !== null) {
|
||||
if (typeof concept.axes !== 'object' || Array.isArray(concept.axes)) {
|
||||
errors.push(`concept ${id} axes must be an object of axis id to value id`);
|
||||
} else if (axes) {
|
||||
const byId = new Map((axes.axes || []).map(axis => [axis.id, axis]));
|
||||
for (const [axisId, valueId] of Object.entries(concept.axes)) {
|
||||
const axis = byId.get(axisId);
|
||||
if (!axis) {
|
||||
errors.push(`concept ${id} names unknown axis "${axisId}"`);
|
||||
} else if (!(axis.values || []).some(value => value.id === valueId)) {
|
||||
errors.push(
|
||||
`concept ${id} axis "${axisId}" has unknown value "${valueId}" `
|
||||
+ `(expected one of ${(axis.values || []).map(v => v.id).join(', ')})`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(concept?.id || '')) {
|
||||
errors.push(`invalid concept id: ${String(concept?.id)}`);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user