diff --git a/docs/USX_SURFACE_BASELINE_SPEC.md b/docs/USX_SURFACE_BASELINE_SPEC.md index 8774b688..47eb39ee 100644 --- a/docs/USX_SURFACE_BASELINE_SPEC.md +++ b/docs/USX_SURFACE_BASELINE_SPEC.md @@ -140,7 +140,14 @@ Form and action controls should use: - Use only var(--usx-color-*) in component CSS. - Do not use --pico-* in new component-level styles. -- Use UIcon with Material Symbols; do not use emoji as UI icons. +- Use UIcon with Material Symbols; do not use emoji as UI icons or action buttons. +- Amber CRT phosphor (`text-amber-*`, raw phosphor glow) is strictly forbidden. Semantic warnings must use `var(--usx-color-warning)`. + +## Surface Toolbar & Button Standards + +- **No Redundant Secondary Back Bars**: Surfaces hosted within `AppShell` must NOT render redundant `โ Dashboard` or `โ Back` top bars. The global shell (`GlobalToolbar`) already provides permanent one-click home and finder navigation. Surfaces begin with their canonical header (`[prefix]-header`) featuring title, status badges (`UBadge`), and action controls. +- **Button Styling Consistency**: Action buttons must strictly use `.usx-btn` (with modifiers `.usx-btn--primary`, `.usx-btn--secondary`, `.usx-btn--danger`, `.usx-btn--sm`) or `UButton`. Do not invent ad-hoc button classes or use misspelt prefixes (e.g. `.uxs-btn`). +- **Sovereign Sync Integration**: System surfaces expose calm, serene indicators for host sync status (Apple PIM JXA, BitChat LAN mesh, sovereign `~/Vault` storage) without visual clutter. ## Compliance Rubric diff --git a/frontend-vue/src/api/client.ts b/frontend-vue/src/api/client.ts index a9e3e58d..d52b8be4 100644 --- a/frontend-vue/src/api/client.ts +++ b/frontend-vue/src/api/client.ts @@ -177,6 +177,57 @@ export const ucoreApi = { body: JSON.stringify(source ? { source } : {}), }), }, + host: { + syncStatus: () => request(`${UCORE_API}/api/host/sync/status`), + mailIntake: (body?: { limit?: number; unread_only?: boolean }) => + request(`${UCORE_API}/api/host/mail/intake`, { + method: "POST", + body: JSON.stringify(body || {}), + }), + imessageIntake: (body?: { limit?: number }) => + request(`${UCORE_API}/api/host/imessage/intake`, { + method: "POST", + body: JSON.stringify(body || {}), + }), + mailArchive: (messageId: string) => + request(`${UCORE_API}/api/host/mail/archive`, { + method: "POST", + body: JSON.stringify({ message_id: messageId }), + }), + mailFlag: (messageId: string, flagIndex: number = 0) => + request(`${UCORE_API}/api/host/mail/flag`, { + method: "POST", + body: JSON.stringify({ message_id: messageId, flag_index: flagIndex }), + }), + }, + workflow: { + actionToTask: (body: { + text: string; + source?: string; + source_ref?: string; + priority?: string; + sender?: string; + }) => + request(`${UCORE_API}/api/workflow/tasks/action-to-task`, { + method: "POST", + body: JSON.stringify(body), + }), + approveTask: (id: string) => + request( + `${UCORE_API}/api/workflow/tasks/${encodeURIComponent(id)}/approve`, + { + method: "POST", + }, + ), + rejectTask: (id: string, reason?: string) => + request( + `${UCORE_API}/api/workflow/tasks/${encodeURIComponent(id)}/reject`, + { + method: "POST", + body: JSON.stringify({ reason }), + }, + ), + }, }; /** diff --git a/frontend-vue/src/skills/organisms/GlobalToolbar.vue b/frontend-vue/src/skills/organisms/GlobalToolbar.vue index d6ce6caa..7e00161d 100644 --- a/frontend-vue/src/skills/organisms/GlobalToolbar.vue +++ b/frontend-vue/src/skills/organisms/GlobalToolbar.vue @@ -82,6 +82,14 @@