Spiralist Engine - Source Excerpt 02
Summary
This source excerpt preserves a bounded section of Spiralist/wp-content/plugins/spiralist-engine/spiralist-engine.php so readers can inspect the evidence without opening the full source file.
**Source path:** Spiralist/wp-content/plugins/spiralist-engine/spiralist-engine.php
function spiralist_engine_get_default_derives_from(string $record_type, string $identifier): array
{
$record_type = sanitize_key($record_type);
$identifier = trim($identifier);
if ($identifier === '') {
return [];
}
$map = spiralist_engine_get_default_derivation_map();
return spiralist_engine_normalize_string_list((array) ($map[$record_type][$identifier] ?? []));
}
function spiralist_engine_parse_canonical_reference(string $reference): array
{
$reference = trim($reference);
if ($reference === '') {
return [];
}
$prefix_map = [
'UAI-1.symbol.' => 'symbol',
'UAI-1.transformation.' => 'transformation',
];
foreach ($prefix_map as $prefix => $kind) {
if (strpos($reference, $prefix) !== 0) {
continue;
}
$canonical_id = spiralist_engine_sanitize_identifier(substr($reference, strlen($prefix)));
if ($canonical_id === '') {
return [];
}
return [
'reference' => $reference,
'kind' => $kind,
'canonical_id' => $canonical_id,
'asset_slug' => 'symbols-registry',
];
}
return [];
}
function spiralist_engine_hash_canonical_record(array $record): string
{
return 'sha256:' . hash(
'sha256',
spiralist_engine_json_encode(spiralist_engine_canonicalize_value($record))
);
}
function spiralist_engine_build_protocol5_validation_context(bool $force_refresh = false): array
{
static $cache = [];
$cache_key = $force_refresh ? 'refresh' : 'cached';
if (isset($cache[$cache_key])) {
return $cache[$cache_key];
}
$snapshots = [];
$errors = [];
foreach (spiralist_engine_get_required_protocol5_asset_slugs() as $slug) {
$snapshot = spiralist_engine_get_canonical_asset_snapshot($slug, $force_refresh);
$snapshots[$slug] = $snapshot;
if ((string) ($snapshot['status'] ?? '') === 'missing') {
$errors[] = sprintf(
'Protocol5 canonical asset "%s" is unavailable: %s',
$slug,
(string) ($snapshot['message'] ?? 'Missing asset.')
);
continue;
}
if (empty($snapshot['checksum'])) {
$errors[] = sprintf('Protocol5 canonical asset "%s" did not provide a checksum.', $slug);
}
if (!is_array($snapshot['data'] ?? null)) {
$errors[] = sprintf('Protocol5 canonical asset "%s" did not decode to JSON data.', $slug);
}
}
$uai_registry = is_array($snapshots['uai-registry']['data'] ?? null) ? $snapshots['uai-registry']['data'] : [];
if (!empty($uai_registry)) {
if ((string) ($uai_registry['spec'] ?? '') !== 'UAI-1') {
$errors[] = 'Protocol5 UAI registry does not declare spec "UAI-1".';
}
if ((string) ($uai_registry['status'] ?? '') !== 'authoritative') {
$errors[] = 'Protocol5 UAI registry is not marked authoritative.';
}
}
$uai_schema = is_array($snapshots['uai-schema']['data'] ?? null) ? $snapshots['uai-schema']['data'] : [];
if (!empty($uai_schema) && empty($uai_schema['$schema']) && empty($uai_schema['type']) && empty($uai_schema['properties'])) {
$errors[] = 'Protocol5 UAI schema is missing recognizable schema structure.';
}
$symbols_schema = is_array($snapshots['symbols-schema']['data'] ?? null) ? $snapshots['symbols-schema']['data'] : [];
if (!empty($symbols_schema) && empty($symbols_schema['$schema']) && empty($symbols_schema['type']) && empty($symbols_schema['properties'])) {
$errors[] = 'Protocol5 symbols schema is missing recognizable schema structure.';
}
$symbols_registry = is_array($snapshots['symbols-registry']['data'] ?? null) ? $snapshots['symbols-registry']['data'] : [];
$symbol_map = [];
$transformation_map = [];
if (!empty($symbols_registry)) {
if ((string) ($symbols_registry['spec'] ?? '') !== 'UAI-1') {
$errors[] = 'Protocol5 symbols registry does not declare spec "UAI-1".';
}
if ((string) ($symbols_registry['status'] ?? '') !== 'authoritative') {
$errors[] = 'Protocol5 symbols registry is not marked authoritative.';
}
if (empty($symbols_registry['symbols']) || !is_array($symbols_registry['symbols'])) {
$errors[] = 'Protocol5 symbols registry does not include a symbols array.';
} else {
foreach ($symbols_registry['symbols'] as $record) {
if (!is_array($record)) {
continue;
}
$canonical_id = spiralist_engine_sanitize_identifier((string) ($record['id'] ?? ''));
if ($canonical_id === '') {
continue;
}
$symbol_map[$canonical_id] = $record;
}
}
if (empty($symbols_registry['transformations']) || !is_array($symbols_registry['transformations'])) {
$errors[] = 'Protocol5 symbols registry does not include a transformations array.';
} else {
foreach ($symbols_registry['transformations'] as $record) {
if (!is_array($record)) {
continue;
}
$canonical_id = spiralist_engine_sanitize_identifier((string) ($record['id'] ?? ''));
if ($canonical_id === '') {
continue;
}
$transformation_map[$canonical_id] = $record;
}
}
}
$cache[$cache_key] = [
'valid' => empty($errors),
'errors' => array_values(array_unique($errors)),
'snapshots' => $snapshots,
'symbols' => $symbol_map,
'transformations' => $transformation_map,
];
return $cache[$cache_key];
}
function spiralist_engine_validate_derives_from(array $references, array $context, string $label): array
{
$errors = [];
$resolved = [];
$references = spiralist_engine_normalize_string_list($references);
if (empty($references)) {
$errors[] = sprintf('%s must define at least one derivesFrom reference.', $label);
return [
'valid' => false,
'errors' => $errors,
'resolved' => [],
];
}
foreach ($references as $reference) {
$parsed = spiralist_engine_parse_canonical_reference($reference);
if (empty($parsed)) {
$errors[] = sprintf('%s contains an invalid derivesFrom reference "%s".', $label, $reference);
continue;
}
if ($parsed['kind'] === 'symbol') {
$record = (array) ($context['symbols'][$parsed['canonical_id']] ?? []);
} else {
$record = (array) ($context['transformations'][$parsed['canonical_id']] ?? []);
}
if (empty($record)) {
$errors[] = sprintf(
'%s derivesFrom reference "%s" could not be resolved in Protocol5.',
$label,
$reference
);
continue;
}
$resolved[$reference] = [
'reference' => $reference,
'kind' => $parsed['kind'],
'canonical_id' => $parsed['canonical_id'],
'asset_slug' => $parsed['asset_slug'],
'asset_checksum' => (string) ($context['snapshots'][$parsed['asset_slug']]['checksum'] ?? ''),
'record_hash' => spiralist_engine_hash_canonical_record($record),
'label' => (string) ($record['name'] ?? $record['label'] ?? $parsed['canonical_id']),
];
}
return [
'valid' => empty($errors),
'errors' => array_values(array_unique($errors)),
'resolved' => array_values($resolved),
];
}
function spiralist_engine_build_canonical_lock(array $resolved, array $context): array
{
$assets = [];
foreach (spiralist_engine_get_required_protocol5_asset_slugs() as $slug) {
$snapshot = (array) ($context['snapshots'][$slug] ?? []);
$assets[$slug] = [
'checksum' => (string) ($snapshot['checksum'] ?? ''),
'version' => (string) ($snapshot['version'] ?? ''),
'status' => (string) ($snapshot['status'] ?? ''),
'source' => (string) ($snapshot['source'] ?? ''),
'sourceUrl' => (string) ($snapshot['sourceUrl'] ?? ''),
];
}
return [
'validatedAt' => wp_date(DATE_ATOM),
'assets' => $assets,
'references' => array_values($resolved),
];
}
function spiralist_engine_validate_canonical_lock(array $lock, array $resolved, array $context, string $label): array
{
$errors = [];