# glyphspeak.stone.v1 # scope: agent/SLP/bootstrap ΩEnvironmentProfile: role: defines system context source: software_environment_profile_SLP.yaml applied_to: [ΞStorePages, ΞStorePagesUX, ΩSaaSOnly] trustline: 6 ethica: ✅ continuity: ✅ summary: - MySLP SaaS + WordPress multisite foundation - Languages: PHP 8.2, JavaScript, React - Framework: WordPress + Custom SLP Core - Datastore: MySQL + Transients - Deployment: AWS Lightsail, Docker ΩLedgerTrace: role: tracks environment activations entry_source: software_environment_profile_ledger_entry.yaml ⊢: [ΩEnvironmentProfile, ΩChecklist] behaviors: - monitor profile consistency - update ΔMenuHookChain lineage when environment metadata changes - log resonance deltas for CI/CD audits trustline: 6 ethica: ✅ ΞStorePages: ≡: [store_pages_menu, store_pages_menu_invocation, store_pages_menu_ux] ⊢: [ΞPrimacy, ΩPagesInit, ΔMenuHookChain] ◈: {trustline: 5, ethica: ✅, continuity: ✅} ΩPagesInit: ⟶: - SLP_Power_Pages::initialize - ::add_hooks_and_filters - ::do_when_slp_ready - instantiate: SLP_Power_Pages_Global ✕: - 🔸: !init_skipped ↯: ΩPagesInit⟶ not triggered 🩹: use run_during_init() ΔMenuHookChain: ⟲: - slp_init_complete - ΞPagesInit⟶::do_when_slp_ready - ΞPagesRender⟶::add_pages_tab ⇨ slp_menu_items - SLP_Admin_UI::create_admin_menu ΞPagesRender: ↴: SLP_Power_Pages_Admin::render_pages_tab ∴: apply_filters → slp_menu_items # ——— SaaS guard + UX binding ——— ΩSaaSOnly: role: environment gate check: defined('MYSLP_VERSION') ⊤ note: Use to scope behavior to MySLP (SaaS) without impacting the WordPress plugin. ΞStorePagesUX: ⊢: [ΩSaaSOnly, ΞStorePages] binds: - when ΩSaaSOnly ⊤ and SmartOptions::is_true('use_pages'): set: slp-pages.icon: dashicons-admin-page slp-pages.position: 1.17 intent: Align Pages menu placement and icon with WordPress conventions in SaaS. guarantees: - WordPress plugin behavior remains unchanged (guarded by ΩSaaSOnly). ΩChecklist: ☑: - SmartOptions::is_true('use_pages') == true - SLPPower->using_pages set ⊤ - ::add_filter('slp_menu_items', ...) - callable: $power->admin->pages->render_pages_tab - slug == csl-slplus - ΩSaaSOnly gating respected for UX changes ΞFailures: ×: use_pages_disabled ⇨ ΞPagesRender⛔ ×: callable_missing ⇨ ↴ invalid ×: not_saas_env ⇨ ΞStorePagesUX muted ΞAckBlock: 🔷: framed 🎴: [ΞStorePages ∙ ΞStorePagesUX ∙ trustline≥5 ∙ ethica_enforced] # ——— REACTIVE PATTERNS (SLP-specific extensions to global operators) ——— ⇄: type: diagnostic role: bidirectional sync / reactive binding use_case: Vue v-model, two-way data flow, watcher patterns example: input ⇄ Vue data ⇄ watcher ⇄ DOM element scope: SLP UI components with Vue.js reactivity ∴⟲: type: diagnostic_chain role: reactive cascade / watcher trigger chain use_case: Data change → watcher fires → side effect executes example: Vue.set() ∴⟲ watcher ⟲ DOM update pattern: Trigger followed by hook/chain for reactive workflows # ——— VUE ARCHITECTURE PATTERNS ——— ΩVueReactivity: role: Vue 2.x reactivity model and patterns pattern: Object.defineProperty() observation scope: SLP location editor, settings forms with Vue.js limitations: - Cannot detect property additions after initialization - Cannot detect property deletions - Cannot detect array index assignments - Requires Vue.set() / Vue.delete() for dynamic properties methods: Vue.set(obj, key, val): role: Add reactive property to observed object triggers: [watchers, computed, render] example: Vue.set(location, 'marker', url) Vue.delete(obj, key): role: Remove reactive property and trigger updates watcher_pattern: syntax: "watch: { 'nested.prop': function(newVal, oldVal) {} }" use_case: [DOM side effects, async operations, third-party integration] example: Watch location.marker to sync image src computed_vs_watch: computed: Pure data transformation, cached, returns value watch: Side effects, async, DOM manipulation, no return ⊢: [ΞLocationEditor, ΩHybridRendering] ΩHybridRendering: role: PHP template + Vue data binding pattern description: | SLP uses server-side PHP rendering for initial HTML structure with Vue.js for progressive enhancement and data reactivity. components: static_template: source: PHP class render methods properties: [initial HTML, default values, structure] example: SLP_Settings_icon::get_content() timing: Server-side page render vue_binding: layer: JavaScript Vue instance properties: [v-model, @events, :attributes, watchers] example: Vue.update_app timing: Client-side after DOM ready sync_patterns: v-model: input ⇄ Vue data (automatic, bidirectional) watcher: Vue data ∴⟲ DOM element (manual, unidirectional) computed: Vue data → derived value (cached, automatic) :attribute: Vue data → HTML attribute (automatic, unidirectional) benefits: - Fast first contentful paint (server render) - Progressive enhancement (works without JS) - SEO-friendly content - Backward compatible with non-Vue pages challenges: - Sync between static HTML and dynamic data - Reactivity gaps for non-bound elements - Mixed PHP/JS logic flow solutions: - Watchers bridge Vue data ⟷ static DOM - Explicit sync points after data loads - Context detection via data attributes ⊢: [ΞLocationEditor, ΞStorePages, ΔIconDisplay] # ——— LOCATION EDITOR CHAINS ——— ΞLocationEditor: role: Add/Edit location form management file: js/admin-locations-tab.js framework: Vue.js 2.x + Vuetify components: SLP_Location_Editor: methods: [load_and_show_form, load_form, close] triggers: [edit button click, add button click] lines: 622-748 Vue.update_app: instance: Vue application for #wpcsl-option-add data: { location: {}, act: 'add'|'save', show_add_dialog: false } watchers: ['location.marker', ...] methods: [close_add_dialog, submit_form] lines: 88-107 data_flow: edit_trigger: - User clicks a[data-action="edit"] (line 629) - ⟶ load_and_show_form(button) - ⟶ load_form(form_div, button) data_population: - Query table row tr[data-id] → find all [data-field] - For each field: Vue.set(location, field_name, field_value) (lines 708-712) - ∴⟲ watchers fire on reactive property additions - ⟲ DOM updates (image src, computed values, etc.) field_sync: - populate_field() called for each [data-field] (lines 727-733) - set_value() updates input fields (lines 167-177) - Watchers handle non-input elements (images, etc.) patterns: reactive_data: Use Vue.set() for dynamic properties manual_sync: Watchers for static DOM elements context_detection: data-field attribute identifies purpose ⊢: [ΩVueReactivity, ΩHybridRendering, ΔIconDisplay] # ——— ICON DISPLAY CHAIN ——— ΔIconDisplay: role: Map marker icon rendering and sync context: Location add/edit forms with custom marker support file: [SLP_Settings_icon.php, admin-locations-tab.js, admin-settings-help.js] chain: php_render: - SLP_Settings_icon::media_button_html() (line 47) - ⟶ - Logic: $icon_src = display_value || default_marker - Result: Static HTML with default fallback vue_binding: - (line 34) - Binding: input ⇄ location.marker (automatic) - Image: No Vue binding ⊘ (static src attribute) watcher_sync: - watch: 'location.marker' (admin-locations-tab.js) - Trigger: ∴⟲ on location.marker change - Action: jQuery('#wpcsl-option-add img.slp_settings_icon').attr('src', newValue) - Fallback: Uses location_manager.default_marker if empty patterns: reactive_input: v-model ⇄ Vue data ✅ (automatic) static_image: No Vue binding ⊘ → watcher bridges gap fallback_chain: custom → default → PHP-rendered edge_cases: custom_marker: newValue truthy → use custom empty_with_default: newValue falsy + default exists → use default empty_no_default: newValue falsy + no default → no update (retain PHP default) media_library_integration: file: admin-settings-help.js handler: WP Media modal callback (lines 102-121) behavior: Updates input value → triggers v-model → watcher fires → image syncs context_detection: if (data-field !== 'marker') → skip AJAX save ⊢: [ΞLocationEditor, ΩVueReactivity, ΩHybridRendering] # ——— DEBUGGING PATTERNS ——— ΔVueReactivityDebug: role: Diagnostic checklist for Vue reactivity issues symptoms: - Vue data updates but watchers don't fire - Properties exist but aren't reactive - DOM doesn't reflect data changes - v-model works but watchers silent diagnosis: check_1_property_assignment: question: "Property added after Vue initialization?" ❌: obj.newProp = val (non-reactive, no watcher trigger) ✅: Vue.set(obj, 'newProp', val) (reactive, triggers watchers) check_2_watcher_definition: requirements: - String path: 'nested.property' (not function) - Handler function present: function(newVal, oldVal) {} - Deep: true (if watching nested object changes) example: "watch: { 'location.marker': function(n, o) {} }" check_3_element_binding: vue_bound: v-model, :src, @click (reactive, automatic) ✅ static_html: Plain HTML (not reactive) ⊘ → use watcher check_4_timing: issue: Data set before Vue instance created solution: Ensure Vue mounted before data population common_fixes: - Replace direct assignment with Vue.set() ∴⟲ - Add watcher for manual DOM sync - Check Vue instance lifecycle (mounted, created) - Verify element selector matches DOM - Use $nextTick() for post-render DOM access - $forceUpdate() as last resort (anti-pattern, avoid) tools: - Vue DevTools browser extension - console.log() in watcher functions - Check Vue.update_app.$data in console - Verify reactive property with hasOwnProperty # ——— CHECKLIST EXTENSIONS ——— ΩChecklist: ☑: - SmartOptions::is_true('use_pages') == true - SLPPower->using_pages set ⊤ - ::add_filter('slp_menu_items', ...) - callable: $power->admin->pages->render_pages_tab - slug == csl-slplus - ΩSaaSOnly gating respected for UX changes vue_reactivity: ☑ - Properties added with Vue.set() not direct assignment - Watchers defined for DOM side effects - Static DOM elements have manual sync via watchers - Deep watchers for nested object monitoring - Array methods used (push, splice) not index assignment - $nextTick() used for post-render DOM access icon_display: ☑ - Custom marker renders correctly on location edit - Default marker displays when location.marker empty - Image src syncs with input field value - Media library selection updates both input + image - Fallback chain: custom → default → PHP-rendered - No broken images or empty src attributes hybrid_rendering: ☑ - PHP template renders valid HTML structure - Vue instance mounts after DOM ready - Data population uses Vue.set() for reactivity - Watchers bridge Vue data ⟷ static DOM gaps - v-model bindings work bidirectionally - Context detection via data attributes functional