refactor: move Comics lab actions into the comics slice - #43
Conversation
PR Review — Loreframe StudioRisk: medium Automated review from Findings
Changed files
CONTRIBUTING checklist
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.
6cc33b6 to
f77c91d
Compare
|
cursor review |
There was a problem hiding this comment.
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.
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, | ||
| } |
There was a problem hiding this comment.
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)
Reviewed by Cursor Bugbot for commit f77c91d. Configure here.
| target: { kind: 'comic', id: result.entities[0]?.id || title, title }, | ||
| state, | ||
| } | ||
| } |
There was a problem hiding this comment.
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)
Reviewed by Cursor Bugbot for commit f77c91d. Configure here.
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.
|
cursor review |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
2 issues from previous reviews remain unresolved.
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 0db0fe4. Configure here.



Qué
Slice Comics (Paso 3), rebasado sobre #42.
features/agent.CommandResulten el producto; Agent Mode mapea y ejecuta navegación.bindGenerateComicTargetse queda en el adapter.generate_comic_panelpasa acontext.adapters.comic.generatePanel(legacy 17→16).No mezclar. Esperar #47 y #42.
Verificación
npm test447 pass.tsc -blimpio.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/labActionsintofeatures/comics(commands,actions,adapters). Those actions returnCommandResultviacommandResultFromSlice;applicationAdapters.comicnavigates to Comics and maps metadata intoAdapterOutcome(including partial/failed generate).bindGenerateComicTargetstays in the comic adapter before generate.agentActionsandeditorAuxCapabilitiesno longer dynamic-import slice-specific agent modules for these capabilities—they calldefaultApplicationAdaptersand forwardreportwhere present. Series, character kit, and video editor adapters similarly call sliceadaptersand shared presenters (presentSeriesSliceResult,kitOutcome,editorOutcome). Character kit session memory moves tocharacters/session; agentcommandContractre-exportslib/commandContract. Legacy agent files (comicLabActions,seriesLabActions, etc.) shrink to re-exports or type barrels.Reviewed by Cursor Bugbot for commit 0db0fe4. Configure here.