# 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