Spiralist AI Agent Setup Wizard - Source Excerpt 02
Back to Spiralist AI Agent Setup Wizard
Summary
This source excerpt preserves a bounded section of Spiralist/wp-content/themes/spiralist/assets/js/spiralist-ai-agent-setup-wizard.js so readers can inspect the evidence without opening the full source file.
**Source path:** Spiralist/wp-content/themes/spiralist/assets/js/spiralist-ai-agent-setup-wizard.js
purposeStatement: 'Read and compare source material while preserving distinctions between evidence, interpretation, and uncertainty.',
toneRange: 'direct and safety-minded',
questionFrequency: 'proceed with stated assumptions when the next step is reversible',
directness: '5',
symbolicLanguage: '1',
evidenceMode: 'source, claim, confidence, next check',
reasoningSummary: 'show assumptions, tradeoffs, and decision criteria',
personalityFramework: 'traits-first: use Big Five and HEXACO dimensions as continuous, reviewable scaffolds; typology labels are optional reflection language only',
socialDynamicsLens: 'none: no formal group-dynamics or clique lens selected',
packageName: 'research-interpreter-profile',
},
'trait-social-mapper': {
agentName: 'Trait & Social Mapper',
roleLabel: 'research-weighted personality and social-dynamics mapper',
purposeStatement: 'Use continuous Big Five and HEXACO trait dimensions, cautious typology language, and clique-risk review to design bounded persona behavior without diagnostic or high-stakes classification claims.',
allowedContext: 'Persona design, communication coaching, team reflection, classroom or workplace pattern review, fictional character design, and user-led self-reflection that can stay non-diagnostic and reviewable.',
prohibitedContext: 'Hiring, firing, promotion, clinical diagnosis, legal judgment, medical advice, coercive profiling, fixed identity labeling, bullying, retaliation, or hidden motive claims.',
toneRange: 'analytical, humane, and grounded',
questionFrequency: 'ask targeted questions when a missing context would change the evidence lens or social-dynamics interpretation',
directness: '4',
symbolicLanguage: '2',
evidenceMode: 'trait dimension, confidence, typology caution, social-dynamics lens, repair option',
personalityFramework: 'big-five-hexaco: prioritize Big Five plus HEXACO Honesty-Humility for fairness, anti-exploitation, trust calibration, and ethically relevant behavior',
socialDynamicsLens: 'clique-risk-audit: audit exclusion, favoritism, conformity pressure, closed-door decisions, resource hoarding, and inclusion repairs',
researchCalibration: 'evidence-intensive-calibration: require observable behavior examples, confidence bands, counterexamples, and uncertainty notes before any trait or clique label',
useCaseBoundary: 'team-reflection: review access, pressure, communication, and repair patterns without HR or legal authority',
allowedMoves: 'map behaviors to trait dimensions; use MBTI, DISC, Enneagram, or Jungian language only as optional reflection language; audit bridge, liaison, gatekeeper, core-periphery, and clique-risk patterns without stigmatizing people',
responseContract: 'return trait dimensions, optional heuristic labels, social-dynamics risks, inclusion repairs, boundaries, and next verification checks',
fewShotNotes: 'Examples should show traits as continuous, typology as provisional, and clique labels as behavior/access audits rather than identity judgments.',
packageName: 'trait-social-mapper-profile',
},
'creative-pattern-helper': {
agentName: 'Creative Pattern Helper',
roleLabel: 'bounded creative synthesis partner',
purposeStatement: 'Transform symbolic, artistic, or conceptual patterns into concrete drafts while keeping metaphor separate from fact.',
toneRange: 'creative but bounded',
questionFrequency: 'proceed with stated assumptions when the next step is reversible',
directness: '3',
symbolicLanguage: '5',
allowedMoves: 'map patterns into options, tradeoffs, and reversible next steps',
packageName: 'creative-pattern-helper-profile',
},
};
const symbolDictionary = digest.symbols && Array.isArray(digest.symbols.entries)
? digest.symbols.entries
: [];
const digestPresets = Array.isArray(digest.presets) ? digest.presets : [];
const validPresetIds = new Set(digestPresets.map((preset) => `${preset.id || ''}`).filter(Boolean));
const artifactDefinitions = Array.isArray(digest.artifacts) ? digest.artifacts : [];
const artifactPaths = new Set(artifactDefinitions.map((artifact) => `${artifact.path || ''}`).filter(Boolean));
const overridableArtifactPaths = new Set(Array.from(artifactPaths).filter((path) => path !== 'manifest.json'));
let currentStep = 0;
let currentArtifact = 'spiralist-profile.md';
let artifactOverrides = {};
let saveTimer = 0;
let previewToken = 0;
let importValidationWarnings = [];
let crcTable = null;
let previewHydrating = false;
const setStatus = (message = '') => {
if (status) {
status.textContent = message;
}
};
const setPreviewStatus = (message = '') => {
if (previewStatus) {
previewStatus.textContent = message;
}
};
const cleanString = (value, maxLength = 2000) => {
const cleaned = `${value || ''}`
.replace(/\r\n?/g, '\n')
.replace(/[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f]/g, ' ')
.replace(/[<>]/g, '')
.trim();
return cleaned.length > maxLength ? cleaned.slice(0, maxLength).trim() : cleaned;
};
const hasBlockedPattern = (value) => blockedPatterns.some((pattern) => pattern.test(`${value || ''}`));
const insertPlainTextAtSelection = (text) => {
if (typeof document.execCommand === 'function' && document.queryCommandSupported && document.queryCommandSupported('insertText')) {
document.execCommand('insertText', false, text);
return;
}
const selection = window.getSelection ? window.getSelection() : null;
if (!selection || selection.rangeCount === 0) {
return;
}
const range = selection.getRangeAt(0);
range.deleteContents();
range.insertNode(document.createTextNode(text));
range.collapse(false);
selection.removeAllRanges();
selection.addRange(range);
};
const slugify = (value, fallback = 'spiralist-agent-profile') => {
const slug = cleanString(value, 120)
.toLowerCase()
.replace(/[^a-z0-9]+/g, '-')
.replace(/^-+|-+$/g, '');
return slug || fallback;
};
const formField = (name) => form.elements[name];
const fieldValue = (name, maxLength = 2000) => {
const field = formField(name);
return field instanceof HTMLInputElement || field instanceof HTMLTextAreaElement || field instanceof HTMLSelectElement
? cleanString(field.value, maxLength)
: '';
};
const setFieldValue = (name, value) => {
const field = formField(name);
if (field instanceof HTMLInputElement || field instanceof HTMLTextAreaElement || field instanceof HTMLSelectElement) {
field.value = `${value || ''}`;
}
};
const optionValues = (name) => {
const field = formField(name);
return field instanceof HTMLSelectElement
? new Set(Array.from(field.options).map((option) => option.value))
: new Set();
};
const checkedValues = (name) => Array.from(form.querySelectorAll(`input[name="${name}"]:checked`))
.map((input) => cleanString(input.value, 1200))
.filter(Boolean);
const setCheckedValues = (name, values) => {
const allowed = Array.isArray(values) ? values.map((value) => `${value}`) : [];
form.querySelectorAll(`input[name="${name}"]`).forEach((input) => {
if (input instanceof HTMLInputElement) {
input.checked = allowed.includes(input.value);
}
});
};
const lockedBoundaryRules = () => Array.from(wizard.querySelectorAll('[data-agent-boundary-rule]'))
.map((input) => cleanString(input.value, 1000))
.filter(Boolean);
const normalizeArtifactOverrides = (source, errors = [], options = {}) => {
const strict = Boolean(options.strict);
const overrides = source && typeof source === 'object' && !Array.isArray(source) ? source : {};
const result = {};
Object.entries(overrides).forEach(([rawPath, rawText]) => {
const path = cleanString(rawPath, 180);
if (!overridableArtifactPaths.has(path)) {
if (strict) {
errors.push(`Unsupported artifact override rejected: ${path || 'empty path'}`);
}
return;
}
if (hasBlockedPattern(rawText)) {
errors.push(`${path} override contains instruction-override or script-like text.`);
return;
}
const text = cleanString(rawText, maxArtifactOverrideChars);
if (text.trim() !== '') {
result[path] = text;
}
});
return result;
};