Skip to content

experiment(ui): prototype two-level task navigation - #104

Merged
IAnMove merged 17 commits into
mainfrom
experiment/ui-information-architecture
Sep 2, 2026
Merged

experiment(ui): prototype two-level task navigation#104
IAnMove merged 17 commits into
mainfrom
experiment/ui-information-architecture

Conversation

@IAnMove

@IAnMove IAnMove commented Sep 2, 2026

Copy link
Copy Markdown
Owner

Resumen

  • reorganiza la navegación en cuatro categorías visibles: Generación directa, Estudios, Producción y Media
  • muestra sus destinos en una segunda barra horizontal vinculada visualmente al botón padre
  • usa matices oscuros y sutiles por categoría, estado presionado y halo en el destino activo
  • integra el selector de carpeta de salida en la navegación y elimina el encabezado derecho redundante
  • mantiene navegación semántica para Ask to the Wizard, selector rápido de idioma y Settings
  • actualiza las pruebas afectadas por la nueva arquitectura

Validación

  • npm run check
  • 507/507 tests
  • i18n, lint, build y budget correctos

Es una rama experimental de UI; el árbol de trabajo usado por Grok no se ha modificado.


Note

Medium Risk
Broad navigation and layout changes affect how users reach every major area; output-folder and studio/director routing moved but still use existing store APIs, with no backend or auth changes.

Overview
This PR restructures the main shell around a new left Wizard column and a category-based top nav, instead of one long tab strip plus agent UI in the activity footer.

Navigation replaces the horizontal scroll tabs with four primary categories (Direct generation, Studios, Production, Media), each opening a second row of destinations with category-colored styling and a visual “notch” aligned to the active parent. Direct-generation picks now set generationMode, open studio via hocuspocus:studio-open, and drop the in-sidebar mode strip. Workspaces, Activity (Runs), output folder, search, quick EN/ES, and Settings live in the nav bar; the main content header no longer shows folder picker or output counts.

Ask to the Wizard moves into new WizardSidebar (collapsible, mobile overlay) with AgentAssistantPanel embedded mode. ActivityFooter only handles task history; it publishes canonical tasks through canonicalTaskFeed so the wizard shares the same task list.

Studio sidebar loses the Director/Studio toggle and header settings; collapse is generalized for all tool modes, titles reflect direct generation vs Director, and SettingsDrawer slides in from the right. Agent navigation actions call announceWizardNavigation so the matching category expands and gets the wizard highlight animation.

i18n, CSS, tests, and optional HOCUSPOCUS_API_TARGET for the Vite proxy are updated to match.

Reviewed by Cursor Bugbot for commit 630ec50. Configure here.

@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown

PR Review — Loreframe Studio

Risk: medium
Scope: 68 file(s); +1886/-681; React UI, docs

Automated review from scripts/analyze_pr.py. This is a heuristic pass (no LLM) so humans still own the merge decision.

Findings

  • medium — Large pull request
    1886 additions / 681 deletions. Reviewers will have an easier time with smaller, focused PRs.
  • low — UI changed — rebuild before merge
    Run cd ui && npm run build (CI already does this). Pinokio Update rebuilds for end users; keep ui/dist untracked.

Changed files

  • added: ui/src/components/MainContent/OutputFolderSelector.tsx, ui/src/components/Sidebar/WizardSidebar.tsx, ui/src/features/activity/canonicalTaskFeed.ts, ui/src/i18n/SpokenLanguageOptions.tsx, ui/src/i18n/locales/en/auditDev.json, ui/src/i18n/locales/en/projects.json, ui/src/i18n/locales/en/styleSheet.json, ui/src/i18n/locales/en/videoEditor.json, ui/src/i18n/locales/en/workspaces.json, ui/src/i18n/locales/es/auditDev.json, ui/src/i18n/locales/es/projects.json, ui/src/i18n/locales/es/styleSheet.json, ui/src/i18n/locales/es/videoEditor.json, ui/src/i18n/locales/es/workspaces.json, ui/src/lib/navigationCategories.ts
  • modified: docs/development/INTERNATIONALIZATION.md, tests/test_video_editor_replacement_ui.py, ui/e2e/helpers/apiRoutes.ts, ui/e2e/helpers/gotoApp.ts, ui/e2e/specs/boot.spec.ts, ui/e2e/specs/story-lab-music-productions.spec.ts, ui/scripts/check-i18n-catalogs.mjs, ui/src/App.tsx, ui/src/components/ActivityFooter.tsx, ui/src/components/MainContent/MainContent.tsx, ui/src/components/MainContent/MediaFeedItem.tsx, ui/src/components/MainContent/TabFilter.tsx, ui/src/components/SettingsDrawer/SettingsDrawer.tsx, ui/src/components/Sidebar/DirectorChat.tsx, ui/src/components/Sidebar/GenerationModeSelector.tsx, ui/src/components/Sidebar/Sidebar.tsx, ui/src/features/agent/AgentAssistantPanel.tsx, ui/src/features/agent/applicationAdapters.ts, ui/src/features/auditdev/AuditDevPanel.tsx, ui/src/features/projects/ProjectsPanel.tsx
    … and 33 more

CONTRIBUTING checklist

  • python scripts/verify_clean_repo.py
  • python -m compileall -q app/services app/launch.py scripts
  • cd ui && npm run build if the UI changed
  • No weights, CivitAI sidecars, or generated guides
  • Stays local-first (no required accounts / telemetry)

Posted by the repo PR review workflow. Re-runs on each push to the PR.

@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown

Code health

Metric Value
Production LOC 234,881
Production files 508
Test LOC 64,310
Functions measured 14,732
Functions complexity ≥ 15 776
Maximum complexity 667

Markdown, JSON catalogs and tests are out of this table. Only app/ runtime + ui/src TS/JS count.

Most complex functions

Complexity Where
667 app/wgp.py:7157 generate_video
374 ui/src/stores/useStore.ts:4426 Async method 'startGeneration'
356 app/_launch_runtime.py:23733 _run_generation
308 app/wgp.py:12274 generate_video_tab
272 ui/src/components/Sidebar/SceneAnimatorPanel.tsx:469 Function 'SceneAnimatorPanel'
266 ui/src/stores/useStore.ts:9164 Async method 'loadSettingsFromOutput'
258 app/services/director/planners/short_film.py:3433 ShortFilmPlanner._plan_story_driven
254 app/services/director_pipeline.py:13539 _run_video_generation
245 app/services/director_pipeline.py:7663 _run_pipeline
241 ui/src/features/agent/agentActions.ts:1077 Function 'parseAction'
227 ui/src/features/agent/agentActions.ts:2672 Async function 'executeAgentActions'
226 app/services/director_pipeline.py:6492 update_comic_preview

Trend vs baseline

Metric Δ
Production LOC +1,216
Test LOC +496
Functions ≥ 15 +2
Maximum complexity +0

Warnings

  • production LOC increased by +1,216
  • functions at complexity >= 15 increased by +2
  • complexity hotspot ui/src/stores/useStore.ts rose 373 -> 374
  • complexity hotspot app/services/model3d_service.py rose 51 -> 54
  • complexity hotspot ui/src/components/MainContent/TabFilter.tsx rose 19 -> 23
  • complexity hotspot ui/src/features/agent/AgentAssistantPanel.tsx rose 19 -> 23
  • hotspot app/_launch_runtime.py increased by +66 lines
  • hotspot ui/src/features/agent/agentActions.ts increased by +3 lines
  • hotspot ui/src/features/video-editor/VideoEditorPanel.tsx increased by +10 lines
  • hotspot ui/src/types/index.ts increased by +3 lines
  • hotspot app/services/model3d_service.py increased by +58 lines
  • hotspot ui/src/features/agent/capabilityRegistry.ts increased by +2 lines
  • hotspot ui/src/features/agent/applicationAdapters.ts increased by +7 lines

Ratchet passed.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 6 potential issues.

Fix All in Cursor

Bugbot Autofix prepared fixes for all 6 issues found in the latest run.

  • ✅ Fixed: Style sheet and filters unreachable
    • Restored Style Sheet, Scenes, Edits, and Multi-clip as media child-bar destinations so those still-implemented filters have a navigation path again.
  • ✅ Fixed: Output folder menu is clipped
    • Moved OutputFolderSelector out of the overflow-x-auto primary row so its absolute dropdown can paint below the nav without being clipped.
  • ✅ Fixed: Navigation chrome ignores store changes
    • Category highlight and expansion now follow mediaFilter and dashboardOpen changes from the footer, dashboard, and dialogs.
  • ✅ Fixed: Settings button also opens sidebar
    • hocuspocus:settings-open now closes the generation sidebar and opens Settings only, matching wizard navigate('settings').
  • ✅ Fixed: Wizard steals keyboard focus
    • The embedded wizard textarea no longer uses autoFocus, so first keystrokes stay in studio controls.
  • ✅ Fixed: Embedded wizard stays announced modal
    • The embedded rail now uses role=region without aria-modal so assistive tech no longer treats the rest of the app as inert.

Create PR

Or push these changes by commenting:

@cursor push 074371ac92
Preview (074371ac92)
diff --git a/ui/src/components/MainContent/TabFilter.tsx b/ui/src/components/MainContent/TabFilter.tsx
--- a/ui/src/components/MainContent/TabFilter.tsx
+++ b/ui/src/components/MainContent/TabFilter.tsx
@@ -98,9 +98,20 @@
   const topRowRef = useRef<HTMLDivElement>(null)
   const childBarRef = useRef<HTMLDivElement>(null)
   const magicTimerRef = useRef<number | null>(null)
-  const initialCategory = categoryForMediaFilter(mediaFilter) || 'direct-generation'
+  const storeCategory = dashboardOpen
+    ? 'production' as const
+    : categoryForMediaFilter(mediaFilter)
+      ?? (sidebarMode === 'director' && sidebarOpen ? 'production' as const : null)
+  const destinationKey = `${mediaFilter}:${dashboardOpen}`
+  const initialCategory = storeCategory || 'direct-generation'
   const [activeCategory, setActiveCategory] = useState<NavigationCategory | null>(initialCategory)
   const [expandedCategory, setExpandedCategory] = useState<NavigationCategory | null>(initialCategory)
+  const [syncedDestination, setSyncedDestination] = useState(destinationKey)
+  if (syncedDestination !== destinationKey) {
+    setSyncedDestination(destinationKey)
+    setActiveCategory(storeCategory)
+    setExpandedCategory(storeCategory)
+  }
   const language: UiLanguage = String(i18n.resolvedLanguage || i18n.language).startsWith('es') ? 'es' : 'en'
 
   useEffect(() => {
@@ -219,6 +230,10 @@
     { value: 'series_episodes', label: t('tabs.episodes'), description: t('descriptions.mediaFilters'), icon: <Video size={15} />, action: () => openFilter('series_episodes') },
     { value: 'audio', label: t('tabs.audio'), description: t('descriptions.mediaFilters'), icon: <Activity size={15} />, action: () => openFilter('audio') },
     { value: 'model3d', label: t('tabs.model3d'), description: t('descriptions.mediaFilters'), icon: <Boxes size={15} />, action: () => openFilter('model3d') },
+    { value: 'scenes', label: t('tabs.scenes'), description: t('descriptions.mediaFilters'), icon: <MonitorPlay size={15} />, action: () => openFilter('scenes') },
+    { value: 'styles', label: t('tabs.styles'), description: t('descriptions.mediaFilters'), icon: <WandSparkles size={15} />, action: () => openFilter('styles') },
+    { value: 'avatars', label: t('tabs.edits'), description: t('descriptions.mediaFilters'), icon: <WandSparkles size={15} />, action: () => openFilter('avatars') },
+    { value: 'multiclip', label: t('tabs.multiclip'), description: t('descriptions.mediaFilters'), icon: <Clapperboard size={15} />, action: () => openFilter('multiclip') },
     { value: 'favorites', label: t('tabs.favorites'), description: t('descriptions.mediaFilters'), icon: <Sparkles size={15} />, action: () => openFilter('favorites') },
     ...(developerMode ? [{ value: 'auditdev' as const, label: t('tabs.auditDev'), description: t('descriptions.mediaFilters'), icon: <Activity size={15} />, action: () => openFilter('auditdev') }] : []),
   ]
@@ -252,15 +267,17 @@
 
   return (
     <nav aria-label={t('aria.sections')} className="flex min-w-0 flex-1 flex-col rounded-xl border border-border bg-bg-tertiary/70 p-1">
-      <div ref={topRowRef} className="flex min-w-0 flex-nowrap items-center gap-1 overflow-x-auto [scrollbar-width:none] [&::-webkit-scrollbar]:hidden">
-        <PrimaryButton active={activeCategory === 'direct-generation'} expanded={expandedCategory === 'direct-generation'} category="direct-generation" buttonRef={element => { categoryRefs.current['direct-generation'] = element }} icon={<Sparkles size={14} />} label={t('primary.directGeneration')} onClick={() => selectCategory('direct-generation')} />
-        <PrimaryButton active={activeCategory === 'studios'} expanded={expandedCategory === 'studios'} category="studios" buttonRef={element => { categoryRefs.current.studios = element }} icon={<BookOpen size={14} />} label={t('primary.studios')} onClick={() => selectCategory('studios')} />
-        <PrimaryButton active={activeCategory === 'production'} expanded={expandedCategory === 'production'} category="production" buttonRef={element => { categoryRefs.current.production = element }} icon={<Clapperboard size={14} />} label={t('primary.production')} onClick={() => selectCategory('production')} />
-        <PrimaryButton active={activeCategory === 'media'} expanded={expandedCategory === 'media'} category="media" buttonRef={element => { categoryRefs.current.media = element }} icon={<Library size={14} />} label={t('primary.media')} onClick={() => selectCategory('media')} />
-        <PrimaryButton active={mediaFilter === PRIMARY_DESTINATIONS.workspaces.value} icon={<FolderKanban size={14} />} label={t('tabs.workspaces')} onClick={() => openFilter(PRIMARY_DESTINATIONS.workspaces.value)} />
-        <PrimaryButton active={mediaFilter === PRIMARY_DESTINATIONS.activity.value} icon={<Activity size={14} />} label={t('primary.activity')} ariaLabel={`${t('tabs.runs')} · ${t('primary.activity')}`} onClick={() => openFilter(PRIMARY_DESTINATIONS.activity.value)} />
+      <div className="flex min-w-0 items-center gap-1">
+        <div ref={topRowRef} className="flex min-w-0 flex-1 flex-nowrap items-center gap-1 overflow-x-auto [scrollbar-width:none] [&::-webkit-scrollbar]:hidden">
+          <PrimaryButton active={activeCategory === 'direct-generation'} expanded={expandedCategory === 'direct-generation'} category="direct-generation" buttonRef={element => { categoryRefs.current['direct-generation'] = element }} icon={<Sparkles size={14} />} label={t('primary.directGeneration')} onClick={() => selectCategory('direct-generation')} />
+          <PrimaryButton active={activeCategory === 'studios'} expanded={expandedCategory === 'studios'} category="studios" buttonRef={element => { categoryRefs.current.studios = element }} icon={<BookOpen size={14} />} label={t('primary.studios')} onClick={() => selectCategory('studios')} />
+          <PrimaryButton active={activeCategory === 'production'} expanded={expandedCategory === 'production'} category="production" buttonRef={element => { categoryRefs.current.production = element }} icon={<Clapperboard size={14} />} label={t('primary.production')} onClick={() => selectCategory('production')} />
+          <PrimaryButton active={activeCategory === 'media'} expanded={expandedCategory === 'media'} category="media" buttonRef={element => { categoryRefs.current.media = element }} icon={<Library size={14} />} label={t('primary.media')} onClick={() => selectCategory('media')} />
+          <PrimaryButton active={mediaFilter === PRIMARY_DESTINATIONS.workspaces.value} icon={<FolderKanban size={14} />} label={t('tabs.workspaces')} onClick={() => openFilter(PRIMARY_DESTINATIONS.workspaces.value)} />
+          <PrimaryButton active={mediaFilter === PRIMARY_DESTINATIONS.activity.value} icon={<Activity size={14} />} label={t('primary.activity')} ariaLabel={`${t('tabs.runs')} · ${t('primary.activity')}`} onClick={() => openFilter(PRIMARY_DESTINATIONS.activity.value)} />
+        </div>
 
-        <div className="ml-auto flex items-center gap-1">
+        <div className="flex shrink-0 items-center gap-1">
           <OutputFolderSelector />
           {searchOpen ? (
             <div className="flex items-center gap-1 rounded-lg border border-border bg-bg-secondary px-2 py-0.5">

diff --git a/ui/src/components/Sidebar/Sidebar.tsx b/ui/src/components/Sidebar/Sidebar.tsx
--- a/ui/src/components/Sidebar/Sidebar.tsx
+++ b/ui/src/components/Sidebar/Sidebar.tsx
@@ -95,8 +95,7 @@
       setSidebarOpen(true)
     }
     const openSettings = () => {
-      setToolsSidebarCollapsed(false)
-      setSidebarOpen(true)
+      setSidebarOpen(false)
       setSettingsOpen(true)
     }
     const openDirector = () => {

diff --git a/ui/src/features/agent/AgentAssistantPanel.tsx b/ui/src/features/agent/AgentAssistantPanel.tsx
--- a/ui/src/features/agent/AgentAssistantPanel.tsx
+++ b/ui/src/features/agent/AgentAssistantPanel.tsx
@@ -449,8 +449,8 @@
 
   const panel = (
     <section
-      role="dialog"
-      aria-modal="true"
+      role={embedded && !expanded ? 'region' : 'dialog'}
+      aria-modal={embedded && !expanded ? undefined : 'true'}
       aria-label={t('title')}
       data-expanded={expanded ? 'true' : 'false'}
       className={`hp-agent-panel z-[100] flex flex-col overflow-hidden border border-amber-200/20 bg-[#0d0b13]/95 shadow-2xl backdrop-blur-xl ${expanded
@@ -579,7 +579,7 @@
         <div className="flex items-end gap-2 rounded-xl border border-white/10 bg-black/25 p-2 focus-within:border-amber-200/35">
           <Sparkles size={14} className="mb-1 shrink-0 text-amber-200/55" />
           <textarea
-            autoFocus
+            autoFocus={!embedded}
             rows={2}
             value={draft}
             disabled={busy}

diff --git a/ui/tests/wizardPresentationContract.test.mjs b/ui/tests/wizardPresentationContract.test.mjs
--- a/ui/tests/wizardPresentationContract.test.mjs
+++ b/ui/tests/wizardPresentationContract.test.mjs
@@ -47,7 +47,8 @@
 
 test('Wizard panel keeps dialog, live-region and pending-question ARIA contracts', async () => {
   const panelSource = await readFile(new URL('../src/features/agent/AgentAssistantPanel.tsx', import.meta.url), 'utf8')
-  assert.match(panelSource, /role="dialog"[\s\S]{0,160}aria-modal="true"/)
+  assert.match(panelSource, /role=\{embedded && !expanded \? 'region' : 'dialog'\}/)
+  assert.match(panelSource, /aria-modal=\{embedded && !expanded \? undefined : 'true'\}/)
   assert.match(panelSource, /aria-live="polite"/)
   assert.match(panelSource, /role="group" aria-label="Wizard pending question"/)
   assert.match(panelSource, /aria-label=\{t\('title'\)\}/)

You can send follow-ups to the cloud agent here.

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 630ec50. Configure here.

{ value: 'model3d', label: t('tabs.model3d'), description: t('descriptions.mediaFilters'), icon: <Boxes size={15} />, action: () => openFilter('model3d') },
{ value: 'favorites', label: t('tabs.favorites'), description: t('descriptions.mediaFilters'), icon: <Sparkles size={15} />, action: () => openFilter('favorites') },
...(developerMode ? [{ value: 'auditdev' as const, label: t('tabs.auditDev'), description: t('descriptions.mediaFilters'), icon: <Activity size={15} />, action: () => openFilter('auditdev') }] : []),
]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style sheet and filters unreachable

High Severity

The new child menus omit styles, scenes, avatars, and multiclip, so Style Sheet and those gallery filters have no navigation path. MainContent and galleryListQuery still handle them, and they remain in the MEDIA set, so this looks like an accidental drop rather than a removal.

Additional Locations (2)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 630ec50. Configure here.

className="text-text-muted hover:text-text-secondary">
<X size={12} />
<div className="ml-auto flex items-center gap-1">
<OutputFolderSelector />

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Output folder menu is clipped

High Severity

OutputFolderSelector now lives inside the top nav row that uses overflow-x-auto. Its absolutely positioned dropdown extends below that short row, so the folder list is clipped and switching, creating, or deleting output folders becomes unusable.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 630ec50. Configure here.

const magicTimerRef = useRef<number | null>(null)
const initialCategory = categoryForMediaFilter(mediaFilter) || 'direct-generation'
const [activeCategory, setActiveCategory] = useState<NavigationCategory | null>(initialCategory)
const [expandedCategory, setExpandedCategory] = useState<NavigationCategory | null>(initialCategory)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Navigation chrome ignores store changes

Medium Severity

activeCategory and expandedCategory are local state and never follow mediaFilter unless the user clicks TabFilter or a wizard event fires. Footer, dashboard, and dialog navigations leave the previous category highlighted and expanded beside the real destination.

Additional Locations (2)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 630ec50. Configure here.

setToolsSidebarCollapsed(false)
setSidebarOpen(true)
setSettingsOpen(true)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Settings button also opens sidebar

Medium Severity

The nav Settings control dispatches hocuspocus:settings-open, and that handler expands the studio tools and sets sidebarOpen as well as opening the settings drawer. Users asking for Settings also get the generation sidebar, which is the opposite of wizard navigate('settings').

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 630ec50. Configure here.

</section>
)

if (embedded && !expanded) return panel

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wizard steals keyboard focus

Medium Severity

The wizard column now mounts on load (expanded unless localStorage says otherwise) and the chat textarea still has autoFocus. Focus lands in Ask to the Wizard instead of the generation prompt, so the first keystrokes go to the assistant.

Additional Locations (2)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 630ec50. Configure here.

data-expanded={expanded ? 'true' : 'false'}
className={`hp-agent-panel z-[100] flex flex-col overflow-hidden border border-amber-200/20 bg-[#0d0b13]/95 shadow-2xl backdrop-blur-xl ${expanded
? 'hp-agent-panel--expanded fixed inset-0 rounded-none text-sm sm:inset-2 sm:rounded-2xl'
: 'fixed bottom-12 left-2 h-[min(34rem,calc(100vh-5rem))] w-[min(25rem,calc(100vw-1rem))] rounded-2xl text-xs'}`}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Embedded wizard stays announced modal

Medium Severity

The embedded sidebar still uses role="dialog" and aria-modal="true". Assistive tech treats the rest of the app as inert even though generation, navigation, and the gallery remain interactive beside the wizard.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 630ec50. Configure here.

@IAnMove

IAnMove commented Sep 2, 2026

Copy link
Copy Markdown
Owner Author

He mezclado el main actualizado y he resuelto los seis hallazgos. La sincronización de navegación usa una suscripción al store y preserva intencionadamente Generación directa cuando esta cambia la biblioteca asociada; así Imagen abre Studio Imagen + Media Imágenes sin que el resaltado salte a Media. También se añadieron pruebas para los destinos restaurados, el desplegable sin clipping, cambios externos y el contrato accesible. Validación local: npm run check, 509/509 tests, i18n, lint, build y budget correctos.

@cursor review

@IAnMove

IAnMove commented Sep 2, 2026

Copy link
Copy Markdown
Owner Author

Seguimiento: el commit 5911d65 también cierra vistas superpuestas al navegar desde Producciones o Settings y mantiene la selección local como última operación del clic. Pruebas específicas y build pasan. @cursor review

pinokio and others added 4 commits September 2, 2026 22:39
… audit chrome

Move leftover hardcoded Spanish/English visible copy into EN+ES catalogs
(director spoken/T2V, videoEditor transitions and time cards, production
runs and Workspace collections, style sheet, projects, internal audit).
Retarget tests and E2E so Story Lab is opened through Studios, not as a
top-level tab.
TRANSITIONS stored catalog keys as string, so t(option.labelKey) was not a videoEditor key.
@IAnMove
IAnMove merged commit a4b6c9a into main Sep 2, 2026
4 checks passed
@IAnMove
IAnMove deleted the experiment/ui-information-architecture branch September 5, 2026 11:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant