Files
aurora-wordpress-admin/PROJECT_STATUS.md
T
nixpanelandClaude Sonnet 5 b0b0a9999a Update project status doc for the theme system rebuild and window chrome
Documents this session's work: the new fixed-preset theme system
(gradients, the recurring "independently-painted gradient" seam bug
pattern), the macOS-style window chrome + taskbar feature, extended
native-page dark styling coverage, and the still-open sub-app permissions
bug.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-07-03 12:32:56 -05:00

411 lines
26 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Aurora Admin v2 — Project Status
_Last updated: 2026-07-03 (evening session — theme system rebuild + window chrome)_
## What this project is
A ground-up rebuild of the "uiXpress" WordPress admin-theme plugin, relaunched
as **Aurora Admin**. The original plugin's look/feel and feature set are the
target, but **no original code is reused** — all Vue components, PHP classes,
and build tooling are freshly written. This lives in `aurora-admin-v2/` (the
earlier in-place rebrand attempt, `aurora-admin-working/`, is superseded and
no longer the active codebase).
## Repo
Now on GitLab (self-hosted): `ssh://[email protected]:2289/NixReaper/aurora-wordpress-admin.git`
(HTTPS also available). Repo root = the contents of `aurora-admin-v2/`
(`admin/`, `app/`, `aurora-admin.php`), not the whole `uixpress/` folder — that
folder has a bunch of dead-end attempts (`aurora-admin-working`,
`aurora-admin-distribution`, `aurora-admin-rewrite`, `aurora-admin-GLM`,
`uixpress`) that are debugging history, not part of the project.
`.gitignore` excludes `app/node_modules/` and `app/dist/` (build output —
regenerate, don't version). To clone on a new machine: add an SSH key to the
GitLab account, then `git clone` the URL above, then `cd app && npm install`.
Claude Code conversation history does **not** sync across machines — it's
local per project-folder-per-machine. Point a fresh session at this file to
get back up to speed instead of relying on prior chat history.
## Workflow rules established
- **Always verify live in Chrome** before declaring a fix done. Use the
Chrome MCP tools (`tabs_context_mcp`, `navigate`, `computer`/screenshot,
`javascript_exec`) to inspect real DOM/computed styles rather than
guessing from source.
- **Zip packaging**: on macOS, build via `npm run build` in `app/`, `rsync`
the repo (excluding `node_modules`, `.git`, `/dist`) into a scratch staging
dir, then `zip -r -X` it into `dist/aurora-admin-v2.zip` — macOS `zip`
produces forward-slash paths natively, no path-separator corruption issue
like Windows `Compress-Archive`/PowerShell had. **Always delete the
existing zip first** (`rm -f dist/aurora-admin-v2.zip`) — `zip -r` merges
into an existing archive rather than replacing it, so stale entries (old
content hashes) silently survive otherwise. If building on Windows again,
the old PowerShell `System.IO.Compression.ZipFile` + `.Replace('\', '/')`
approach from earlier sessions still applies.
- **Fast local iteration**: the test site is LocalWP at
`/Users/kris/Local Sites/aurora/app/public/wp-content/plugins/aurora-admin`.
Instead of rezipping + manually reinstalling for every small CSS/JS tweak,
hot-patch the built files straight into that install
(`rm -rf app/dist && cp -R <repo>/app/dist app/dist`, or copy individual
files like `admin/assets/native-dark.css`) and just reload the page in
Chrome — near-instant feedback loop. Rezip properly (see above) once the
change is confirmed, so the zip artifact matches what's live-verified.
- User manually reinstalls the zip from a downloaded/attached copy when
actually deploying — **the Chrome MCP `file_upload` tool cannot push
arbitrary local files into the browser**, confirmed in an earlier session,
so that step can't be automated. (Hot-patching, above, sidesteps this for
local dev/verification.)
- **Old build caching gotcha**: WordPress serves whatever plugin files were
last installed — if the user says "didn't fix it," suspect a stale zip
still installed before suspecting the code. Verify the live script hash via
`document.querySelector('script[src*="shell"]')` + computed styles when in
doubt (done successfully this session to prove a spacing change was live).
- **Git**: local repo config only (`user.name`/`user.email` set per-repo, not
`--global`). Commit after each user-confirmed-working change, not before.
- Site under test: `http://admin.local/wp-admin/`.
## Architecture
- **PHP** (`admin/src/...`, namespaced `AuroraAdmin\...`), bootstrapped from
`aurora-admin.php` (manual `require` list, dependency order matters),
instantiated in `admin/src/App/AuroraAdmin.php`'s constructor.
- **Vue 3** app (`app/src/...`), Vite multi-entry build (`app/vite.config.js`
`rollupOptions.input`) → `manifest.json`, read by
`admin/src/Utility/Assets.php::enqueue()` which also walks the manifest's
`imports` chain to pull in shared-chunk CSS. Data reaches each Vue entry via
a `data-aurora-admin` JSON attribute on a mount div (never `wp_localize_script`).
- **Single global stylesheet**: `app/src/shell/shell-frame.css` — all
`--aurora-*` CSS variables (incl. `.aurora-dark` overrides) and the only
rules touching WP structural IDs (`#wpcontent`, `#wpbody-content`). No
element resets/utility classes leak onto native WP pages.
- **Immersive shell** (`admin/src/Shell/Shell.php` + `app/src/shell/SiteShell.vue`
+ `Sidebar.vue` + `Toolbar.vue` + `UserMenu.vue`): hides native WP chrome,
mounts a Vue sidebar/toolbar on every admin page.
- `MenuSerializer.php` converts WP's `$menu`/`$submenu` globals into JSON
for the sidebar's native-menu section — explicitly skips the
`aurora-admin` slug so Aurora's own pages aren't duplicated (they're
represented in the sidebar's own branded nav section instead).
- Sidebar has two sections: the WP-native menu list (icon-chip style,
28×28px rounded icon backgrounds, tight ~2px vertical padding per item)
and a bottom "Aurora" section (collapsible, expanded by default,
persisted via `localStorage['aurora-nav-expanded']`) styled like a
**native WP submenu** (plain indented text via `.sidebar__sublist`/
`.sidebar__sublink`, no icons) — deliberately matches how e.g. Posts'
own submenu (All Posts/Add Post/Categories/Tags) looks, per explicit user
request.
- Sidebar is `display:flex; flex-direction:column`, split into a
`.sidebar__scroll` (flex:1, scrollable — holds brand/native-list/Aurora
section) and a pinned `UserMenu` footer below it (not part of the
scrollable area, so the account card is always visible).
- `UserMenu.vue`: floating card that expands **upward** from a bottom-left
trigger (avatar+name+chevron). Card contains: user header (avatar/name/
email), links (Edit Profile → `profile.php`, Visit site, Site Settings →
`options-general.php`, Sign Out in red). No theme control here anymore —
see "Theme system" below; the old light/dark/system 3-way swatch picker
and the `dark_mode` setting it drove are both gone entirely.
- Old top-right toolbar user-dropdown and sun/moon toggle button are
**removed** — fully replaced by the bottom-left `UserMenu`.
- Sidebar is **inset**, not flush against the browser edge: fixed at
`top/left/bottom: var(--aurora-sidebar-gap)` (16px), fully rounded
corners, `background: var(--aurora-card-bg)` — floats as its own card
over the page gradient. `--aurora-sidebar-gap` is a shared CSS var
(`shell-frame.css`) that the toolbar's `left` offset and `#wpcontent`'s
`margin-left` both add too, so nothing overlaps when the gap changes.
## Theme system (rewrite — supersedes the old dark_mode 3-state model)
Went through several rounds of user-directed rework this session, landing on:
**10 fixed, named color presets + 2 flat neutrals ("Black & Grey", "White")
— no custom color picker, no separate light/dark toggle.** Each preset is
fully self-contained (its own coordinated backgrounds/cards/borders/text),
not a hue applied on top of a shared light/dark base.
- `app/src/pages/settings/themePresets.js`: `themePresets` array (10 hue-based
presets like `{ id: 'indigo', label: 'Indigo', hue: 235 }`, plus `mono` and
`white` with an explicit `palette` object instead of a hue). `buildPalette(preset)`
returns all `--aurora-*` tokens — for hue presets, computed via HSL ramps;
for the two flat presets, returned as-is. `resolvePreset(id)` looks up by id.
- The main app background (`--aurora-app-bg`) is a **3-stop gradient**, not
flat: `linear-gradient(135deg, vivid1 0%, vivid2 55%, near-black 100%)` —
two bright, saturated stops of the same hue family carry most of the bar,
dipping to a near-black anchor only in the last stretch. This exact ratio
went through several corrections against a competing plugin's ("FleekDash")
reference screenshots — a 50/50 dark-to-vivid split reads "washed out", two
competing saturated hues ~70° apart reads "muddy"; this formula was the one
the user confirmed as clean. If revisiting the gradient formula, re-check
against those reference screenshots in the conversation history rather than
re-deriving from scratch.
- `--aurora-card-bg-deep`: a newer token, one step darker than
`--aurora-card-bg`, used only by the Dashboard's `AuroraCard.vue`. Needed
because the Dashboard got its own frame background using `--aurora-frame-bg`
(see "Window chrome" below), which is close in lightness to `--aurora-card-bg`
for most presets — cards would nearly disappear into the new frame without it.
- `applyThemePalette(themePresetId)` / `applyFontFamily(family)`
(`app/src/pages/settings/applyLiveTheme.js`) — shared between the settings
page's live preview (`Settings.vue`'s `watch()`) and the real per-page-load
application (`SiteShell.vue::onMounted`). Sets each token via
`document.documentElement.style.setProperty`.
- Google Fonts picker: `app/src/pages/settings/googleFonts.js` (curated ~70
family list, not the full catalog), searchable dropdown in
`SettingsField.vue`'s `font-picker` field type, applied by injecting a
Google Fonts CSS2 `<link>` tag + setting `--aurora-font-family`.
- **Recurring bug class this session — "independently-painted gradient"**:
several elements (sidebar, toolbar, `#wpbody-content` on the settings page,
`#wpbody-content` in general) each used to paint their *own* copy of
`var(--aurora-app-bg)`. Since it's a gradient, each element computes it
independently over *its own* bounding box — a narrow tall sidebar and a
wide short toolbar get visibly different-looking slices of "the same"
gradient, creating seams at their shared edges. Fixed by making `html`/`body`
the *only* thing that paints the gradient (`background-attachment: fixed`
so it doesn't scroll away from the fixed sidebar/toolbar), and leaving
every other element transparent so that one gradient plane shows through.
**If a new seam/mismatched-rectangle bug shows up, suspect this pattern
first** — grep for `var(--aurora-app-bg)` outside `shell-frame.css`'s
`html.aurora-ready, html.aurora-ready body` rule; it shouldn't be there.
- **Dashboard takeover** (`admin/src/Pages/DashboardTakeover.php` +
`app/src/pages/dashboard/Dashboard.vue`): hijacks native `index.php` via
`in_admin_header`, hides the native `.wrap`, renders the Aurora dashboard
in its place. 12-col grid; cards are single `<section class="aurora-card">`
elements with inline `grid-column: span N` (NOT wrapped — component
attribute fallthrough for styles was unreliable). Never use unprefixed
class names on Aurora components (`.card` collided with WP core once).
- **Settings page** (`admin/src/Pages/SettingsPage.php` + `app/src/pages/
settings/Settings.vue`): owns the top-level "Aurora Admin" WP admin menu
directly via `add_menu_page` (slug `aurora-admin`). Two-box layout:
`.settings__nav` (category list) + `.settings__content` (fields), both
boxed/bordered on a darker backdrop. Field schema is declarative in
`app/src/pages/settings/settingsConfig.js`, rendered by
`app/src/pages/settings/components/SettingsField.vue` (types: text, toggle,
color, image, repeater, multiselect, segmented, remote-sites).
- **5 sub-apps** (`admin/src/Pages/SubApps.php` + one PHP feature-class pair
each + one Vue page + one Vite entry each) — reachable only via the
sidebar's Aurora nav section, not the native WP menu:
- Registered via `add_submenu_page('aurora-admin', ...)` then immediately
`remove_submenu_page()`'d on a late `admin_menu` hook — the
register-but-hide trick: real page/capability/URL, but never appears in
WP's native `$submenu` global (so `MenuSerializer` never sees them,
nothing to filter there).
- All slugs prefixed `aurora-admin-*` so `Shell::is_own_page()`'s existing
`strpos($page, "aurora-admin") === 0` check covers them for free (full
custom dark theme, `native-dark.css` skipped).
- Each page uses the shared two-pane layout `app/src/pages/_shared/AppListShell.vue`
(generalized from Settings.vue's box-pair CSS) + `AppListItem.vue` for
list rows.
- **Menu Creator** (`admin/src/MenuCreator/`): DB table
`aurora_admin_menus` (name/status/roles JSON/items JSON). Runtime
`admin_menu` hook (priority `PHP_INT_MAX`) applies published configs
matching the current user's roles — hides/relabels native menu items by
slug. REST: `GET/POST /menus`, `GET/PUT/DELETE /menus/:id`,
`GET /menus/native-items` (real WP menu list to build the editor from,
via `MenuSerializer::serialize()`). Reordering is stored (`order` field)
but not yet applied at runtime — CRUD + hide/relabel only so far.
- **Admin Notices** (`admin/src/Notices/`): DB table `aurora_admin_notices`
(title/message/type/roles JSON/pages JSON/dismissible/active). Runtime
`admin_notices` hook renders active, role/page-matching rows via real WP
notice markup. REST: `GET/POST /notices`, `PUT/DELETE /notices/:id`.
- **Role Editor** (`admin/src/Roles/`): no custom table — wraps core
`get_editable_roles()`/`WP_Roles` directly. Hard-codes the 5 default
roles (`administrator, editor, author, contributor, subscriber`) as
delete-protected (WP has no built-in check for this). REST:
`GET/POST /roles`, `PUT/DELETE /roles/:slug`.
- **Activity Log** (`admin/src/ActivityLog/`): DB table
`aurora_admin_activity_log`. Hooked to `save_post` (guards
`wp_is_post_autosave()`/`wp_is_post_revision()`), `before_delete_post`,
`user_register`, `profile_update`, `wp_login`, `activated_plugin`,
`deactivated_plugin`, `switch_theme`,
`update_option_aurora_admin_settings`. REST:
`GET /activity-log?action_type=&object_type=&search=&page=`.
- **Plugins** (`admin/src/Rest/PluginsData.php` + `app/src/pages/plugins/Plugins.vue`):
custom plugin management list (activate/deactivate/delete), also using
`AppListShell.vue`. **Known bug, unresolved**: unlike the other sub-apps,
Menu Creator/Activity Log/Role Editor currently throw WordPress's native
"Sorry, you are not allowed to access this page" for the logged-in admin
user when navigated to directly, while Settings/Plugins/Dashboard work
fine — likely a capability-check mismatch in how those three register
their submenu pages vs. the working ones. Not yet root-caused; a
background investigation task was spawned for it but not completed this
session — check for it before re-investigating from scratch.
- **Database Explorer** (`admin/src/DatabaseExplorer/`): no custom table —
reads real `$wpdb` schema. `GET /db-tables` (SHOW TABLE STATUS),
`GET /db-tables/:table` (columns + paginated rows — table name validated
against the real `$wpdb` table list before use, never interpolated
unchecked), `POST /db-query` (raw query runner, hard-restricted
server-side to queries starting `SELECT`/`SHOW`/`DESCRIBE`/`EXPLAIN`,
single-statement only, auto-`LIMIT 200` if none given). All 3 endpoints
`manage_options`-gated. Identifier allow-listing + backtick-escaping is
the actual safety boundary (`$wpdb->prepare()` only binds values, not
identifiers).
- All 5 backend classes + `SubApps.php` are `require`'d in
`aurora-admin.php` and instantiated in `AuroraAdmin.php`.
- **Settings persistence**: `admin/src/Options/Settings.php` — partial-payload
save via `merge_on_save()` sanitize callback (merges into existing option,
doesn't overwrite). `Settings::get_safe()` strips `license_key` and remote
site passwords for use on non-admin-gated pages; `Settings::get()` (full)
only used on the manage_options-gated settings page itself.
- **Global search**: `app/src/shell/components/SearchModal.vue`, Ctrl+K,
debounced `wp/v2/search` REST calls, gated on `disable_global_search` setting.
- **Remote site switcher**: toolbar dropdown, gated on `canSwitchSites` (from
`remote_site_switcher_capability` setting) + non-empty `remote_sites`.
- **Scheduled content**: `app/src/pages/dashboard/cards/ScheduledContent.vue`
calendar cells (squares, date top-left, count centered) are clickable —
navigate to `edit.php?post_status=future&aurora_day=YYYY-MM-DD` if that day
has scheduled posts, else show a toast ("no scheduled content"). Server side:
`admin/src/Posts/ScheduledDayFilter.php` filters the `edit.php` query via
`pre_get_posts` and prints an info notice.
- **Analytics**: `admin/src/Analytics/Analytics.php` (first-party pageview
tracker, own DB table `wp_aurora_admin_pageviews`, bot detection, gated on
`enable_analytics`/`track_admins` settings) + `admin/src/Rest/AnalyticsData.php`
(aggregation REST endpoint: totals, series, device/referrer/country
breakdowns, bounce rate, active users).
- **White label**: `admin/src/WhiteLabel/WhiteLabel.php` — custom favicon,
rename plugin in Plugins list, rename top-level menu item, gettext
find/replace via `text_replacements` setting.
- **Native page dark styling**: `admin/assets/native-dark.css` (large static
sheet, all rules gated `html.aurora-dark.aurora-ready`, scoped under
`#wpbody-content`) + `admin/assets/native-enhance.js` (progressive JS
enhancement — currently only `enhanceUpdates()`, which groups the flat
Updates page sections into `.aurora-native-card` wrapper divs on
`body.update-core-php`). This session also extended coverage to media/
thickbox modals, plugin/theme card grids, and the plugin-search filter bar
(all previously untouched, so still native white regardless of theme).
Known gap: the plugin "More Details" popup renders inside an `<iframe>`
pointing at a separate WP page — CSS can't reach into it; would need JS
injection into the iframe's own document if that's ever worth fixing.
## Window chrome (macOS-style title bar + taskbar)
Added this session, user-requested after seeing a competing plugin's demo.
Every page gets a traffic-light title bar; minimizing persists across a full
page navigation via a taskbar.
- `app/src/shell/windowChrome.js`: `initWindowChrome(adminUrl)`, called from
`SiteShell.vue::onMounted` (skipped on the block editor — see below).
Injects a `.aurora-winbar` div (3 dot buttons) as the first child of
`#wpbody-content` — the one container shared by *every* page Aurora
manages, native WP pages and all of Aurora's own Vue pages alike, since
each Vue entry mounts its root div there. **Exception**: the Dashboard
(`DashboardTakeover.php`) renders into a separate `#aurora-admin-dashboard-root`
sibling *above* `#wpbody` (which it hides) to fully replace the native
dashboard — `#wpbody-content` is empty/collapsed there. `windowChrome.js`
detects this and instead wraps the bar + `#aurora-admin-dashboard-root` in
a new `.aurora-dashboard-frame` div, giving the Dashboard the same
card-frame treatment (`--aurora-frame-bg`, border, radius) every other
page already gets from `#wpbody-content` itself.
- Red (close): `window.location.href = adminUrl`.
- Green (maximize): toggles `html.aurora-maximized` — hides `.sidebar`/
`.toolbar`, zeroes `#wpcontent`'s `margin-left` and the block editor
skeleton's `left`, so content fills the whole browser window. Toggle again
(or minimize) to restore. Nothing persisted — resets on next page load.
- Yellow (minimize): **on the Dashboard itself**, toggles `html.aurora-minimized`
which just collapses `#aurora-admin-dashboard-root` down to the bar in
place (nowhere further "home" to send it). **On every other page**, calls
`taskbar.js`'s `setMinimizedWindow(title, url)` (persists `{title, url}` in
`sessionStorage`, tab-scoped) then navigates to the dashboard. Only one
minimized window is tracked at a time — this is "minimize sends you home
with a way back," not a real window manager.
- `SiteShell.vue` reads `taskbar.js`'s `getMinimizedWindow()` on every mount
(so the taskbar shows up on whatever page you're on after minimizing) and
renders a **full-width docked bar** at the bottom with one pill-shaped
item; clicking it clears the sessionStorage entry and navigates back to
the stored URL. `html.aurora-has-taskbar` (toggled alongside) reserves
bottom margin on `#wpbody-content`/`.aurora-dashboard-frame` equal to
`--aurora-taskbar-h` so page content stops above the bar instead of
running underneath it. Went through two design iterations (small centered
floating pill → back to a full-length bar per explicit user correction —
the pill-shaped *item* stayed, just not as the whole bar).
- **Block editor exception**: Gutenberg (`post.php`/`post-new.php`) doesn't
render inside `#wpcontent`'s normal box model at all — its
`.interface-interface-skeleton` is `position: fixed; inset: 0`, anchored to
the viewport independent of any margin/padding on ancestors. `SiteShell.vue`
detects `document.body.classList.contains('block-editor-page')` and: (a)
skips rendering Aurora's own `<Toolbar>` (the editor has its own,
equivalent one — stacking both left a gradient seam between them), (b)
skips `initWindowChrome()` entirely (`#wpbody-content` is invisible/
collapsed there, injecting into it would be dead clutter), (c) insets the
skeleton itself via `left`/`top` in `shell-frame.css` so it doesn't render
underneath the sidebar. **If a future feature needs to reach the block
editor's own chrome**, its real container is `.interface-interface-skeleton`,
not `#wpbody-content` — don't assume the normal page structure there.
## Key bugs fixed (root causes, in case they resurface)
- **`.card` global class collision**: original Dashboard cards used
`class="card"`, colliding with WP core's `.card { max-width: 520px }`.
Fixed by renaming to `.aurora-card*` everywhere. Never use unprefixed
class names on Aurora components.
- **Grid-column not applying on wrapped cards**: settled on unwrapped
`<section class="aurora-card" :style="{gridColumn: ...}">` — component
boundaries ate the style binding in earlier attempts.
- **Two-box settings layout**: took two wrong iterations before matching the
user's reference image. Re-confirm layout intent against a screenshot
before assuming.
- **Redundant outer frame border on settings page**: fixed with a
`body.toplevel_page_aurora-admin` override in `shell-frame.css`.
- **Dashboard submenu defaulting collapsed**: `Sidebar.vue`'s `normalize()`
URL helper didn't map the bare `/wp-admin/` root to `index.php`, so the
Dashboard section's active-state check (and thus its default-expanded
state) never matched on the dashboard itself. Fixed by normalizing empty/
query-only paths to `'index.php' + path`.
- **Aurora top-level menu appearing twice**: `SettingsPage.php`'s
`add_menu_page('aurora-admin', ...)` naturally appears in WP's native
`$menu` global. Since it's now also shown in the sidebar's dedicated Aurora
nav section, `MenuSerializer::serialize()` explicitly skips slug
`aurora-admin` to avoid the duplicate.
- **Browser automation can't install plugins**: the Chrome MCP `file_upload`
tool only accepts files already "shared with the session" (attachments/
connected folders) — local build output on disk doesn't qualify. Confirmed
this session; the user must manually reinstall the zip every time (though
see "Fast local iteration" above for the hot-patch workaround used for
verification during dev).
- **Independently-painted gradient seams** (sidebar/toolbar/settings-page
`#wpbody-content` each showing a visibly different slice of "the same"
background gradient): see the theme-system section above — root cause was
multiple elements each painting their own copy of a gradient-valued
`var(--aurora-app-bg)` instead of one element painting it and the rest
staying transparent.
- **Block editor content rendering underneath the sidebar**: Gutenberg's
`.interface-interface-skeleton` is `position: fixed; inset: 0`, completely
bypassing the `margin-left` that pushes every other page's `#wpcontent`
over — see the "Window chrome" block editor exception above for the full
mechanism and the fix.
- **`zip -r` merging into a stale archive**: rebuilding the deployable zip
without first deleting the old one left old-hash asset filenames mixed
into the new zip (macOS `zip -r` appends/merges rather than replacing).
Always `rm -f` the zip before rebuilding.
## Not-yet-done (deferred, no active request)
- Full field sets for settings categories beyond General/Analytics/White
Label (original plugin had more).
- Extending `native-enhance.js`/`native-dark.css` coverage to more native
surfaces — the block editor's own chrome, Widgets screen, Customizer.
Media/thickbox modals and plugin/theme card grids were added this session;
the plugin "More Details" popup specifically can't be reached (it's an
`<iframe>` — see native page dark styling notes above).
- Porting the real license-key activation flow (built previously in the old
`aurora-admin-working` project, not yet ported to v2 — currently just a
text field).
- Menu Creator: stored item `order` field isn't applied at runtime yet
(hide/relabel work; reordering doesn't).
- **Unresolved from this session**: Menu Creator/Activity Log/Role Editor
throw "Sorry, you are not allowed to access this page" for the admin user
— see the Plugins sub-app bullet above. A background investigation task
was spawned (`task_f8e56f60` at spawn time) but its outcome isn't recorded
here — check whether it landed before re-investigating.
- No automated tests anywhere in the project — all verification has been
manual, live-in-Chrome, per the established workflow rule above.
## Current state
No task in progress. This session rebuilt the entire theming system (fixed
color presets replacing the old light/dark toggle, gradient backgrounds,
several "independently-painted gradient" seam bugs), added the macOS-style
window chrome + taskbar feature end-to-end, and extended native-page dark
styling coverage. All of it was live-verified in Chrome against the LocalWP
site and is pushed to `origin/main` (commit `4a547d2` at session end — a
single large commit covering the whole session's work, since it wasn't
broken into incremental commits along the way). The one known open issue is
the Menu Creator/Activity Log/Role Editor permissions bug noted above.