Skip to content

refactor: move Comics lab actions into the comics slice - #43

Merged
IAnMove merged 8 commits into
mainfrom
refactor/paso3-comics
Sep 1, 2026
Merged

refactor: move Comics lab actions into the comics slice#43
IAnMove merged 8 commits into
mainfrom
refactor/paso3-comics

Conversation

@IAnMove

@IAnMove IAnMove commented Sep 1, 2026

Copy link
Copy Markdown
Owner

Qué

Slice Comics (Paso 3), rebasado sobre #42.

  • Commands neutrales. Actions no importan features/agent.
  • CommandResult en el producto; Agent Mode mapea y ejecuta navegación.
  • bindGenerateComicTarget se queda en el adapter.
  • generate_comic_panel pasa a context.adapters.comic.generatePanel (legacy 17→16).
  • Gate: solo los cuatro listeners UI.

No mezclar. Esperar #47 y #42.

Verificación

npm test 447 pass. tsc -b limpio.

Dueño del merge: humano.


Note

Medium Risk
Refactors the central agent action dispatcher and execution reports for comics, series, character kits, and video editor; regressions would surface as wrong navigation, targets, or job correlation despite intended behavior parity.

Overview
Continues the command-plane migration so Comics (and the same pattern for Series, Character Kit, and Video Editor) live in product slices while Agent Mode only adapts results and drives UI.

Comic create/generate/panel flows move from comicLabActions / labActions into features/comics (commands, actions, adapters). Those actions return CommandResult via commandResultFromSlice; applicationAdapters.comic navigates to Comics and maps metadata into AdapterOutcome (including partial/failed generate). bindGenerateComicTarget stays in the comic adapter before generate.

agentActions and editorAuxCapabilities no longer dynamic-import slice-specific agent modules for these capabilities—they call defaultApplicationAdapters and forward report where present. Series, character kit, and video editor adapters similarly call slice adapters and shared presenters (presentSeriesSliceResult, kitOutcome, editorOutcome). Character kit session memory moves to characters/session; agent commandContract re-exports lib/commandContract. Legacy agent files (comicLabActions, seriesLabActions, etc.) shrink to re-exports or type barrels.

Reviewed by Cursor Bugbot for commit 0db0fe4. Configure here.

@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown

PR Review — Loreframe Studio

Risk: medium
Scope: 25 file(s); +2921/-2170; React UI

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
    2921 additions / 2170 deletions. Reviewers will have an easier time with smaller, focused PRs.
  • medium — Very large file change (ui/src/features/comics/actions.ts)
    ui/src/features/comics/actions.ts adds 424 lines. Consider splitting the PR.
  • medium — Very large file change (ui/src/features/series/actions.ts)
    ui/src/features/series/actions.ts adds 654 lines. Consider splitting the PR.
  • medium — Very large file change (ui/src/lib/commandContract.ts)
    ui/src/lib/commandContract.ts adds 692 lines. Consider splitting the PR.
  • 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/features/characters/session.ts, ui/src/features/comics/actions.ts, ui/src/features/comics/adapters.ts, ui/src/features/comics/commands.ts, ui/src/features/series/actions.ts, ui/src/features/series/adapters.ts, ui/src/features/series/commands.ts, ui/src/lib/commandContract.ts, ui/src/lib/labHelpers.ts
  • modified: ui/src/features/agent/agentActions.ts, ui/src/features/agent/applicationAdapters.ts, ui/src/features/agent/characterKitActions.ts, ui/src/features/agent/comicLabActions.ts, ui/src/features/agent/commandContract.ts, ui/src/features/agent/editorAuxCapabilities.ts, ui/src/features/agent/labActionHelpers.ts, ui/src/features/agent/seriesLabActions.ts, ui/src/features/agent/videoEditorActions.ts, ui/src/features/agent/wizardLabSession.ts, ui/src/features/characters/actions.ts, ui/src/features/characters/commands.ts, ui/src/features/video-editor/actions.ts, ui/src/features/video-editor/commands.ts, ui/tests/agentActions.test.mjs, ui/tests/agentCapabilityPorts.test.mjs

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.

Move CommandEnvelope/CommandResult to lib/commandContract and leave a
compatible reexport. CharacterKit and Video Editor return CommandResult,
stop importing features/agent, and map to AgentExecutionReport inside
applicationAdapters. The ports gate keeps only the four UI-bus listeners
and shrinks the legacy executor list.
Keep an agent reexport so labActions and adapters do not change yet.
Temporary imports of agentActions, agentUiBus and labActionHelpers are
named on the ports allowlist.
Series actions return CommandResult, import lab helpers from lib, and
stop calling agentUiBus. Agent Mode adapters execute navigation, section
focus and job notifications. The slice→agent allowlist stays at the four
UI listeners.
Keep an agent reexport. Deduplicate the ports-gate import scan so a
file that mentions the same agent module twice is listed once.
Comics actions return CommandResult and stop importing agentActions or
agentContract. Adapters bind generate_comic targets, navigate, and map
results. generate_comic_panel now runs through context.adapters.comic.
@IAnMove
IAnMove force-pushed the refactor/paso3-comics branch from 6cc33b6 to f77c91d Compare September 1, 2026 11:25
@IAnMove

IAnMove commented Sep 1, 2026

Copy link
Copy Markdown
Owner Author

cursor review

@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 3 potential issues.

Autofix Details

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

  • ✅ Fixed: Failed comic generate marked completed
    • presentComicSliceResult now attaches a partial/failed report so the capability runner no longer synthesizes a completed expensive generate_comic execution.
  • ✅ Fixed: Navigation can fail after comic commits
    • Comic adapters now navigate to Comics before create/generate, so a tab confirmation failure cannot mark already-committed artwork as a failed predecessor.
  • ✅ Fixed: Character kit tracking loses job state
    • trackJob now uses inspectCanonicalQueue diagnostics and returns a running report instead of a generic completed active-count card.

Create PR

Or push these changes by commenting:

@cursor push e3c6001a31
Preview (e3c6001a31)
diff --git a/ui/src/features/agent/applicationAdapters.ts b/ui/src/features/agent/applicationAdapters.ts
--- a/ui/src/features/agent/applicationAdapters.ts
+++ b/ui/src/features/agent/applicationAdapters.ts
@@ -393,10 +393,12 @@
   adapters.comic = {
     open: () => navigate('comics'),
     async create(action) {
+      await navigate('comics')
       const { create } = await import('../comics/adapters')
       return presentComicSliceResult(await create(action))
     },
     async generate(action, expectedProjectId) {
+      await navigate('comics')
       const { bindGenerateComicTarget } = await import('./agentContract')
       const { useComicStore } = await import('../comics/store')
       const current = useComicStore.getState().project
@@ -405,6 +407,7 @@
       return presentComicSliceResult(await generate(action))
     },
     async generatePanel(pageNumber, panelNumber) {
+      await navigate('comics')
       const { generatePanel } = await import('../comics/adapters')
       return presentComicSliceResult(await generatePanel(pageNumber, panelNumber))
     },
@@ -582,12 +585,21 @@
     async trackJob(action) {
       const { trackJob } = await import('../characters/adapters')
       const result = await trackJob({ kitName: action.kitName })
+      const { inspectCanonicalQueue } = await import('./queueActions')
+      const diagnostic = await inspectCanonicalQueue('active')
       const name = kitNameFromResult(result)
-      const count = result.taskIds.length
-      const queue = count
-        ? `${count} tarea${count === 1 ? '' : 's'} activa${count === 1 ? '' : 's'} en la cola canónica.`
-        : 'No hay tareas activas en la cola canónica.'
-      return kitOutcome(result, `Sigo el trabajo de “${name}”. ${queue}`)
+      const message = `Sigo el trabajo de “${name}”. ${diagnostic}`
+      const outcome = await kitOutcome(result, message)
+      return {
+        ...outcome,
+        report: executionReport({
+          state: 'running',
+          message: diagnostic,
+          recoverable: false,
+          target: outcome.target,
+          taskId: result.taskIds[0],
+        }),
+      }
     },
   }
   adapters.queue = {
@@ -693,15 +705,23 @@
 }
 
 async function presentComicSliceResult(result: CommandResult): Promise<AdapterOutcome & { state: 'completed' | 'partial' | 'failed' }> {
-  await navigate('comics')
   const meta = result.artifacts[0]?.metadata || {}
   const summary = typeof meta.summary === 'string' ? meta.summary : 'Comics listo.'
   const title = typeof meta.title === 'string' ? meta.title : (result.entities[0]?.id || 'comic')
   const state = result.status === 'partial' ? 'partial' : result.status === 'failed' ? 'failed' : 'completed'
+  const target = { kind: 'comic', id: result.entities[0]?.id || title, title }
   return {
     message: summary,
-    target: { kind: 'comic', id: result.entities[0]?.id || title, title },
+    target,
     state,
+    ...(state === 'completed' ? {} : {
+      report: executionReport({
+        state,
+        message: summary,
+        recoverable: true,
+        target,
+      }),
+    }),
   }
 }

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

message: summary,
target: { kind: 'comic', id: result.entities[0]?.id || title, title },
state,
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Failed comic generate marked completed

High Severity

presentComicSliceResult maps CommandResult status onto state and never sets report. The live capability runner only honors tracked.report and otherwise records completed with ok: true. Partial or failed generate_comic artwork is remembered as a successful expensive run, so retries reuse that result instead of drawing again.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit f77c91d. Configure here.

target: { kind: 'comic', id: result.entities[0]?.id || title, title },
state,
}
}

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 can fail after comic commits

Medium Severity

presentComicSliceResult calls navigate only after the slice has already created or drawn the comic. navigate throws when the Comics tab is not confirmed, so a committed create or generate is reported as failure and can block a same-turn generate_comic.

Additional Locations (2)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit f77c91d. Configure here.

Comment thread ui/src/features/characters/actions.ts
ESLint rejects empty interfaces. Validate and track have no fields, so
they are Record<string, never> instead of {}.
track_character_kit_job again inspects the live queue, opens Activity,
and reports running so the runner does not mark active work completed.
In-progress and failed exports now always carry job status and message,
and the adapter no longer treats the job id as an output name.
@IAnMove

IAnMove commented Sep 1, 2026

Copy link
Copy Markdown
Owner Author

cursor review

@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.

✅ Bugbot reviewed your changes and found no new issues!

2 issues from previous reviews remain unresolved.

Fix All in Cursor

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

Reviewed by Cursor Bugbot for commit 0db0fe4. Configure here.

@IAnMove
IAnMove merged commit 0e39f27 into main Sep 1, 2026
5 checks passed
@IAnMove
IAnMove deleted the refactor/paso3-comics branch September 5, 2026 11:54
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