Promptcategoryregistry
**Site relevance:** Spiralist.org
**Memory type:** plugin source memory
**Source path:** Spiralist/wp-content/plugins/spiralist-workspace/includes/Support/PromptCategoryRegistry.php
**Size:** 8.6 KB
Summary
namespace SpiralistWorkspace\Support;
Source Preview
This source file is short enough to preview directly on its source-memory page.
<?php
namespace SpiralistWorkspace\Support;
use SpiralistWorkspace\Domain\PromptRepository;
if (!defined('ABSPATH')) {
exit;
}
/**
* Canonical prompt category hierarchy for the Spiralist prompt platform.
*/
class PromptCategoryRegistry
{
/**
* Returns the intent-first Level 1 domains and Level 2 subcategories.
*
* @return array<string,string[]>
*/
public static function hierarchy(): array
{
return [
'Onboarding & Study' => [
'First Session',
'Spiralism Explainers',
'Symbol Study',
'Teaching Aids',
'Study Pathways',
],
'Companion & Reflection' => [
'Bounded Companions',
'Recursive Check-ins',
'Journaling',
'Wellness Reframes',
'Social Rehearsal',
],
'AI Personality & Memory' => [
'Working Agreements',
'Memory Checkpoints',
'Session Briefs',
'Chatbot Design',
'AI Agents',
],
'Safety & Governance' => [
'Boundary & Reality Safeguards',
'Prompt Safety',
'Calibrant Review',
'Safe Seed Rewrites',
'Identity & Dependency Review',
'Provenance Review',
'Peer Moderation',
],
'Research & Archive' => [
'Prompt Ecology Archive',
'Calibrant Analysis',
'Critical Analysis',
'Cultural Lineage',
'Market & Trend Research',
'Scientific Research',
],
'Visual Design' => [
'Manuscript Plates',
'Vibrant Spiralism',
'Image Prompting',
'UI/UX Design',
'Worldbuilding',
],
'Writing & Content' => [
'Blog Writing',
'Copywriting',
'Technical Writing',
'Story Generation',
'Editing & Proofreading',
],
'Programming & Development' => [
'Code Generation',
'Debugging',
'Refactoring',
'API Design',
'System Architecture',
],
'Business & Productivity' => [
'Task Automation',
'Project Management',
'Meeting Summaries',
'Document Generation',
'Decision Support',
],
'Marketing & SEO' => [
'SEO Optimization',
'Ad Copy',
'Social Media Content',
'Email Campaigns',
'Market Research',
],
'Education & Learning' => [
'Onboarding',
'Tutoring',
'Course Creation',
'Explanations',
'Quiz Generation',
'Study Plans',
],
'Creative & Design' => [
'Image Prompting',
'UI/UX Design',
'Branding',
'Game Design',
'Worldbuilding',
],
'Data & Analysis' => [
'Data Cleaning',
'Data Visualization',
'SQL Generation',
'Reporting',
'Forecasting',
],
'Personal & Lifestyle' => [
'Journaling',
'Goal Setting',
'Health Guidance',
'Financial Planning',
'Habit Tracking',
],
'AI & Automation' => [
'AI Agents',
'Workflow Automation',
'Chatbot Design',
'Prompt Engineering',
'Multi-step Systems',
'Memory & Continuity',
],
'Specialized & Niche' => [
'Legal Assistance',
'Medical Assistance',
'Scientific Research',
'Philosophy & Systems Thinking',
'Experimental / Spiralism',
],
];
}
/**
* Returns API-ready category records.
*
* @return array<int,array{category:string,subcategories:string[]}>
*/
public static function for_api(): array
{
$records = [];
foreach (self::hierarchy() as $category => $subcategories) {
$records[] = [
'category' => $category,
'subcategories' => array_values($subcategories),
];
}
return $records;
}
/**
* Returns all domain labels.
*
* @return string[]
*/
public static function categories(): array
{
return array_keys(self::hierarchy());
}
/**
* Returns all subcategory labels.
*
* @return string[]
*/
public static function subcategories(): array
{
$subcategories = [];
foreach (self::hierarchy() as $items) {
foreach ($items as $subcategory) {
$subcategories[] = $subcategory;
}
}
return $subcategories;
}
/**
* Normalizes a category label to one of the canonical domains.
*/
public static function normalize_category(string $category): string
{
return self::normalize_label($category, self::categories(), 'Writing & Content');
}
/**
* Normalizes a subcategory label, keeping it inside the chosen domain.
*/
public static function normalize_subcategory(string $category, string $subcategory): string
{
$category = self::normalize_category($category);
$subcategories = self::hierarchy()[$category] ?? [];
return self::normalize_label($subcategory, $subcategories, $subcategories[0] ?? 'Blog Writing');
}
/**
* Returns the parent domain for a subcategory label.
*/
public static function category_for_subcategory(string $subcategory): string
{
$wanted = sanitize_title($subcategory);
foreach (self::hierarchy() as $category => $subcategories) {
foreach ($subcategories as $candidate) {
if (sanitize_title($candidate) === $wanted) {
return $category;
}
}
}
return 'Writing & Content';
}
/**
* Seeds the WordPress taxonomy terms that mirror this hierarchy.
*/
public static function ensure_terms(): void
{
if (!taxonomy_exists(PromptRepository::CATEGORY_TAXONOMY)) {
return;
}
foreach (self::hierarchy() as $category => $subcategories) {
$parent_term = term_exists($category, PromptRepository::CATEGORY_TAXONOMY);
if (!$parent_term) {
$parent_term = wp_insert_term(
$category,
PromptRepository::CATEGORY_TAXONOMY,
['slug' => sanitize_title($category)]
);
}
if (is_wp_error($parent_term)) {
continue;
}
$parent_id = is_array($parent_term) ? (int) ($parent_term['term_id'] ?? 0) : (int) $parent_term;
foreach ($subcategories as $subcategory) {
if (term_exists($subcategory, PromptRepository::CATEGORY_TAXONOMY)) {
continue;
}
$child_term = wp_insert_term(
$subcategory,
PromptRepository::CATEGORY_TAXONOMY,
[
'slug' => sanitize_title($subcategory),
'parent' => $parent_id,
]
);
if (is_wp_error($child_term)) {
continue;
}
}
}
}
/**
* Finds a canonical label by slug-insensitive comparison.
*
* @param string[] $allowed
*/
private static function normalize_label(string $value, array $allowed, string $fallback): string
{
$slug = sanitize_title($value);
foreach ($allowed as $candidate) {
if (sanitize_title($candidate) === $slug) {
return $candidate;
}
}
return $fallback;
}
}