Derive adultType from effectiveSeed, rename sync terminology

BlobbiCompanion.adultType now derives from the effective seed for adult
Blobbies instead of reading the (potentially stale) stored tag. Falls
back to the tag only for legacy events without a seed.

Renames to reflect the broadened scope of the sync system:
- needsColorSync -> needsSeedIdentitySync
- eventNeedsColorSync -> eventNeedsSeedIdentitySync

No behavior change beyond making adultType consistent with the seed-
truth model and aligning names with what the code already does.
This commit is contained in:
filemon
2026-04-21 23:07:51 -03:00
parent 3dac492e31
commit d951aab997
4 changed files with 12 additions and 10 deletions
+2 -2
View File
@@ -20,7 +20,7 @@ import {
} from '../lib/blobbi';
/**
* For each visible companion that has needsColorSync === true,
* For each visible companion that has needsSeedIdentitySync === true,
* republish it with an `updateBlobbiTags` call that includes the
* companion's (possibly adjusted) seed. The merge pipeline's
* syncMirrorTagsToSeed will overwrite all stale mirror tags.
@@ -41,7 +41,7 @@ export function useSeedIdentitySync(
if (companions.length === 0) return;
const toSync = companions.filter(
(c) => c.needsColorSync && !c.isLegacy && c.seed && !syncedRef.current.has(c.d),
(c) => c.needsSeedIdentitySync && !c.isLegacy && c.seed && !syncedRef.current.has(c.d),
);
if (toSync.length === 0) return;
+8 -6
View File
@@ -262,7 +262,7 @@ export interface BlobbiCompanion {
/** Whether this is a legacy event that needs migration */
isLegacy: boolean;
/** Whether stored mirror tags differ from seed-derived identity and need republishing */
needsColorSync: boolean;
needsSeedIdentitySync: boolean;
/** Timestamp of last user interaction (unix seconds) */
lastInteraction: number;
/** Timestamp used for stat decay checkpoint (unix seconds) */
@@ -974,7 +974,7 @@ export function companionNeedsMigration(companion: BlobbiCompanion): boolean {
* - no seed exists (legacy event; tags are authoritative)
* - all mirror tags already match the seed-derived values
*/
export function eventNeedsColorSync(tags: string[][]): boolean {
export function eventNeedsSeedIdentitySync(tags: string[][]): boolean {
const seed = getTagValue(tags, 'seed');
if (!seed || seed.length !== 64) return false;
@@ -1204,7 +1204,7 @@ export function parseBlobbiEvent(event: NostrEvent): BlobbiCompanion | undefined
// Check if stored mirror tags need syncing with seed-derived values
// Uses the effective seed (which may be adjusted during compat window)
const needsColorSync = eventNeedsColorSync(
const needsSeedIdentitySync = eventNeedsSeedIdentitySync(
effectiveSeed !== seed
? tags.map((t) => t[0] === 'seed' ? ['seed', effectiveSeed!] : t)
: tags,
@@ -1215,7 +1215,7 @@ export function parseBlobbiEvent(event: NostrEvent): BlobbiCompanion | undefined
d: d.length > 30 ? `${d.slice(0, 20)}...` : d,
name,
isLegacy,
needsColorSync,
needsSeedIdentitySync,
hasSeed: !!seed,
traits: `${visualTraits.baseColor} ${visualTraits.pattern} ${visualTraits.size}`,
});
@@ -1252,7 +1252,7 @@ export function parseBlobbiEvent(event: NostrEvent): BlobbiCompanion | undefined
seed: effectiveSeed,
visualTraits,
isLegacy,
needsColorSync,
needsSeedIdentitySync,
lastInteraction: parseNumericTag(tags, 'last_interaction')!,
lastDecayAt: parseNumericTag(tags, 'last_decay_at'),
stats: {
@@ -1270,7 +1270,9 @@ export function parseBlobbiEvent(event: NostrEvent): BlobbiCompanion | undefined
careStreakLastDay: getTagValue(tags, 'care_streak_last_day'),
incubationTime: parseNumericTag(tags, 'incubation_time'),
startIncubation: parseNumericTag(tags, 'start_incubation'),
adultType: getTagValue(tags, 'adult_type'),
adultType: stage === 'adult' && effectiveSeed && effectiveSeed.length === 64
? deriveAdultTypeFromSeed(effectiveSeed)
: getTagValue(tags, 'adult_type'),
stateStartedAt: parseNumericTag(tags, 'state_started_at'),
progressionStartedAt: parseNumericTag(tags, 'progression_started_at') ?? parseNumericTag(tags, 'state_started_at'),
tasks,
+1 -1
View File
@@ -183,7 +183,7 @@ export function previewToBlobbiCompanion(preview: BlobbiEggPreview) {
// Required but not used for preview rendering
isLegacy: false,
needsColorSync: false,
needsSeedIdentitySync: false,
lastInteraction: preview.createdAt,
lastDecayAt: preview.createdAt,
generation: 1,
+1 -1
View File
@@ -228,7 +228,7 @@ function BlobbiContent() {
}, [filteredCompanions]);
// STEP 3: Sync visible companions whose mirror tags are stale.
// Republishes only companions with actual mismatches (needsColorSync flag).
// Republishes only companions with actual mismatches (needsSeedIdentitySync flag).
useSeedIdentitySync(filteredCompanions, updateCompanionEvent);
// STEP 5: localStorage for UI selection (user-scoped key)