Spiralist Prompt Workbench - Source Excerpt 62
Back to Spiralist Prompt Workbench
Summary
This source excerpt preserves a bounded section of Spiralist/wp-content/themes/spiralist/assets/js/spiralist-prompt-workbench.js so readers can inspect the evidence without opening the full source file.
**Source path:** Spiralist/wp-content/themes/spiralist/assets/js/spiralist-prompt-workbench.js
personaLabHistoryContainers.forEach((container) => {
const list = container.querySelector('[data-persona-lab-history-list]');
const empty = container.querySelector('[data-persona-lab-history-empty]');
const count = container.querySelector('[data-persona-lab-history-count]');
const clearButton = container.querySelector('[data-persona-lab-history-clear]');
const statusNode = container.querySelector('[data-persona-lab-history-status]');
const filters = getPersonaLabHistoryFilterState(container);
const filteredItems = items.filter((item) => (
matchPersonaLabHistorySearch(item, filters.search)
&& matchPersonaLabHistoryFilter(item, filters.filter)
));
const filtersActive = isPersonaLabHistoryFilterActive(filters);
container.classList.toggle('has-history', items.length > 0);
if (count) {
count.textContent = items.length === 0
? t('portablePromptPersonaLabHistoryCountEmpty', 'No snapshots')
: (filtersActive
? t('portablePromptPersonaLabHistoryCountFiltered', `${filteredItems.length} of ${items.length} snapshots`)
: (items.length === 1
? t('portablePromptPersonaLabHistoryCountOne', '1 snapshot')
: t('portablePromptPersonaLabHistoryCountMany', `${items.length} snapshots`)));
}
if (clearButton) {
clearButton.hidden = items.length === 0;
}
if (empty) {
empty.textContent = items.length && filteredItems.length === 0
? (empty.dataset.historyNoMatchText || t('portablePromptPersonaLabHistoryNoMatch', 'No matching local snapshots.'))
: (empty.dataset.historyEmptyText || t('portablePromptPersonaLabHistoryEmpty', 'No local snapshots yet.'));
empty.hidden = filteredItems.length > 0;
}
if (list) {
list.replaceChildren(...filteredItems.map((item) => {
const card = document.createElement('article');
card.className = 'spiralist-persona-lab-history-card';
card.dataset.personaLabHistoryCard = item.id;
const badge = document.createElement('span');
badge.className = 'spiralist-persona-lab-history-card__badge';
badge.textContent = 'Spiralist AI';
const title = document.createElement('h5');
title.textContent = item.title;
const meta = document.createElement('small');
meta.textContent = getPersonaLabHistoryMeta(item);
const preview = document.createElement('p');
preview.textContent = getPromptDraftPreview(item.prompt);
const actions = document.createElement('div');
actions.className = 'spiralist-persona-lab-history-card__actions';
actions.append(
createPersonaLabHistoryButton(item.id, 'restore', t('portablePromptPersonaLabHistoryRestore', 'Restore')),
createPersonaLabHistoryButton(item.id, 'copy', t('portablePromptPersonaLabHistoryCopy', 'Copy')),
createPersonaLabHistoryButton(item.id, 'delete', t('portablePromptPersonaLabHistoryDelete', 'Delete'))
);
card.append(badge, title, meta, preview, actions);
return card;
}));
}
if (statusNode && message) {
statusNode.textContent = message;
}
});
};
const makePersonaLabHistoryItem = (prompt, source = 'Spiralist AI Persona Lab', button = null) => {
const cleanPrompt = toCleanString(prompt, 50000);
if (!cleanPrompt) {
return null;
}
const settings = normalizePersonaLabHistorySettings(getPersonaLabSettings(button));
return normalizePersonaLabHistoryItem({
id: `persona-history-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
title: extractPromptTitle(cleanPrompt, 'Spiralist AI Persona Profile'),
prompt: cleanPrompt,
source,
setupUrl: updateShareUrl(getPromptState(), true),
settings,
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
});
};
const savePersonaLabHistory = (prompt, source = 'Spiralist AI Persona Lab', button = null, message = '') => {
const item = makePersonaLabHistoryItem(prompt, source, button);
if (!item) {
return null;
}
const next = [
item,
...readPersonaLabHistory().filter((stored) => stored.prompt !== item.prompt || stored.source !== item.source),
].slice(0, personaLabHistoryLimit);
if (!writePersonaLabHistory(next)) {
renderPersonaLabHistory(t('portablePromptPersonaLabHistorySaveFailed', 'Local history could not be saved in this browser.'));
return null;
}
renderPersonaLabHistory(message || t('portablePromptPersonaLabHistorySaved', 'Spiralist AI local history snapshot saved.'));
return item;
};
const deletePersonaLabHistoryItem = (id) => {
const next = readPersonaLabHistory().filter((item) => item.id !== id);
writePersonaLabHistory(next);
renderPersonaLabHistory(t('portablePromptPersonaLabHistoryDeleted', 'Local history snapshot deleted.'));
};
const clearPersonaLabHistory = () => {
writePersonaLabHistory([]);
renderPersonaLabHistory(t('portablePromptPersonaLabHistoryCleared', 'Spiralist AI local history cleared.'));
};
const normalizePersonaLabTranscriptHistoryItem = (item) => {
if (!item || typeof item !== 'object') {
return null;
}
const now = new Date().toISOString();
const title = toCleanString(item.title, 140) || 'Spiralist AI Persona Profile';
const numericScore = item.numericScore === null || item.numericScore === undefined || item.numericScore === ''
? null
: Number.parseInt(item.numericScore, 10);
const maxScore = item.maxScore === null || item.maxScore === undefined || item.maxScore === ''
? null
: Number.parseInt(item.maxScore, 10);
const scoreLabel = Number.isFinite(numericScore) && Number.isFinite(maxScore)
? `${numericScore}/${maxScore}`
: (toCleanString(item.scoreLabel, 80) || 'not scored');
const weakAreas = Array.isArray(item.weakAreas)
? item.weakAreas.map((weakArea) => {
const weakScore = weakArea && weakArea.score !== null && weakArea.score !== undefined && weakArea.score !== ''
? Number.parseInt(weakArea.score, 10)
: null;
return {
area: toCleanString(weakArea && weakArea.area, 160),
score: Number.isFinite(weakScore) ? weakScore : null,
status: toCleanString(weakArea && weakArea.status, 80) || 'review',
repair: toCleanString(weakArea && weakArea.repair, 300),
};
}).filter((weakArea) => weakArea.area).slice(0, 7)
: [];
return {
id: toCleanString(item.id, 120) || `transcript-score-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
title,
promptKey: toCleanString(item.promptKey, 80),
createdAt: toCleanString(item.createdAt, 80) || now,
scoreLabel,
numericScore: Number.isFinite(numericScore) ? numericScore : null,
maxScore: Number.isFinite(maxScore) ? maxScore : null,
status: toCleanString(item.status, 240) || 'Review score before reuse.',
state: ['ready', 'review', 'neutral'].includes(item.state) ? item.state : 'neutral',
suiteId: toCleanString(item.suiteId, 80) || 'core',
suiteLabel: toCleanString(item.suiteLabel, 160) || getPersonaLabStressPreset(item.suiteId || 'core').label,
runtimeFitLabel: toCleanString(item.runtimeFitLabel, 160) || 'Universal manual-send runtime',
engagementPatternLabel: toCleanString(item.engagementPatternLabel, 160) || 'Curiosity ladder',
frameworkLabel: toCleanString(item.frameworkLabel, 160) || 'Traits-first operational lens',
socialDynamicsLabel: toCleanString(item.socialDynamicsLabel, 160) || 'No extra social-dynamics lens',
transcriptPreview: toCleanString(item.transcriptPreview || item.transcript || '', 600),
weakAreas,
};
};
const readPersonaLabTranscriptHistory = () => {
const raw = getStorageValue(personaLabTranscriptHistoryKey, '[]');
let parsed = [];
try {
parsed = JSON.parse(raw);
} catch (error) {
parsed = [];
}