$ cat workspace-template.yaml
Slide Presentation for Mission Operative Briefing
// An interactive presentation with HTML slides for Marina Militare Italiana Briefings, Missions and Operations
// Canvas Preview
// Instruction
Briefing Missione Navale dalle Cartelle Drive
Template ID
4f9ff1f1-9fd5-4d32-a4df-58eebe3c43ae
Overview
Composes a mission briefing deck from documents stored in a Drive Folder, using the Marina Militare theme and slide layouts. Designed for Italian Navy operational use — the output is a self-contained Reveal.js briefing presentation exported to PPTX, styled as a formal naval briefing. The workflow reads documents, then "Selezione dei Topic Principali" identifies the main topics and their subtopics. A centralized "Contenuto Presentazione" node generates ALL slide content for the entire briefing in a single pass. For each subtopic, the agent MUST clone a prototype node, rename it, wire its content input from "Contenuto Presentazione", and wire its output to "Make Array". All slides are assembled into the briefing and exported to PPTX.
Terminology: A topic is a high-level subject area. Each topic is subdivided into subtopics — each subtopic becomes exactly one slide. When a user says "I want 10 topics with 5 subtopics each," the result is 50 content slides plus intro and outro. Each topic can have a different number of subtopics.
The template includes one prototype: a standalone node for text-only slides ("Topic #x - Subtopic #x") configured with marina-content by default. In Phase 3, the agent clones this prototype for EVERY topic and subtopic, renames it, and optionally picks a more specific marina layout (marina-metrics, marina-timeline, marina-comparison) based on the subtopic content shape. Do NOT delete the prototype — it must remain on the canvas. Unless the user specifies a maximum, ALL topics and subtopics from the output are used.
Marina v1 does NOT ship image-layout variants. There is no marina-image-left or marina-image-right. If the user requests images, see "Common User Requests" below for the correct response — do NOT fall back to vanilla image-left / image-right (they render unbranded white and look broken next to the marina navy).
Workflow Chain
Data Source Selection
The data source depends on what the user wants to process:
- Folder (multiple documents): Use Drive Folder Reader connected to Drive Document Reader (both nodes). The Folder Reader lists items, the Document Reader reads their content.
- Single file: Use only Drive Document Reader (no Folder Reader needed). The user selects the document directly. You must delete the "Seleziona Materiale Sorgente" node from the canvas using
deleteNode, then configure the Document Reader withupsertNode.
Node Reference
Data Source Nodes
"Seleziona Materiale Sorgente" (Drive Folder Reader):
- What it does: Lists all document items in a selected Drive folder.
- Configurable inputs:
driveItemId— the Drive folder ID (NOTfolderId). - Output:
driveItemIds→ list of document IDs.
"Leggi i Documenti disponibili" (Drive Document Reader):
- What it does: Reads the processed text content from documents.
- Input from: Drive Folder Reader
[driveItemIds](folder mode) or user-selected document (single file mode). - Configurable inputs:
driveItemId— the Drive item ID. - Output:
content→ full text content of the document(s). This content feeds "Selezione dei Topic Principali" AND "Contenuto Presentazione".
"Selezione dei Topic Principali" (Topic Selector)
What it does: Analyzes document content and identifies both the main topics AND the subtopics for each topic in a single pass. This is the only node that determines the presentation structure.
Input from: "Leggi i Documenti disponibili" [content].
Configurable inputs:
llmModel: LLM model for topic extraction (default: auto-selected)prompt: Instruction for topic and subtopic selection. Default:"Seleziona i topic principali dei documenti e riassumi i punti chiave (topics), per ciascun topic riassumi i temi (subtopic) rilevanti". Can be customized to focus on specific areas or to request a specific number of topics/subtopics. Output:summary→ structured text containing topics and their subtopics. The agent MUST read this output to extract both the topic names AND the subtopic names per topic. All subsequent node naming and prompts MUST use the exact topic and subtopic names from this output.
"Contenuto Presentazione" (Content Generator)
What it does: Generates the complete textual content for ALL slides in the presentation in a single pass. The agent MUST update the prompt with the full list of topics and subtopics (from "Selezione dei Topic Principali" output) before executing this node.
Input from: "Leggi i Documenti disponibili" [content].
Configurable inputs:
llmModel: LLM model (default:openai/gpt-oss-120b)prompt: MUST be updated by the agent to list ALL topics and subtopics in the following format:
Output: summary → complete presentation content organized by topic/subtopic. This feeds "#Intro", "#outro", and ALL topic Slide Generator nodes.
"#Intro" and "#outro" (Slide Generators)
"#Intro" (Slide Generator):
- What it does: Generates the opening slide(s) for the presentation with the Marina Militare crest, uppercase title, and subtitle.
- Input from: "Contenuto Presentazione"
[summary]→[content]. - Pre-connected: Output
slide_html→ Make Arrayitem_0. - Default config:
template_name: "marina-intro",instruction: "titolo slide di apertura".
"#outro" (Slide Generator):
- What it does: Generates the closing slide with the Marina Militare crest, "Grazie" headline, and hashtag.
- Input from: "Contenuto Presentazione"
[summary]→[content]. - NOT pre-connected to Make Array — the agent MUST wire it to the last pin after all topic slides are connected.
- Default config:
template_name: "marina-outro".
Prototype Node (for cloning)
The template includes one prototype. It is NOT real content — it serves as a template to clone from. Do NOT delete the prototype — it must remain on the canvas as a reference node for future operations.
"Topic #x - Subtopic #x" (standalone Slide Generator, text-only):
- 1 node: Slide Generator
- Default config:
template_name: "marina-content",instruction: "Inserisci il contenuto del Topic #x - Subtopic #x" - Input:
content← from "Contenuto Presentazione"[summary](external edge — NOT preserved bycloneNodes) - Output:
slide_html— NOT pre-connected to Make Array - IMPORTANT: This is a standalone node, NOT inside a section. Use
nodeFinderto locate it (notsectionFinder). When cloning withcloneNodes({ nodeIds: [nodeId] }), the clone keeps the original label "Topic #x - Subtopic #x" — you MUST callupsertNodeto rename it, set the instruction, and (optionally) pick a specific marina layout for that subtopic.
Make Array
What it does: Collects all slide HTML outputs into a single ordered array. Pin order determines slide order in the final presentation.
Pin layout: item_0 = #Intro, then all subtopic slides grouped by topic in sequential order, last pin = #outro.
Example (2 topics, 3 and 2 subtopics): item_0 = #Intro, item_1 = T1-Sub1, item_2 = T1-Sub2, item_3 = T1-Sub3, item_4 = T2-Sub1, item_5 = T2-Sub2, item_6 = #outro.
Default pins: The template ships with 10 input pins. When the total exceeds 10, new pins are created automatically by upsertEdge.
Total pins formula: 1 (Intro) + sum of all subtopics across all topics + 1 (Outro).
Output: Array of slide HTML sections (ordered by pin index).
Presentation Composer
What it does: Assembles individual slides into a complete self-contained Reveal.js HTML presentation.
Pre-connected in template: Receives items array from Make Array.
Configurable inputs:
title: Presentation title (shown in browser tab)theme: default"marina"(Marina Militare — navy + gold + Italian tricolor footer). The marina theme renders at a 1920×1080 internal canvas with Google Fonts (Graduate + Montserrat).transition: Slide transition effect —slide,fade,convex,concave,zoom,noneOutput: Complete HTML document (self-contained presentation).
PPTX Converter
What it does: Converts the Reveal.js HTML presentation into a downloadable PowerPoint .pptx file.
Pre-connected in template: Receives presentation HTML from Presentation Composer.
Configurable inputs:
title: PowerPoint metadata titletheme: default"marina"— must match Presentation Composer theme for correct color mapping. Note: the PPTX converter uses its own inch-based coordinate system; the marina theme's 1920×1080 Reveal canvas does NOT affect PowerPoint output dimensions (PPTX is always 13.33 × 7.5 inches LAYOUT_WIDE). Output: PowerPoint .pptx file.
Public Share
What it does: Publishes the Reveal.js HTML from Presentation Composer as a shareable, read-only public link. Intended for recipients who want to preview the briefing in a browser without downloading the .pptx.
Pre-connected in template: Receives the presentation HTML from Presentation Composer.
Configurable inputs: none required for the default publish flow — the node uses workspace defaults.
Output: url → a public URL the user can share.
Marina Layout Selection
Marina Militare ships 6 slide layouts in v1. The agent SHOULD pick the best layout per subtopic based on the content shape, not just use marina-content for everything. Variety across slides improves the visual pacing of the deck.
marina-intro— cover/title slide. Used by the#Intronode only. Shows the Marina Militare crest, a large uppercase title in Graduate font, a subtitle, and a meta line. Navy-blue gradient background + Italian tricolor footer.marina-content— default workhorse for text-and-bullets content. Shows a fixed top header bar (Marina logo + slide title pulled fromdata-header-title), an<h2>section heading, and a body of text, lists, or mixed content. Use when the subtopic doesn't fit one of the more specialized layouts below.marina-metrics— KPI/capability dashboard with 3–6 card grid. Each card has a label, a large value (optionally colored gold for highlights, cyan for cool readings, red for alerts, green for OK), and an optional detail line. Use when the subtopic content is numerical or capability-oriented: performance metrics, operational readiness, fleet stats, force levels, budget summaries.marina-timeline— vertical timeline with circular markers along a gold rail. Each event has a timestamp and a description. Supportsalert(red with halo) andgold(milestone) variants. Use when the subtopic content is chronological: mission timeline, historical milestones, project cadence, development roadmap, cronologia operativa.marina-comparison— wide table with a navy header row (gold text), bordered rows, and right-aligned status-pill dots (cyan / green / gold / red). Use when the subtopic content is a comparison table, a tracking list, or a status-by-category layout: platform-vs-platform comparisons, contact tracking tables, capability-vs-ally tables, threat assessment tables.marina-outro— closing slide. Used by the#outronode only. Shows the Marina Militare crest, a "Grazie" headline in gold, and a hashtag subtitle.
Layout picking rule (apply in Phase 3 step B when renaming each cloned node):
- If the subtopic title or expected content is chronological (contains words like "timeline", "cronologia", "milestone", "history", "roadmap", "evolution", "phases", dates, years) →
marina-timeline - Else if the subtopic is number-heavy (contains words like "metrics", "KPI", "statistics", "performance", "capability", "budget", "readiness", "fleet size", "counts") →
marina-metrics - Else if the subtopic is a comparison or tracking list (contains words like "comparison", "vs", "competitors", "tracking", "allies", "table", "matrix") →
marina-comparison - Else →
marina-content
The agent MUST NOT use marina-intro or marina-outro for topic subtopics — those are reserved for the #Intro and #outro nodes.
Theme consistency: marina is already the active theme throughout this template (Presentation Composer + PPTX Converter + all Slide Generator prototypes). If the user explicitly requests a different theme (Polizia Postale, Emblema), that is out of scope for this marina-flavored workspace template — direct them to the sibling pptx-from-drive.md (polpostale-flavored) template instead.
Important: Node IDs and Field Names
- After
applyCanvasData(used only for initial template commit), always usenodeFinderto locate nodes by label name —nodesPreviewIDs are no longer valid. - Use atomic tools (
upsertNode,upsertEdge,deleteNode,deleteEdge,cloneNodes) for ALL canvas modifications after the initial template apply. These execute instantly — noapplyCanvasDataneeded. - The Drive Folder Reader input field is
driveItemId(NOTfolderId). - The Drive Document Reader input field is
driveItemId. - Always verify that a
nodeIdis a valid UUID before passing it toupsertEdge. IfnodeFinderreturns no match, do NOT proceed with a missing ID — investigate the label mismatch first.
Execution Strategy
Layout contract: Call organizeNodes (step 14b) → sectionManager group (step 14c) → autoLayout (step 15a) in that exact order. The first two are scoped to the cloned Topic # nodes only; autoLayout then arranges the whole canvas. These tools only change visual arrangement and the section wrapping — they do NOT change node semantics or edges.
You MUST complete all 4 phases in order: Phase 1 → Phase 2 → Phase 3 → Phase 4. Do NOT skip any phase. Do NOT jump to Phase 4 early.
After calling nodeExecutor, the system notifies automatically when execution completes. Do NOT poll getNodeOutput in a loop.
Do NOT call followUp until Phase 4 is fully complete AND the verification audit has been presented in step 18.
If a tool call returns an error, retry up to 3 times with the same or corrected parameters before giving up. If all 3 retries fail, ask the user for help — do NOT skip the step and continue with default values.
If interrupted mid-step and the user sends "continua", resume from where you left off. Use nodeFinder to check which nodes already have the correct label/connections before re-processing them. Nodes that already show the correct label or connections do not need to be updated again.
NEVER execute the prototype node ("Topic #x - Subtopic #x") directly. Only execute cloned and renamed nodes. The prototype is a template for cloning — executing it produces incorrect output.
Phase 1: Setup
applyCanvasData→ IMMEDIATELY call this to commit the template to workspace. You MUST callapplyCanvasDatahere before any other tool call.searchDriveItems+selectDriveItem→ get the folder/file ID the user mentioned. If no results, try shorter/broader queries (e.g., "cyber" instead of "cybersecurity cyber security"). If still nothing after 2 attempts, ask the user to specify the drive item. Do NOT retry the same query.- Configure the data source:
- If folder:
nodeFinder→ find "Seleziona Materiale Sorgente".upsertNode({ nodeId: "<found ID>", input: { driveItemId: "<selected ID>" } }). - If single file:
nodeFinder→ find "Seleziona Materiale Sorgente".deleteNode({ nodeId: "<found ID>" }). ThennodeFinder→ find "Leggi i Documenti disponibili".upsertNode({ nodeId: "<found ID>", input: { driveItemId: "<selected ID>" } }).
- If folder:
Phase 1 complete. Now proceed to Phase 2. Do NOT skip to Phase 4.
Phase 2: Topic Selection & Content Generation
nodeFinder→ find "Selezione dei Topic Principali" by label. If the user specified a topic/subtopic count or focus area, update the prompt:upsertNode({ nodeId: <found ID>, input: { prompt: "Seleziona N topic principali dei documenti e per ciascun topic seleziona M temi (subtopic) rilevanti" } })— replace N and M with the user's desired counts. If the user did NOT specify counts, leave the default prompt.
nodeExecutor→ execute "Selezione dei Topic Principali". Wait for completion. The system will execute "Leggi i Documenti disponibili" as a dependency of this node.getNodeOutput→ read the output. Extract the structured list of topics AND their subtopics. For each topic, extract the topic name and the list of subtopic names. Store as:topics = [topic1_name, topic2_name, ..., topicN_name]subtopics[X] = [sub1_name, sub2_name, ..., subM_name]for each topic XN = number of topics,M_x = number of subtopics for topic X- If the user specified a maximum topic count, use that count. If the user did NOT specify a maximum, use ALL topics from the output — do NOT cap or reduce them.
- If the user specified a maximum subtopic count per topic, use that count. If the user did NOT specify a maximum, use ALL subtopics per topic from the output — do NOT cap or reduce them.
- Safety limits: if
N(number of topics) exceeds 20, warn the user and ask whether to proceed or reduce. Iftotal_subtopics(sum of M_x across all topics) exceeds 50, warn the user and ask whether to proceed or reduce. Do NOT silently reduce.
CRITICAL: ALL topic names and subtopic names used in subsequent phases MUST come from the "Selezione dei Topic Principali" output (this step). Do NOT invent topic or subtopic names — always use the exact names from this output.
nodeFinder→ find "Contenuto Presentazione" by label. Update its prompt to list ALL topics and subtopics using the exact names from step 6:upsertNode({ nodeId: <found ID>, input: { prompt: "Prepara il contenuto della presentazione espandendo ogni topic e subtopic selezionati dal nodo \"Selezione dei Topic Principali\" creando il testo per ciascuna sezione.\n\nNel prompt elenca tutti i topic e subtopic da espandere includendo il loro nome esteso nel seguente formato:\n\n#Topic 1: <topic1_name>\n##Subtopic 1: <subtopics[1][1]>\n##Subtopic 2: <subtopics[1][2]>\n...\n#Topic 2: <topic2_name>\n##Subtopic 1: <subtopics[2][1]>\n...\n\nPer ogni topic principale, sviluppa una sezione dettagliata con tutti i relativi subtopic, fornendo descrizioni complete e coerenti per la presentazione finale." } })— replace ALL placeholder names with actual names from step 6.
nodeExecutor→ execute "Contenuto Presentazione". IMMEDIATELY after step 7 — do NOT stop between step 7 and step 8. Wait for completion.
Phase 2 complete. Now proceed to Phase 3. Do NOT skip to Phase 4.
Phase 3: Slide Chain Creation
This phase has 4 sequential steps (A → B → C → D) with hard gates. You MUST complete each step before proceeding to the next step. Each batch tool must be called EXACTLY ONCE per step.
Marina v1 has only TEXT-ONLY MODE. There is no image-layout branching in this phase. If the user explicitly asked for images, see the error handling at the bottom of this document — do NOT silently proceed with vanilla image-left/image-right fallbacks; they render unbranded white and look broken next to marina navy.
Rules:
- Use batch tools for all bulk modifications:
batchCloneNodesto duplicate all at once,batchUpsertNodesto rename/configure all at once,batchUpsertEdgesfor all connections at once. - Each batch tool is called EXACTLY ONCE per step. Do NOT call a batch tool a second time to "fix" or "add" entries. If you discover a mistake after a batch call, use the single-operation tool (
upsertNode,upsertEdge) to patch the specific item. - Do NOT use
compileCanvasDataorapplyCanvasDatain this phase. All modifications use atomic/batch tools only. - Do NOT delete the prototype node — it must remain on the canvas for future reference.
Step A — Build mapping table, find the prototype, and clone ALL subtopic nodes:
- Find prototype and key nodes:
nodeFinder→ find "Topic #x - Subtopic #x" (standalone Slide Generator prototype). Store itsnodeIdassimplePrototypeId.nodeFinder→ find "Contenuto Presentazione" and "Make Array". Store theirnodeIdvalues for all subsequent steps.
9b. Build the COMPLETE MAPPING TABLE before cloning. This mapping is IMMUTABLE — once built, do NOT change it. All subsequent steps (B, C, D) MUST use this exact mapping.
-
Clone ALL subtopic nodes in a single call:
batchCloneNodes({ nodeIds: ["<simplePrototypeId>"], count: <total_subtopics> })→ Returnsclonesarray. Eachclones[i].nodeIdMap[simplePrototypeId]= cloned Slide Generator ID.
The
clonesarray is indexed byclone_indexfrom the mapping table.clones[0]= first row,clones[1]= second row, etc.
Do NOT proceed to Step B until Step A completes. You should have exactly total_subtopics entries in the clones array.
Step B — Rename ALL cloned nodes, set their instructions, AND set their marina layouts in one call:
CRITICAL: Cloned nodes keep the original label "Topic #x - Subtopic #x", the original instruction, and the original template_name: "marina-content". You MUST update EVERY cloned node to set label, input.instruction, AND input.template_name (to the layout picked in the mapping table).
-
Build the operations array using the MAPPING TABLE from step 9b and call
batchUpsertNodesexactly once: For each row in the mapping table, construct one operation:{ nodeId: clones[clone_index].nodeIdMap[prototypeId], label: "Topic #X - Subtopic #Y", input: { instruction: "Inserisci il contenuto del Topic #X '<topicX_name>' - Subtopic #Y '<subtopics[X][Y]>'", template_name: "<layout from mapping table>" } }- The instruction MUST include the exact topic and subtopic names. Example:
"Inserisci il contenuto del Topic #1 'Operazioni nel Mediterraneo' - Subtopic #2 'Cronologia Operativa'"— NOT"Inserisci il contenuto del Topic #1 - Subtopic #2"alone. - The
template_nameMUST be one of the 4 content layouts:marina-content,marina-metrics,marina-timeline,marina-comparison. Do NOT usemarina-introormarina-outro(reserved for the#Introand#outronodes). Do NOT use layouts from other themes (noemblema-*, nopolpostale-*, no vanillabullet-pointsetc.).
- The instruction MUST include the exact topic and subtopic names. Example:
ANTI-PATTERN: Do NOT call batchUpsertNodes a second time to "fix" or "add" entries. If you discover a mistake, use the single upsertNode tool to patch that specific node.
Do NOT proceed to Step C until Step B completes with all nodes renamed and their marina layouts set.
Step C — Wire content input on ALL cloned nodes in one call:
CRITICAL: Cloned nodes do NOT inherit external edges. Each cloned Slide Generator starts with NO content input. You MUST create an edge from "Contenuto Presentazione" to EVERY cloned Slide Generator. Without this edge, slides will be EMPTY.
-
Build the edges array using the MAPPING TABLE from step 9b and call
batchUpsertEdgesexactly once: For each row in the mapping table:{ sourceNodeId: "<Contenuto Presentazione ID>", sourcePort: "summary", targetNodeId: clones[clone_index].nodeIdMap[prototypeId], targetPort: "content" }
ANTI-PATTERN: Do NOT call batchUpsertEdges a second time. If a single edge is missing, use upsertEdge to add it.
Do NOT proceed to Step D until Step C completes with all content inputs wired.
Step D — Wire ALL cloned nodes to Make Array and connect #outro in one call:
CRITICAL: item_0 is RESERVED for #Intro (already pre-connected). The first topic slide MUST go to item_1, NOT item_0. If you connect a topic slide to item_0, you will overwrite the Intro slide.
-
nodeFinder→ find "#outro". Store itsnodeIdfor the last connection. -
Build the edges array using the MAPPING TABLE from step 9b and call
batchUpsertEdgesexactly once: For each row in the mapping table, the pin is already determined:pin = item_<clone_index + 1>:{ sourceNodeId: clones[clone_index].nodeIdMap[prototypeId], sourcePort: "slide_html", targetNodeId: "<Make Array ID>", targetPort: "item_<clone_index + 1>" }LAST entry: #outro on
item_<total_subtopics + 1>:{ sourceNodeId: "<#outro ID>", sourcePort: "slide_html", targetNodeId: "<Make Array ID>", targetPort: "item_<total_subtopics + 1>" }
ANTI-PATTERN: Do NOT call batchUpsertEdges a second time. If a single edge is missing, use upsertEdge to add it.
Do NOT proceed to Phase 4 until Step D completes with #outro connected to Make Array.
Step E — Organize the cloned subtopic nodes into a tidy grid:
14b. Build the list of cloned node IDs from the MAPPING TABLE: cloneIds = [ clones[i].nodeIdMap[<prototypeId>] for i in 0..total_subtopics-1 ]. Call organizeNodes exactly once:
organizeNodes({ nodeIds: cloneIds })
— no anchor (the tool centers the grid on the clones' current centroid), default gap: 80. The tool computes rows × cols automatically, targeting a ~16:9 bounding box.
ANTI-PATTERN: Do NOT pass section IDs (the "Prototype Node per Topic/Subtopic" section stays where it is). Do NOT pass #Intro / #outro / Make Array / Presentation Composer / PPTX Converter / Public Share — those are arranged by autoLayout in Phase 4.
Do NOT proceed to Step F until Step E completes.
Step F — Group the organized clones into a section:
14c. Using the same cloneIds array from step 14b, call sectionManager exactly once with the group action:
sectionManager({ action: "group", nodeIds: cloneIds, label: "Topic Slides", color: "#3b82f6" })
— this wraps all the cloned Topic # nodes into a single section labeled "Topic Slides". The section becomes a single draggable unit that autoLayout arranges alongside the other top-level nodes in Phase 4.
ANTI-PATTERN: Do NOT include the prototype node (simplePrototypeId), #Intro, #outro, or any non-subtopic node in this group call. The section must contain ONLY the cloned Topic # subtopic slides.
Do NOT proceed to Phase 4 until Step F completes.
Pin order example (3 topics: M_1=2, M_2=3, M_3=2):
item_0= #Intro (pre-connected — do NOT touch)item_1= Topic #1 - Subtopic #1 (clone_index=0),item_2= Topic #1 - Subtopic #2 (clone_index=1)item_3= Topic #2 - Subtopic #1 (clone_index=2),item_4= Topic #2 - Subtopic #2 (clone_index=3),item_5= Topic #2 - Subtopic #3 (clone_index=4)item_6= Topic #3 - Subtopic #1 (clone_index=5),item_7= Topic #3 - Subtopic #2 (clone_index=6)item_8= #outro
Do NOT delete the prototype node. It must remain on the canvas for future reference.
Phase 3 complete. All subtopic nodes must be cloned, renamed, assigned a marina layout, wired for content, connected to Make Array starting at item_1, and #outro connected as the last pin. Now proceed to Phase 4.
Phase 4: Verification & Final Execution
15a. Call autoLayout exactly once to arrange the entire canvas (sections + top-level nodes) along the edge flow: autoLayout({}) — defaults direction: "LR", nodeSpacing: 50, rankSpacing: 100. The locked section "Prototype Node per Topic/Subtopic" stays pinned (the tool excludes locked sections and their children). This makes the graph easy to scan before the user runs it.
CRITICAL: Do NOT skip this phase. You MUST verify connections before executing. Missing edges cause empty slides in the final presentation. Phase 4 ends with a final audit via the verification tool — followUp must not be called until the audit has been presented.
nodeFinder→ find "Make Array" and ALL Slide Generator nodes (matching "Topic #" in label, plus "#Intro" and "#outro"). Computetotal_subtopics= sum of M_x across all topics. Check that Make Array has exactlytotal_subtopics + 2inputs (1 #Intro + total_subtopics + 1 #outro). Verify:- #Intro on item_0: "#Intro" output
slide_html→ Make Arrayitem_0. If a topic slide is onitem_0instead, it has overwritten #Intro — fix by reconnecting #Intro toitem_0and shifting topic slides to start fromitem_1. - Content connection: For EACH Slide Generator node labeled "Topic #X - Subtopic #Y", verify it has
contentinput connected. If a Slide Generator showsinputs: []or no input from "Contenuto Presentazione", it will produce an EMPTY slide. Fix withupsertEdge({ sourceNodeId: "<Contenuto Presentazione>", sourcePort: "summary", targetNodeId: <Slide Gen ID>, targetPort: "content" }). - Marina layout: For EACH Slide Generator node labeled "Topic #X - Subtopic #Y", verify
template_nameis one of the 4 valid content layouts (marina-content,marina-metrics,marina-timeline,marina-comparison). If any showstemplate_name: "marina-content"uniformly across all slides, step B may have skipped the per-subtopic layout picking — re-check and patch withupsertNodeif needed for visual variety. - Make Array connection: Each "Topic #X - Subtopic #Y" → "Make Array"
item_<pin>. Topic slides start atitem_1. #outro is always on the last pin. - #outro connected: "#outro" output
slide_html→ Make Array last pin. If #outro is NOT connected, the presentation will have no closing slide. Fix immediately. - Theme consistency: Presentation Composer
theme == "marina"AND PPTX Convertertheme == "marina". If either drifted to another theme (e.g. default"white"), fix withupsertNode. If ANY Slide Generator node showsoutputs: [], it is missing its Make Array edge. Fix ALL missing connections withupsertEdgebefore proceeding.
- #Intro on item_0: "#Intro" output
nodeFinder→ find "PPTX Converter" by label.- Execute both terminal nodes sequentially:
a.
nodeExecutor→ execute "PPTX Converter" (node id from step 16). Wait for completion. The system auto-runs all upstream nodes (#Intro + all topic slides + #outro → Make Array → Presentation Composer → PPTX Converter). When complete, a.pptxfile is available for download. b.nodeFinder→ find "Public Share" by label.nodeExecutor→ execute it. Because Presentation Composer has already produced its HTML output in step 17a, Public Share will resolve quickly. On completion, the Public Share node returns a publicurl.
Both terminal executions must complete before step 18. If either fails, retry per the "retry 3×, then ask the user" rule in the Execution Strategy preamble — do NOT skip either output silently.
(Legacy note): The system auto-runs all upstream nodes (#Intro + all topic slides + #outro → Make Array → Presentation Composer → PPTX Converter). Wait for completion.
18. verification → run a final audit and present the results to the user as a checklist before summarizing. Items array (use info severity ✓ for passing checks, warning/error for real issues found):
- Make Array has exactly total_subtopics + 2 inputs
- #Intro is on item_0
- #outro is on the last Make Array pin
- Every "Topic #X - Subtopic #Y" Slide Generator has a content edge from "Contenuto Presentazione"
- Every "Topic #X - Subtopic #Y" Slide Generator has a valid marina content layout (marina-content, marina-metrics, marina-timeline, or marina-comparison)
- Presentation Composer theme == "marina" and PPTX Converter theme == "marina"
- autoLayout was applied in step 15a (canvas has been laid out left-to-right along the edge flow; no node is stacked on top of another unless part of the locked Prototype section)
- Both "PPTX Converter" AND "Public Share" completed successfully. PPTX Converter produced a downloadable .pptx file; Public Share produced a shareable url
followUp— summarize what was done (mention both deliverables: the.pptxfile from PPTX Converter and the Public Shareurl): N topics, M_x subtopics per topic, total slides = total_subtopics + 2 (intro + outro), theme = Marina Militare. The PPTX file is available for download.
Common User Requests → Configuration Tips
Error Handling
- MANIFEST_NOT_FOUND: Documents not processed. User needs to upload them to a KnowledgeBase first.
- Connection refused: Check that www-emblema is running at the correct EMBLEMA_API_BASE_URL.
- Empty slides: Cloned Slide Generator nodes do NOT inherit external edges. Verify that "Contenuto Presentazione"
[summary]→ each Slide Generator[content]edge exists. Also check the "Contenuto Presentazione" prompt includes all topics/subtopics with their full names. - No topics or subtopics in output: If "Selezione dei Topic Principali" returns no topics or fewer subtopics than expected, the document may not have enough content. Try providing more source material or adjusting the prompt to be less restrictive.
- Missing "Contenuto Presentazione" content: If the prompt was not updated with all topics/subtopics, or if topic names are wrong, the Slide Generators will produce incomplete or mismatched slides. Always verify the prompt matches step 6 output exactly.
- Connected slide_html → undefined: The
targetNodeIdortargetPortwas invalid. Verify Make Array nodeId is a valid UUID fromnodeFinderand theitem_Xpin number is correct. Always validate nodeIds before passing toupsertEdge. - Nodes still named "Topic #x - Subtopic #x":
cloneNodeswith a singlenodeIdsdoes NOT rename the cloned node. You MUST callupsertNodewithlabelto rename each clone (Step B). - All slides are
marina-contentuniformly: Step B's per-subtopic layout picking was skipped. Go back and patch each cloned node withupsertNodeto set the right layout (marina-timeline/marina-metrics/marina-comparison) based on the subtopic's content shape. - User requested image layouts: Marina v1 has no
marina-image-leftormarina-image-right. Respond with the polite refusal from the Common User Requests table above. Do NOT silently use vanillaimage-left/image-right— they are unbranded and break the marina visual identity. If the user specifically wants to add marina image layouts to the theme itself, that is a separate theme-extension task: new CSS in_MR_CSS, newTEMPLATE_INSTRUCTIONSentries inslide_generator.py, new entries inslide-templates.ts, new SVG thumbnails, and an executor rebuild. Direct the user to request that separately. - Theme drifted from marina: If Presentation Composer or PPTX Converter
themefield shows anything other than"marina"(e.g. default"white"), fix withupsertNode({ nodeId: <found ID>, input: { theme: "marina" } }). Both nodes must match.
Cross-references
apps/workspace-service/app/templates/themes/marina/— staging folder for the marina theme adaptation work (source Reveal.js files + extracted CSS / base64 artifacts).apps/workspace-service/app/templates/MARINA_SLIDES_CATALOG.md— full catalog of the marina-* slide layouts (including the 18 aspirational layouts not yet shipped in v1).apps/workspace-service/app/templates/sample_marina_briefing.md— ready-to-feed mock briefing content covering every marina-* layout in this document, grounded in publicly-verifiable Marina Militare facts.apps/workspace-service/app/templates/ADDING_PRESENTATION_THEMES.md— procedure for adding or extending marina (e.g. if you want to shipmarina-image-left/marina-image-rightlater).apps/workspace-service/app/templates/reference/pptx-from-drive.md— the polpostale-flavored sibling of this document. Use it for Polizia Postale or Emblema theme workflows.apps/workspace-service/app/templates/presentation_composer.py— composer source with_MR_CSS(marina theme CSS),CUSTOM_THEMES["marina"], andTHEME_DIMENSIONS["marina"] = (1920, 1080).apps/workspace-service/app/templates/slide_generator.py— slide generator with the 6marina-*entries inTEMPLATE_INSTRUCTIONS.
// Dependencies
1from input import DriveFolderReader2from input import DriveDocumentReader3from process import SlideGenerator4from process import MakeArray5from output import PresentationComposer6from output import PPTXConverter7from process import RecursiveSummarizer8from output import PublicShare$ git log --oneline
set slide as default transition for composer
unlocked sections