ELNOR REPO READER TEXT MIRROR Original path: Design Mockups/DOC23 Mockups/Q_TASK_MODULAR_CANVAS_V11_ALT_C_DOC20_INTEGRATION_PREVIEW.jsx Source repo: /Users/OpenClaw1/Elnor/Elnor Specs Git branch: main Git commit: dbaa25962edc11ab30e8d4ca1715f9ae5bf77331 Generated: 2026-06-09T01:23:58.539Z --- import React, { useState, useCallback, useRef } from "react"; // ═══════════════════════════════════════════════════════════════ // Q TASK SYSTEM — MODULAR CANVAS V11 ALT C — DOC20 SHELL + INSPECTOR REFINEMENT // Experimental Mode: DOC20 main-area integration, graph⇄inspector navigation, // module output links, artifact/delivery access, context inspector, and Task Agent side panel // ═══════════════════════════════════════════════════════════════ const c = { bg:"#0f1117", bgCard:"#161920", bgHover:"#1c1f2a", bgSel:"#1e2233", bgPanel:"#131620", bgPopup:"#1a1e2b", border:"#262a36", text:"#e2e4ea", textSec:"#8b8fa3", textTer:"#5d6178", accent:"#5b8af5", green:"#34d399", red:"#f87171", amber:"#fbbf24", purple:"#a78bfa", cyan:"#22d3ee", orange:"#fb923c", }; const sans = "-apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif"; const mono = "'SF Mono','Cascadia Code','Fira Code', monospace"; const catColor = { trigger:c.amber, step:c.accent, utility:c.purple, output:c.green, source:c.cyan, environment:"#8b9cf5", system:c.orange }; const catLabel = { trigger:"TRIGGER", step:"ACTION", utility:"UTILITY", output:"OUTPUT", source:"SOURCE", environment:"ENVIRON", system:"SYSTEM" }; const catIcon = { trigger:"⚡", step:"◆", utility:"⑂", output:"→", source:"◇", environment:"◎", system:"⊙" }; // ── CONFIG SCHEMAS ── const MC = { "trigger.manual":[{t:"n",v:"Fires when you click ▶ Run. You can optionally provide launch data (text or files) in the Run dialog."},{t:"n",v:"Resuming a paused task does NOT re-fire this trigger — resume continues from wherever execution was paused."},{t:"hd",l:"Manual Fire"},{t:"n",v:"Use the button below to fire this trigger independently (e.g., when the task is running and you want to re-inject at this point)."},{t:"btn",l:"▶ Fire Now"}], "trigger.schedule":[ {t:"s",l:"Schedule Type",o:["Recurring interval","Day of week + time","Specific date & time (one-shot)"],v:"Recurring interval"}, {t:"hd",l:"Recurring Interval"}, {t:"row",items:[{t:"i",l:"Every",v:"1"},{t:"s",l:"Unit",o:["minutes","hours","days","weeks"],v:"days"}]}, {t:"hd",l:"Day of Week + Time"}, {t:"n",v:"Select one or more days:"}, {t:"tags",l:"Days",v:["Sun"]}, {t:"row",items:[{t:"i",l:"Time",v:"16:00",p:"HH:MM"},{t:"s",l:"Timezone",o:["America/Los_Angeles","America/New_York","America/Chicago","UTC"],v:"America/Los_Angeles"}]}, {t:"hd",l:"One-Shot"}, {t:"i",l:"Date & Time 📅",v:"",p:"calendar + time picker in app"}, {t:"n",v:"All date/time fields render as calendar picker + hours/minutes/AM-PM selector in the built app. ISO format shown in mockup only."}, {t:"hd",l:"Common"}, {t:"i",l:"End Date",v:"",p:"blank = no end"}, {t:"c",l:"Enabled",ck:true}], "trigger.email":[ {t:"n",v:"Fires when a matching email arrives. Wire outputs to route the email body, attachments, or both to downstream modules. Use the output port selector to choose what data to send."}, {t:"s",l:"Condition Logic",o:["ALL must match (AND)","ANY can match (OR)"],v:"ALL must match (AND)"}, {t:"n",v:"Blank fields are ignored. Supports boolean: term AND term, term OR term, \"exact phrase\"."}, {t:"hd",l:"Recipient Filter"}, {t:"i",l:"Email Address",v:"",p:"will@schall.com"}, {t:"c",l:"Match in To",ck:true}, {t:"c",l:"Match in CC",ck:true}, {t:"c",l:"Match in BCC",ck:false}, {t:"hd",l:"Sender & Content Filters"}, {t:"i",l:"From",v:"",p:"*@opposing.com"}, {t:"i",l:"Subject Contains",v:"",p:"keyword AND keyword, \"exact phrase\""}, {t:"i",l:"Subject Exact",v:"",p:"exact subject line"}, {t:"i",l:"Body Contains",v:"",p:"keyword OR keyword"}, {t:"hd",l:"Attachment Filters"}, {t:"c",l:"Must have attachment",ck:false}, {t:"i",l:"Attachment Type",v:"",p:"*.pdf, *.docx"}, {t:"i",l:"Attachment Name Contains",v:"",p:"filename keyword AND keyword"}, {t:"i",l:"Attachment Content Contains",v:"",p:"search inside attachments, term OR term"}, {t:"n",v:"Content search: text-extractable files only (PDF, DOCX, TXT). First 50 pages searched."}, {t:"c",l:"Ignore auto-replies",ck:true}], "trigger.file_watcher":[ {t:"s",l:"Watch For",o:["New file","Modified","Deleted","Any change"],v:"New file"}, {t:"i",l:"Folder Path 📁",v:"",p:"click 📁 to browse or type path"}, {t:"n",v:"📁 opens Finder to select a folder. Add multiple paths to watch several folders."}, {t:"tags",l:"Additional Paths",v:[]}, {t:"i",l:"File Type Filter",v:"",p:"*.pdf, *.docx"}, {t:"i",l:"Ignore Pattern",v:"",p:"~$*, .tmp, .DS_Store"}, {t:"hd",l:"Content Filters (text files only)"}, {t:"i",l:"Title Contains",v:"",p:"keyword AND keyword, \"exact phrase\""}, {t:"i",l:"Document Contains",v:"",p:"term OR term, \"exact phrase\""}], "trigger.discord":[ {t:"i",l:"Channel",v:"",p:"channel name or ID (blank = any)"}, {t:"i",l:"Keyword Filter",v:"",p:"comma-separated keywords"}, {t:"i",l:"User Filter",v:"",p:"username (blank = any)"}, {t:"s",l:"Attachments",o:["Any","Must have","Must not have"],v:"Any"}], "trigger.task_complete":[ {t:"s",l:"Listen For",o:["Task completed","Output received from task"],v:"Task completed"}, {t:"s",l:"Wait Mode",o:["Any listed task","ALL listed tasks"],v:"Any listed task"}, {t:"ta",l:"Task References",v:"",h:50,p:"task IDs, one per line"}, {t:"i",l:"Output Module Ref",v:"",p:"paste output.task module ref (for 'output received')"}, {t:"c",l:"Send my result back to calling task when I finish",ck:false}, {t:"n",v:"'Task completed' passes the completed task's final output as data_out. 'Output received' passes whatever the sending output.task module included. Position determines behavior — first module = new run, mid-chain = resume."}], "trigger.forum_panel":[ {t:"i",l:"Target Panel/Forum ID",v:"",p:"blank = any"}, {t:"i",l:"Keyword Filter",v:"",p:"searches panel posts (not output document)"}, {t:"s",l:"Event Type",o:["Panel complete (any outcome)","Consensus reached","Post created","Any event"],v:"Panel complete (any outcome)"}, {t:"hd",l:"Pass Through"}, {t:"s",l:"Data to pass downstream",o:["Panel output document","Panel posts (all rounds)","Both (output + posts)","Summary of posts"],v:"Panel output document"}, {t:"n",v:"Panel output document = the consensus/final result. Panel posts = the full discussion. 'Both' bundles them. 'Summary' runs a lightweight agent summary of the discussion."}], "trigger.webhook":[ {t:"i",l:"Webhook Path",v:"filing-processor-hook",p:"auto-generated"}, {t:"n",v:"URL: https://elnor.local/hooks/{path}"}, {t:"ta",l:"Expected Fields (JSON)",v:"",h:50,p:'{"filing_id":"string"}'}, {t:"i",l:"HMAC Secret",v:"",p:"optional verification secret"}], "step.agent_task":[ {t:"hd",l:"Agent"}, {t:"s",l:"Agent Mode",o:["Task default","Named agent","Spawn new"],v:"Task default"}, {t:"n",v:"'Task default' = inherits from Task Settings (all fields below disabled). 'Named agent' = pick a registered agent. 'Spawn new' = one-off agent, agent dropdown hidden, model required."}, {t:"s",l:"Agent (for Named agent mode)",o:["Elnor","Nova","Prism","Atlas","Sage"],v:"Elnor"}, {t:"row",items:[{t:"s",l:"Model",o:["(agent default)","claude-opus-4-6","claude-sonnet-4-6","gemini-2.5-pro"],v:"(agent default)"},{t:"s",l:"Think Level",o:["(default)","off","minimal","low","medium","high","xhigh"],v:"(default)"}]}, {t:"row",items:[{t:"s",l:"Fallback Model",o:["(global chain)","claude-sonnet-4-6","gemini-2.5-pro"],v:"(global chain)"},{t:"i",l:"Cost Limit ($)",v:"10.00"}]}, {t:"ta",l:"Instruction",v:"",h:100,p:"What should the agent do with the input?"}, {t:"tags",l:"📎 Attachments",v:["filing_2026-03-15.pdf"]}, {t:"s",l:"If Data Exceeds Context Budget",o:["Fail (safest)","Chunk & iterate","Truncate with warning"],v:"Fail (safest)"}, {t:"hd",l:"Chain History"}, {t:"s",l:"History for this module",o:["Use environment default","Last N steps","None"],v:"Use environment default"}, {t:"i",l:"Last N Steps",v:"",p:"blank = environment default"}, {t:"c",l:"Summarize older history (vs drop entirely)",ck:true}, {t:"hd",l:"Retry & Timeout"}, {t:"row",items:[{t:"i",l:"Max Retries",v:"0"},{t:"i",l:"Backoff (min)",v:"1",p:"minutes — supports decimals"}]}, {t:"s",l:"Retry On",o:["Retryable only (timeout, rate limit)","All errors"],v:"Retryable only (timeout, rate limit)"}, {t:"i",l:"Call Timeout (min)",v:"",p:"blank = 20 min (agent default). Panel/Red Team = no timeout."}, {t:"hd",l:"Named File Outputs"}, {t:"tags",l:"Outputs",v:["Analysis","Prompt"]}, {t:"btn",l:"+ Add Output"}, {t:"n",v:"Each name becomes a wireable output port on this module. CIL auto-instructs the agent to name files matching these labels. Wire each named output to its destination — e.g., '📄 Analysis' → Email body, '📄 Prompt' → next agent's instruction_in."}, {t:"hd",l:"Session Continuity"}, {t:"c",l:"Continue prior agent session",ck:false}, {t:"n",v:"When enabled, this module dispatches into the upstream agent module's existing session instead of opening a new one. The agent retains full conversation context — including its prior reasoning and decisions — from the upstream step. Requires same model. Only works with direct upstream agent connections (not through Junctions)."}], "step.transform":[ {t:"s",l:"Transform Type",o:["Summarize","Extract fields","Format / convert","Merge inputs","Redact","Split"],v:"Summarize"}, {t:"hd",l:"Summarize (LLM call)"}, {t:"ta",l:"Summarize Instructions",v:"",h:60,p:"Executive summary of key findings, bullet point deadlines, one paragraph for a partner"}, {t:"s",l:"Agent Mode",o:["Task default","Named agent","Spawn new"],v:"Task default"}, {t:"row",items:[{t:"s",l:"Agent",o:["Elnor","Nova","Prism","Atlas","Sage"],v:"Elnor"},{t:"i",l:"Target Word Count",v:"",p:"blank = auto"}]}, {t:"hd",l:"Extract"}, {t:"s",l:"Extract Mode",o:["Agent extract (describe fields)","Structured JSONPath (JSON input only)"],v:"Agent extract (describe fields)"}, {t:"ta",l:"Fields to Extract",v:"",h:50,p:"Filing date, Case number, Parties, Deadline dates"}, {t:"s",l:"Extract Agent Mode",o:["Task default","Named agent","Spawn new"],v:"Task default"}, {t:"s",l:"Extract Agent",o:["Elnor","Nova","Prism","Atlas","Sage"],v:"Elnor"}, {t:"i",l:"JSONPath Expression",v:"",p:"$.decision.date (structured mode only)"}, {t:"hd",l:"Format"}, {t:"s",l:"Output Format",o:["DOCX","PDF","MD","TXT"],v:"MD"}, {t:"hd",l:"Redact"}, {t:"ta",l:"Redact Patterns",v:"",h:40,p:"Regex or exact strings, one per line. Matched text → [REDACTED]"}, {t:"n",v:"Examples: \\d{3}-\\d{2}-\\d{4} (SSN), John Henderson (name), \\d{3}-\\d{3}-\\d{4} (phone)"}, {t:"hd",l:"Split (no LLM — deterministic)"}, {t:"s",l:"Split Mode",o:["Text delimiter (split text by markers)","File pattern (route files by name)"],v:"Text delimiter (split text by markers)"}, {t:"i",l:"Delimiters (for text)",v:"",p:"===ANALYSIS===, ===PROMPT=== (each becomes a named output port)"}, {t:"n",v:"Text split: sections between delimiters route to separate output ports named after the delimiter. File split: FileRefs route by filename pattern."}, {t:"tags",l:"File Patterns (for file split)",v:[]}, {t:"n",v:"Add name patterns. Each becomes a named output port. FileRefs with matching filenames route to that port. Unmatched files go to Data Out."}], "step.user_review_gate":[ {t:"ta",l:"Review Instructions",v:"",h:70,p:"What should the reviewer evaluate? Shown alongside the output."}, {t:"hd",l:"Notifications"}, {t:"c",l:"Dashboard notification",ck:true}, {t:"c",l:"Discord notification",ck:false}, {t:"c",l:"Email notification",ck:true}, {t:"i",l:"Email To",v:"will@schall.com",p:"who gets the review email"}, {t:"i",l:"Email Subject",v:"Review needed: {{task_name}} — {{step_name}}",p:"customizable subject"}, {t:"c",l:"Include full output in email",ck:true}, {t:"c",l:"Include review instructions in email",ck:true}, {t:"c",l:"Accept revision instructions via email reply",ck:true}, {t:"n",v:"Reply to the notification email to send revision instructions. Reply with APPROVE or REJECT to take those actions directly."}, {t:"hd",l:"On Rejection"}, {t:"s",l:"Reject Action",o:["Pause task","Redirect to module","Abort task"],v:"Pause task"}, {t:"i",l:"Redirect Target",v:"",p:"module ID (if redirect)"}, {t:"i",l:"Max Redirects",v:"3",p:"safety cap for redirect loops"}, {t:"hd",l:"On Revision"}, {t:"n",v:"Revision instructions and file attachments are submitted via the Review Card tab. Your text + attached files route through revision_out to the receiving step."}, {t:"i",l:"Max Revisions",v:"3",p:"after this, forces final approve/reject"}, {t:"s",l:"Revision Delivery",o:["Route through revision_out (wire to target)","Auto-send to previous step"],v:"Route through revision_out (wire to target)"}], "step.agent_review_gate":[ {t:"hd",l:"Reviewing Agent"}, {t:"s",l:"Agent Mode",o:["Task default","Named agent","Spawn new"],v:"Task default"}, {t:"row",items:[{t:"s",l:"Agent",o:["Elnor","Nova","Prism","Atlas","Sage"],v:"Nova"},{t:"s",l:"Model",o:["(agent default)","claude-opus-4-6","claude-sonnet-4-6"],v:"(agent default)"}]}, {t:"row",items:[{t:"s",l:"Think Level",o:["(default)","off","minimal","low","medium","high","xhigh"],v:"medium"},{t:"i",l:"Cost Limit ($)",v:"5.00"}]}, {t:"ta",l:"Review Criteria / Instructions",v:"",h:80,p:"What should the reviewer check? How should it evaluate the content?"}, {t:"hd",l:"Decision Mode"}, {t:"s",l:"How the agent decides pass/fail",o:["LLM judgment (default)","Keyword match","Always pass (log only)"],v:"LLM judgment (default)"}, {t:"i",l:"Pass Threshold",v:"",p:"e.g. no critical issues, all citations verified"}, {t:"n",v:"LLM judgment: agent makes holistic assessment. Keyword match: scan response for pass/fail keywords (cheaper, deterministic). Always pass: agent runs analysis but always routes to approved_out."}, {t:"tags",l:"Pass Keywords",v:[]}, {t:"tags",l:"Fail Keywords (checked first)",v:[]}, {t:"hd",l:"On Rejection"}, {t:"ta",l:"Feedback agent should provide on rejection",v:"",h:50,p:"Explain what failed, suggest specific revisions, produce a redlined version if applicable"}, {t:"n",v:"The reviewing agent's feedback + any revised documents flow through the failed_out port. Wire failed_out to the originating step's instruction_in to send revisions back, or to a notification, human review, or any handler."}, {t:"s",l:"If Data Exceeds Context Budget",o:["Fail (safest)","Truncate with warning"],v:"Fail (safest)"}, {t:"hd",l:"Retry (optional)"}, {t:"row",items:[{t:"i",l:"Max Retries",v:"0"},{t:"i",l:"Backoff (min)",v:"1"}]}], "step.panel":[ {t:"s",l:"Panel Mode",o:["Create new panel","Use existing panel","Paste panel reference ID"],v:"Use existing panel"}, {t:"i",l:"Panel ID / Reference",v:"",p:"select or paste panel ID"}, {t:"n",v:"'Create new' opens the panel setup page — configure agents, rounds, consensus there. Saves and links back automatically. 'Use existing' shows a list of your panels."}, {t:"hd",l:"Output Timing"}, {t:"s",l:"Output On",o:["Panel complete (final result only)","Each round (fires per round)","Both (round_out + complete_out ports)"],v:"Panel complete (final result only)"}, {t:"n",v:"'Each round' fires data_out after every round — downstream modules run once per round. 'Both' gives two output ports: Round Output and Final Result. Wire each where needed."}, {t:"ta",l:"Additional Instructions",v:"",h:50,p:"Context or instructions beyond what the panel preset defines"}, {t:"i",l:"Cost Cap ($)",v:"5.00"}], "step.pass_through":[{t:"n",v:"Forwards input data unchanged. Use as a waypoint or annotation node."}], "step.red_team":[ {t:"s",l:"Red Team Preset",o:["Select preset...","truth_seeking_standard","high_stakes_review","exploratory_broad"],v:"Select preset..."}, {t:"i",l:"Or Paste Preset ID",v:"",p:"preset reference ID"}, {t:"n",v:"Presets define the full red team configuration — reviewers, rounds, finding limits, evidence mode, adjudication policy. Configure presets in the Red Team settings page."}, {t:"ta",l:"Additional Instructions / Context",v:"",h:50,p:"Optional: focus areas, special concerns, context beyond the preset"}, {t:"hd",l:"Documents"}, {t:"n",v:"Drag additional reference files from Browser or Finder."}, {t:"tags",l:"Attached",v:[]}, {t:"i",l:"Cost Cap ($)",v:"",p:"blank = preset default"}], "step.coding":[ {t:"ta",l:"Instruction",v:"",h:80,p:"What should the coding agent(s) build, fix, or modify?"}, {t:"hd",l:"Agents"}, {t:"n",v:"Assign 1-5 ACP-connected coding agents. Each agent gets the instruction + its role-specific override. Drag to reorder (affects sequential/review_chain execution order)."}, {t:"row",items:[{t:"i",l:"Role",v:"builder",p:"builder, reviewer, tester..."},{t:"s",l:"Agent",o:["Task Default","claude-code","codex","gemini-code","+ New Agent"],v:"claude-code"}]}, {t:"s",l:"ACP Profile Override",o:["(use module default)","dev-sandbox","prod-readonly","full-access"],v:"(use module default)"}, {t:"ta",l:"Role Instructions",v:"",h:40,p:"Role-specific instruction appended to shared instruction"}, {t:"btn",l:"+ Add Agent",v:"add_agent"}, {t:"hd",l:"Workspace"}, {t:"s",l:"ACP Profile",o:["Select profile...","dev-sandbox","prod-readonly","full-access"],v:"Select profile..."}, {t:"i",l:"Working Directory",v:"",p:"/path/to/workspace"}, {t:"n",v:"Reference Roots — additional read-only paths for spec docs, reference code."}, {t:"tags",l:"Reference Roots",v:[]}, {t:"hd",l:"Session"}, {t:"row",items:[{t:"s",l:"Style",o:["Persistent","One-shot"],v:"Persistent"},{t:"s",l:"Completion",o:["Agent Signals","Tests Pass","Iteration Limit"],v:"Agent Signals"}]}, {t:"i",l:"Test Command",v:"",p:"npm test, pytest, etc. (visible when Tests Pass)"}, {t:"i",l:"Max Iterations",v:"",p:"blank = no limit"}, {t:"hd",l:"Limits"}, {t:"row",items:[{t:"i",l:"Cost Limit ($)",v:"",p:"blank = task-level"},{t:"i",l:"Time Limit (min)",v:"",p:"blank = ACP default"}]}, {t:"hd",l:"Output Capture"}, {t:"c",l:"Capture Diff",ck:true}, {t:"c",l:"Capture Test Results",ck:true}], "system.experiment":[ {t:"n",v:"Run 2-4 variant configurations against the same input. Compare models, agents, instructions, or any combination. Wire the target cable from an existing module to auto-copy its config as the baseline."}, {t:"hd",l:"Target Module"}, {t:"n",v:"Wire the target cable FROM an existing module to auto-populate. Or configure manually below."}, {t:"s",l:"Target Type",o:["(auto from target cable)","step.agent_task","step.transform","step.coding"],v:"(auto from target cable)"}, {t:"hd",l:"Variants"}, {t:"n",v:"Configure 2-4 variants. Variant A is the baseline (matches target module). Use the ↗ Expand button above for side-by-side variant editing."}, {t:"s",l:"Variant A Label",o:["Variant A (Baseline)"],v:"Variant A (Baseline)"}, {t:"s",l:"Variant B Agent",o:["(same as A)","Elnor","Nova","Atlas","Sage","+ Configure..."],v:"Nova"}, {t:"i",l:"Variant B Label",v:"Nova",p:"Display label"}, {t:"c",l:"Variant B — same instruction as A",ck:true}, {t:"hd",l:"Run Mode"}, {t:"s",l:"Execution",o:["Parallel (all at once)","Sequential (one at a time)"],v:"Parallel (all at once)"}, {t:"btn",l:"↗ Open Expanded View"}], "step.judge":[ {t:"n",v:"Score outputs on configurable dimensions. Wire target_in from any module. Wire comparison_in from an Experiment module for A/B comparison. Wire evidence_in from red team or review modules."}, {t:"hd",l:"Scoring Preset"}, {t:"s",l:"Load Preset",o:["(custom)","Save current...","Manage presets..."],v:"(custom)"}, {t:"hd",l:"Dimensions"}, {t:"i",l:"Dimension 1 Name",v:"Accuracy",p:"e.g., Accuracy, Completeness, Clarity"}, {t:"s",l:"Method",o:["Claim Verification","Checklist","Consistency Check","Subjective Analysis"],v:"Claim Verification"}, {t:"ta",l:"Criteria",v:"List every factual assertion. Verify each against evidence sources. Count supported vs contradicted.",h:50}, {t:"i",l:"Dimension 2 Name",v:"Completeness",p:""}, {t:"s",l:"Method",o:["Claim Verification","Checklist","Consistency Check","Subjective Analysis"],v:"Checklist"}, {t:"ta",l:"Criteria",v:"Required: scope definition, methodology, key findings, recommendations, limitations",h:40}, {t:"i",l:"Dimension 3 Name",v:"Overall Quality",p:""}, {t:"s",l:"Method",o:["Claim Verification","Checklist","Consistency Check","Subjective Analysis"],v:"Subjective Analysis"}, {t:"ta",l:"Criteria",v:"Holistic assessment considering all evidence. Identify specific strengths and weaknesses.",h:40}, {t:"btn",l:"+ Add Dimension"}, {t:"hd",l:"Judge Agent"}, {t:"s",l:"Agent",o:["Task default","Elnor","Nova","Prism","Atlas","Sage"],v:"Elnor"}, {t:"row",items:[{t:"s",l:"Model",o:["(agent default)","claude-opus-4-6","claude-sonnet-4-6"],v:"claude-opus-4-6"},{t:"s",l:"Think Level",o:["(default)","high","xhigh"],v:"high"}]}, {t:"hd",l:"DSPy Optimization"}, {t:"c",l:"Enable prompt optimization",ck:false}, {t:"n",v:"When enabled, the judge's scoring dimensions become the DSPy metric function. After scoring, click 'Suggest Improvements' to optimize the target module's instruction."}, {t:"s",l:"Optimizer",o:["GEPA (recommended)","MIPROv2 (lighter)"],v:"GEPA (recommended)"}, {t:"s",l:"Reflection Agent",o:["claude-opus-4-6","claude-sonnet-4-6"],v:"claude-opus-4-6"}, {t:"s",l:"Intensity",o:["Light (~$2)","Medium (~$5)","Heavy (~$15)"],v:"Medium (~$5)"}, {t:"i",l:"Min Examples Required",v:"10",p:"10"}, {t:"btn",l:"↗ Open Expanded View"}], "utility.junction":[ {t:"s",l:"Mode",o:["AND — Wait for all inputs","OR — Route based on options below","MERGE — Combine into one document"],v:"AND — Wait for all inputs"}, {t:"n",v:"MERGE joins all inputs into one text document with section headers per source. No AI — for intelligent synthesis, wire output to an Agent Task."}, {t:"i",l:"Section Header Format",v:"## {module_name}",p:"use {module_name} variable"}, {t:"row",items:[{t:"i",l:"Timeout (min)",v:"",p:"none"},{t:"s",l:"On Timeout",o:["Fire with partial data","Error"],v:"Fire with partial data"}]}, {t:"hd",l:"OR Mode Options"}, {t:"s",l:"When additional inputs arrive",o:["Ignore (first input only)","Fire again for each"],v:"Ignore (first input only)"}, {t:"n",v:"Output is always text/markdown. Mixed input types (PDF text, agent output, JSON) are converted to text. For specific file formats, wire output to a Transform module."}], "utility.switch":[ {t:"hd",l:"Routing Conditions"}, {t:"n",v:"First match wins. Each condition routes to its own output port. Select a condition to edit its fields below."}, {t:"s",l:"Active Condition",o:["Condition 1 → Route A","Condition 2 → Route B","Condition 3 → Route C","Condition 4 → Route D","+ Add Condition"],v:"Condition 1 → Route A"}, {t:"hd",l:"Condition Settings (for selected condition)"}, {t:"s",l:"Type",o:["Contains (boolean)","Does not contain","Pattern match (regex)","Character count >","Character count <","Equals exactly","Agent evaluates"],v:"Contains (boolean)"}, {t:"i",l:"Value / Search Term",v:"",p:"term AND term, \"exact phrase\", NOT term"}, {t:"n",v:"Contains / Does not contain: supports boolean syntax — AND, OR, NOT, \"exact phrase\", (groups). Character count: enter a number — total characters in the primary content. Equals exactly: entire content must be this string and nothing else (e.g., agent outputs 'APPROVED')."}, {t:"hd",l:"Agent Eval (when type = Agent evaluates)"}, {t:"s",l:"Agent Mode",o:["Task default","Named agent","Spawn new"],v:"Task default"}, {t:"s",l:"Eval Agent",o:["Elnor","Nova","Prism","Atlas","Sage"],v:"Elnor"}, {t:"s",l:"Think Level",o:["(default)","off","minimal","low","medium","high","xhigh"],v:"(default)"}, {t:"ta",l:"Agent Instruction",v:"",h:60,p:"Read the input and decide: does this indicate the motion was granted? Answer YES or NO."}, {t:"n",v:"Per-condition: each condition can use a different agent and instruction. Agent reads input, returns yes/no judgment. Adds cost per evaluation."}, {t:"hd",l:"Default"}, {t:"s",l:"If no conditions match",o:["Error (task fails)","Route to Default output"],v:"Route to Default output"}, {t:"n",v:"Default is a separate output port. If nothing matches and no default is wired, the module errors."}], "utility.delay":[ {t:"s",l:"Delay Mode",o:["Duration","Until specific time"],v:"Duration"}, {t:"hd",l:"Duration"}, {t:"row",items:[{t:"i",l:"Delay",v:"30"},{t:"s",l:"Unit",o:["minutes","hours","days"],v:"minutes"}]}, {t:"hd",l:"Until Time (when mode = Until specific time)"}, {t:"s",l:"Schedule Type",o:["Specific date & time","Day of week + time","Time only (every day)"],v:"Day of week + time"}, {t:"i",l:"Date",v:"",p:"2026-04-01 (for specific date)"}, {t:"row",items:[{t:"i",l:"Time",v:"09:00",p:"HH:MM"},{t:"s",l:"Timezone",o:["America/Los_Angeles","America/New_York","America/Chicago","UTC"],v:"America/Los_Angeles"}]}, {t:"n",v:"Days (select one or more):"}, {t:"tags",l:"Days",v:["Mon","Wed","Fri"]}, {t:"c",l:"Batch mode — collect all inputs during the delay window and release together as one bundle",ck:false}], "utility.hold":[ {t:"s",l:"Hold Mode",o:["Until release signal","Until specific time","Until signal AND time (both required)","Until signal OR time (whichever first)"],v:"Until release signal"}, {t:"n",v:"'Signal AND time' = both must be met before release. Signal arrives early? Waits for time. Time passes? Waits for signal.\n'Signal OR time' = whichever comes first releases the data."}, {t:"hd",l:"Release Signal Options"}, {t:"i",l:"Max wait for release signal (min)",v:"",p:"blank = wait indefinitely"}, {t:"s",l:"If signal doesn't arrive in time",o:["Release data anyway","Error"],v:"Release data anyway"}, {t:"hd",l:"Scheduled Release (when mode includes time)"}, {t:"s",l:"Schedule Type",o:["Specific date & time","Day of week + time","Time only (every day)"],v:"Day of week + time"}, {t:"i",l:"Date",v:"",p:"2026-04-01 (for specific date)"}, {t:"row",items:[{t:"i",l:"Time",v:"09:00",p:"HH:MM"},{t:"s",l:"Timezone",o:["America/Los_Angeles","America/New_York","America/Chicago","UTC"],v:"America/Los_Angeles"}]}, {t:"n",v:"Days (select one or more):"}, {t:"tags",l:"Days",v:["Mon","Tue","Wed","Thu","Fri"]}], "utility.loop":[ {t:"i",l:"Max Iterations",v:"5"}, {t:"s",l:"Stop Condition",o:["Fixed count","Agent judgment","External signal"],v:"Fixed count"}, {t:"ta",l:"Stop / Judgment Criteria",v:"",h:50,p:"Fixed count: enter a number. Agent judgment: describe what 'done' looks like. External: leave blank."}, {t:"hd",l:"Judgment Agent (when Stop = Agent judgment)"}, {t:"s",l:"Agent Mode",o:["Task default","Named agent","Spawn new"],v:"Task default"}, {t:"row",items:[{t:"s",l:"Agent",o:["Elnor","Nova","Prism","Atlas","Sage"],v:"Elnor"},{t:"s",l:"Model",o:["(agent default)","claude-opus-4-6","claude-sonnet-4-6"],v:"(agent default)"}]}, {t:"row",items:[{t:"s",l:"Think Level",o:["(default)","off","minimal","low","medium","high","xhigh"],v:"(default)"},{t:"i",l:"Cost Limit ($)",v:"2.00"}]}, {t:"i",l:"Loop Timeout (min)",v:"",p:"none"}, {t:"hd",l:"Loop Instruction"}, {t:"s",l:"Instructions for pass",o:["Pass 1","Pass 2","Pass 3","Pass 4","Pass 5"],v:"Pass 1"}, {t:"ta",l:"Agent instruction for this pass",v:"",h:70,p:"Analyze this filing for all CCP deadlines."}, {t:"n",v:"Select each pass from the dropdown and write its instruction. Blank passes inherit the previous pass's instruction. The system auto-prepends iteration context (e.g., 'This is pass 2 of 5. The content below is your prior output.'). Wire instruction_out → agent's instruction_in."}, {t:"c",l:"Include original input as reference on every pass",ck:false}, {t:"n",v:"When checked, each pass receives the original input (from pass 1) alongside the latest output — useful for comparing revisions against the source document."}, {t:"hd",l:"Error Handling"}, {t:"s",l:"On Iteration Error",o:["Stop loop","Skip to next iteration","Retry with delay"],v:"Stop loop"}, {t:"row",items:[{t:"s",l:"Retries",o:["1","2","3","4"],v:"2"},{t:"i",l:"Delay Between (min)",v:"1",p:"minutes"}]}, {t:"n",v:"Stop: terminates loop, fires error_out. Skip: discards failed result, tries next with last good data. Retry: retries N times with delay — all fail → stops loop, fires error_out."}, {t:"hd",l:"Wiring"}, {t:"n",v:"Wire loop_out → data_in on the module to repeat. Wire instruction_out → instruction_in on the same module. Wire that module's data_out → return_in. Each pass, the agent gets fresh data + your instructions + iteration context."}, {t:"n",v:"stop_in is a latch. Signal on stop_in = finish current iteration, then route return_in data to done_out (no more loops). Data on stop_in = that data goes to done_out immediately. Use with a Switch: route 'needs work' → return_in, route 'approved' signal → stop_in."}], "utility.context_filter":[ {t:"hd",l:"How agent context works"}, {t:"n",v:"Each agent step receives three types of input:\n• Operative data — the previous step's output (what the agent works on)\n• Chain history — outputs from earlier steps, auto-accumulated\n• Explicit context — anything you wired to context_in ports\n\nThis filter controls the first two. Explicit context is never filtered — you wired it on purpose."}, {t:"hd",l:"Operative Data"}, {t:"c",l:"Keep operative data (the output from the previous step)",ck:true}, {t:"hd",l:"Chain History"}, {t:"c",l:"Keep chain history (outputs from earlier steps, auto-carried by CIL)",ck:false}, {t:"i",l:"Max chain history items",v:"",p:"blank = keep all"}, {t:"i",l:"Drop history older than N steps back",v:"",p:"blank = no limit"}, {t:"c",l:"Summarize older history to reference-only (instead of dropping)",ck:true}, {t:"n",v:"When checked, items beyond the kept window are compressed to title + one-line summary. When unchecked, they're dropped entirely. Overrides the environment-level chain history policy at this point in the chain."}, {t:"hd",l:"Filter by Specific Module"}, {t:"i",l:"Remove history from these modules",v:"",p:"module IDs, comma-separated"}, {t:"i",l:"Keep ONLY history from these modules",v:"",p:"module IDs, comma-separated"}, {t:"n",v:"Copy a module's ID from the bottom of its detail panel. 'Remove from' strips specific modules' outputs from the history. 'Keep only from' discards everything except those modules' outputs. Use one or the other, not both."}], "utility.manual_switch":[ {t:"s",l:"Default Position",o:["A","B","C","D"],v:"A"}, {t:"n",v:"Which output is active when the task starts. Signals on switch_a/b/c/d flip the routing — they don't pass data through. Data on data_in goes to whichever output is currently active."}, {t:"hd",l:"How It Works"}, {t:"n",v:"Wire signals from other modules (e.g., Agent Review approved_out, Switch signal_out, Human Review) to switch_a/b/c/d to control which path data takes. Wire the content to data_in. The switch remembers its position until a new signal flips it."}, {t:"n",v:"Example: Agent Review approved_out → switch_b flips routing to B. Next data on data_in goes to out_b (the 'done' path) instead of out_a (the 'revise' path)."}], "output.email":[ {t:"i",l:"From Account",v:"",p:"elnor@schall.com (type or select from settings)"}, {t:"n",v:"Which email account Elnor sends from. Leave blank for the default sending account."}, {t:"i",l:"To",v:"will@schall.com"}, {t:"row",items:[{t:"i",l:"CC",v:"",p:"cc@"},{t:"i",l:"BCC",v:"",p:"bcc@"}]}, {t:"i",l:"Subject",v:"{{task_name}} — {{step_name}}"}, {t:"hd",l:"Email Body — check what to include"}, {t:"n",v:"Check one or more. Custom message is always first in the body. If none checked, email has no body (subject + attachments only)."}, {t:"c",l:"Custom message (always appears first)",ck:false}, {t:"ta",l:"Custom Message",v:"",h:60,p:"Hi Will,\n\nPlease see the attached analysis.\n\nTask: {{task_name}} · {{date}}"}, {t:"n",v:"Supports {{task_name}}, {{step_name}}, {{date}}, {{output_summary}}. Exactly what you type is sent."}, {t:"c",l:"Include body input content (from data_in port)",ck:true}, {t:"c",l:"Agent composes body (agent writes or rewrites using instruction below)",ck:false}, {t:"n",v:"When 'Agent composes' is checked with other items, the agent sees all checked body items as context and produces the final body. Agent instructions from instruction_in port are always included when wired — no checkbox needed."}, {t:"s",l:"Agent Mode",o:["Task default","Named agent","Spawn new"],v:"Task default"}, {t:"row",items:[{t:"s",l:"Agent (for Named agent)",o:["Elnor","Nova","Prism","Atlas","Sage"],v:"Elnor"},{t:"s",l:"Think Level",o:["(default)","off","minimal","low","medium","high","xhigh"],v:"(default)"}]}, {t:"ta",l:"Instructions to Agent",v:"",h:50,p:"Write a professional summary. Keep it under 3 paragraphs."}, {t:"hd",l:"Attachments — check what to attach"}, {t:"c",l:"Attach files from attachment_in port (attached as-is, original format)",ck:false}, {t:"c",l:"Attach body input as file (converts data_in text to selected format)",ck:false}, {t:"s",l:"Attachment Format (for body-as-file)",o:["DOCX","PDF","MD","TXT"],v:"PDF"}, {t:"n",v:"Both can be checked — explicit file attachments AND a converted text attachment. All body/attachment content is auto-stripped of internal metadata."}], "output.file":[ {t:"hd",l:"File Format"}, {t:"s",l:"Format",o:["Preserve original (no conversion)","DOCX","PDF","MD","TXT"],v:"Preserve original (no conversion)"}, {t:"n",v:"'Preserve original' keeps the file in whatever format it arrived (e.g., a .docx from an agent stays .docx). If input is text with no file format, falls back to MD."}, {t:"hd",l:"File Naming"}, {t:"s",l:"Name Source",o:["Custom template","Use original file name as base","Use name from specific module","Agent determines name"],v:"Custom template"}, {t:"i",l:"Filename Template (for Custom)",v:"",p:"{{task_name}}_{{step_name}}_{{date}}"}, {t:"i",l:"Module Ref (for Use name from module)",v:"",p:"paste module ref ID — traces FileRef provenance"}, {t:"n",v:"'Original name' = takes the file name from the input FileRef (after filtering out email signatures, inline images, vCards). If multiple files remain after filtering, falls back to template. 'From module' traces the FileRef provenance chain back to that module's output to find the original name."}, {t:"c",l:"Append date to file name",ck:false}, {t:"hd",l:"Agent Naming (when Name Source or Directory = Agent determines)"}, {t:"s",l:"Agent Mode",o:["Task default","Named agent","Spawn new"],v:"Task default"}, {t:"row",items:[{t:"s",l:"Agent",o:["Elnor","Nova","Prism","Atlas","Sage"],v:"Elnor"},{t:"s",l:"Think Level",o:["(default)","off","minimal","low","medium","high","xhigh"],v:"(default)"}]}, {t:"ta",l:"Naming Instructions",v:"",h:50,p:"Name the file based on the case number and filing type from the document content."}, {t:"n",v:"One agent handles both file naming and directory decisions. Naming instructions and directory instructions are both sent to this agent."}, {t:"hd",l:"Save Location"}, {t:"s",l:"Directory Source",o:["Fixed path","Agent determines"],v:"Fixed path"}, {t:"i",l:"Directory Path 📁",v:"",p:"click 📁 to browse or type path"}, {t:"ta",l:"Directory Instructions (for Agent determines)",v:"",h:50,p:"Save in the case folder matching the case number. Create a subfolder if it doesn't exist."}, {t:"i",l:"Top-Level Directory Constraint 📁",v:"",p:"agent can only create within this boundary"}, {t:"n",v:"For 'Agent determines': the agent chooses the folder based on your instructions, but cannot save outside the top-level directory. Security constraint."}, {t:"hd",l:"If File Already Exists (never overwrites)"}, {t:"s",l:"Versioning",o:["Add version number (V2, V3...)","Add date-time suffix","Error (don't save)"],v:"Add version number (V2, V3...)"}, {t:"n",v:"Existing files are NEVER overwritten. If a file already exists at the save path, the selected versioning rule applies automatically."}], "output.chat":[ {t:"s",l:"Mode",o:["New chat","Existing chat"],v:"New chat"}, {t:"i",l:"Chat ID",v:"",p:"for existing chat"}, {t:"hd",l:"Agent"}, {t:"s",l:"Agent Mode",o:["Task default","Named agent","Spawn new"],v:"Task default"}, {t:"s",l:"Post As",o:["Elnor","Nova","Prism","Atlas","Sage"],v:"Elnor"}, {t:"hd",l:"Content Format"}, {t:"s",l:"How to deliver",o:["Inline message (text in chat)","Document attachment","Both (summary inline + full doc attached)"],v:"Inline message (text in chat)"}, {t:"n",v:"'Inline' = output appears as a chat message. 'Attachment' = output sent as a document file in the chat. 'Both' = short summary inline + full output attached."}, {t:"hd",l:"Chat Naming (for New Chat)"}, {t:"c",l:"Auto-name chat after task",ck:true}, {t:"i",l:"Name Template",v:"{{task_name}} — {{date}}",p:"{{task_name}} — {{date}}"}, {t:"n",v:"For repetitive tasks, each run creates a new chat with the run date appended."}], "output.notify":[ {t:"tags",l:"Channels",v:["dashboard","email"]}, {t:"s",l:"Severity",o:["Info","Warning","Urgent"],v:"Info"}, {t:"ta",l:"Message",v:"",h:50,p:"{{task_name}} complete. {{output_summary}}"}, {t:"c",l:"Include full content",ck:false}], "output.memory":[ {t:"s",l:"Memory Tier",o:["Active (relevant topics)","Core (always available)"],v:"Active (relevant topics)"}, {t:"tags",l:"Tags",v:["filing-analysis"]}, {t:"c",l:"Include source attribution",ck:true}], "output.webhook":[ {t:"i",l:"Target URL",v:"",p:"https://api.example.com/"}, {t:"s",l:"Method",o:["POST","PUT","PATCH"],v:"POST"}, {t:"ta",l:"Headers (JSON)",v:"",h:40,p:'{"Authorization":"Bearer ..."}'}, {t:"ta",l:"Payload Template",v:"",h:50,p:'{"data":"{{data}}"}'}], "output.imessage":[ {t:"i",l:"Recipient",v:"",p:"phone or contact name"}, {t:"ta",l:"Message Template",v:"",h:60,p:"{{task_name}}: {{output_summary}}"}], "output.forum":[ {t:"s",l:"Mode",o:["New thread","Existing thread","New panel"],v:"New thread"}, {t:"i",l:"Thread/Panel ID",v:"",p:"for existing"}, {t:"i",l:"Title",v:"",p:"thread title"}, {t:"tags",l:"Tags",v:[]}], "output.task":[ {t:"i",l:"Target Task ID",v:"",p:"task to send data to"}, {t:"c",l:"Include this step's data in the payload",ck:true}, {t:"hd",l:"Link"}, {t:"n",v:"Copy this module's ref ID and paste it into the receiving task's Task Event trigger 'Output Module Ref' field."}], "source.file":[ {t:"i",l:"File Path / Note ID 📁",v:"",p:"click 📁 to browse or type path"}, {t:"ta",l:"Typed Content",v:"",h:50,p:"Enter text directly as source content. Can be used alongside or instead of a file."}, {t:"n",v:"If you provide both a file AND typed content, they are combined per the Combine mode below."}, {t:"ta",l:"About This Source",v:"",h:35,p:"Background info shown to the agent alongside this material. E.g., 'Henderson motion filed 3/20.'"}, {t:"ta",l:"Agent Instructions",v:"",h:35,p:"Tells the agent how to use this material. E.g., 'Use Section 4 for CCP deadline calculations.'"}, {t:"n",v:"'About This Source' describes what it is (shown as context). 'Agent Instructions' tells the agent what to do with it (framed in the instruction section of the prompt)."}, {t:"s",l:"Combine With Incoming",o:["Append","Prepend","Merge","Replace"],v:"Append"}, {t:"n",v:"Combine mode controls how this source's content merges with data arriving on data_in. Only affects this module's output — does not touch context routing on downstream modules. 'Replace' discards incoming data entirely."}, {t:"hd",l:"Global Availability"}, {t:"c",l:"Make available to ALL agent steps (via reference listing)",ck:false}, {t:"n",v:"When enabled, this source appears in every agent step's 'Available References' listing. Agents can fetch it via tool call — content is NOT auto-injected into prompts. Wire to context_in for explicit inclusion."}, {t:"i",l:"Reference Title (optional)",v:"",p:"defaults to module name"}, {t:"ta",l:"Reference Description (optional)",v:"",h:30,p:"defaults to 'About This Source' text above"}], "source.bucket":[ {t:"i",l:"Bucket ID",v:"",p:"select or enter bucket"}, {t:"ta",l:"About This Source",v:"",h:40,p:"Background info shown to the agent. E.g., 'California CCP rules — use for deadline calculations.'"}, {t:"s",l:"Combine With Incoming",o:["Append","Prepend","Merge","Replace"],v:"Append"}, {t:"hd",l:"Global Availability"}, {t:"c",l:"Make available to ALL agent steps (via reference listing)",ck:false}], "source.project":[ {t:"i",l:"Project ID",v:"",p:"select project"}, {t:"c",l:"Include project's context buckets",ck:true}, {t:"c",l:"Include project's background instructions",ck:true}, {t:"s",l:"Combine With Incoming",o:["Append","Prepend","Merge","Replace"],v:"Append"}], "environment.config":[ {t:"hd",l:"Global Instructions"}, {t:"n",v:"Injected directly into every agent prompt. Keep concise — this text is in every step's context window."}, {t:"ta",l:"Objective",v:"",h:60,p:"High-level task goal. First line of every agent prompt."}, {t:"ta",l:"Behavioral Directives",v:"",h:50,p:"Cite CCP sections. Formal legal writing."}, {t:"i",l:"Agent Role",v:"",p:"Litigation paralegal for Henderson v. City of LA"}, {t:"hd",l:"Project Context"}, {t:"i",l:"Project 📁",v:"",p:"select project (inherits project buckets + instructions)"}, {t:"hd",l:"Context Buckets (DOC7)"}, {t:"tags",l:"Attached Buckets",v:["california_ccp_rules","henderson_case_docs"]}, {t:"n",v:"Buckets always available to all agent steps. Content accessed via tool calls, not injected into prompts."}, {t:"hd",l:"Reference Library"}, {t:"n",v:"NOT injected into prompts. Listed by name + description only. Agents fetch full content via tool calls."}, {t:"tags",l:"Reference Items 📁",v:["CCP_Rules.pdf","Henderson_docket.csv","calendaring_memo.md"]}, {t:"n",v:"Drag from Browser or Finder, or click +. Items stored as references — full content resolved at runtime."}, {t:"hd",l:"Chain History Policy"}, {t:"s",l:"Mode",o:["Progressive decay (default)","Keep last N steps only","Off (no chain history)"],v:"Progressive decay (default)"}, {t:"row",items:[{t:"i",l:"Full Fidelity Steps",v:"2",p:"2"},{t:"i",l:"Summarized Through Step",v:"5",p:"5"}]}, {t:"i",l:"Keep Last N Steps",v:"",p:"blank = use decay rules above"}, {t:"c",l:"Summarize older items to reference-only (instead of dropping)",ck:true}, {t:"c",l:"Show available buckets in agent prompts",ck:true}, {t:"i",l:"Max Pinned (📌) Modules",v:"5",p:"5"}, {t:"n",v:"Progressive decay: steps within 'Full Fidelity' range are uncompressed. Steps through 'Summarized' range get ~50% compression. Beyond that: listed-only (title + summary, retrievable via tool). 'Off' = no chain history — each module sees only wired inputs. Max Pinned controls how many modules can have 📌 Carry Forward enabled (max 10)."}], "system.monitor":[ {t:"n",v:"Optional — basic notifications (task complete, task error, review gates) work without this module. Monitor adds extra channels, verbosity control, and custom error handling."}, {t:"hd",l:"Extra Notification Channels"}, {t:"tags",l:"Also notify via",v:["discord"]}, {t:"n",v:"Dashboard notifications are always on. Add channels here for system events beyond what individual modules already send."}, {t:"hd",l:"Activity Feed"}, {t:"s",l:"Verbosity",o:["Errors only","Milestones","All events"],v:"Milestones"}, {t:"n",v:"Controls what appears in the Run Inspector activity feed."}, {t:"hd",l:"Unhandled Error Policy"}, {t:"s",l:"When error_out fires but isn't wired",o:["Notify only (task fails)","Pause & notify (resumable)"],v:"Notify only (task fails)"}, {t:"n",v:"Without this module, unhandled errors fail the task with a dashboard notification. This lets you override that to pause (resumable) instead."}], }; const universalTrigger = [ {t:"hd",l:"Trigger Options"}, {t:"c",l:"Delay before running",ck:false}, {t:"row",items:[{t:"i",l:"Delay",v:"",p:"0"},{t:"s",l:"Unit",o:["minutes","hours","days"],v:"minutes"}]}, {t:"c",l:"Keep listening (repeat)",ck:true}, {t:"c",l:"Cooldown between runs",ck:false}, {t:"row",items:[{t:"i",l:"Cooldown",v:"",p:"0"},{t:"s",l:"Unit",o:["minutes","hours"],v:"minutes"}]}, ]; // ── CABLE FAMILIES ── const cableFamilies = { data:["#1e3a8a","#3b5fc0","#5b8af5","#88b0ff","#b8d4ff","#dbeaff","#2850b0"], signal:["#92400e","#b87a08","#fbbf24","#fde68a","#d4a017","#eab020"], error:["#991b1b","#f87171","#fca5a5"], context:["#0e7490","#22d3ee","#a5f3fc"], }; function getCableColor(cable,idx){const f=cableFamilies[cable.role]||cableFamilies.data;return f[idx%f.length];} // ── PORT POPUP CHOICES ── const outputChoices = { "trigger.email":[{id:"data_out",label:"Full Email",desc:"Body + metadata + attachments (FileRefs)",color:c.accent},{id:"body_out",label:"Email Body",desc:"Body text only — no attachments, no metadata",color:c.cyan},{id:"attachment_out",label:"Attachments",desc:"Attachment FileRefs only",color:c.cyan},{id:"signal_out",label:"⚡ Signal",color:c.amber}], "trigger.file_watcher":[{id:"data_out",label:"Data Out",desc:"File content + event metadata",color:c.accent},{id:"file_only_out",label:"File Only",desc:"FileRef to watched file — no metadata",color:c.cyan},{id:"signal_out",label:"⚡ Signal",color:c.amber}], "trigger.discord":[{id:"data_out",label:"Data Out",color:c.accent},{id:"attachment_out",label:"Attachments",desc:"Message attachments (images, files)",color:c.cyan},{id:"signal_out",label:"⚡ Signal",color:c.amber}], "trigger.webhook":[{id:"data_out",label:"Data Out",desc:"Parsed JSON payload",color:c.accent},{id:"signal_out",label:"⚡ Signal",color:c.amber}], "trigger.forum_panel":[{id:"data_out",label:"Data Out",color:c.accent},{id:"signal_out",label:"⚡ Signal",color:c.amber}], "trigger.task_complete":[{id:"data_out",label:"Data Out",color:c.accent},{id:"file_only_out",label:"Files Only",desc:"FileRefs from the completed task's output",color:c.cyan},{id:"signal_out",label:"⚡ Signal",color:c.amber}], "step.agent_task":[{id:"data_out",label:"Data Out",desc:"Full output — text, file refs, chain history",color:c.accent},{id:"file_only_out",label:"File Only",desc:"FileRef(s) from created/edited files — no text, no history",color:c.cyan},{id:"signal_out",label:"⚡ Signal",color:c.amber},{id:"error_out",label:"⚠ Error",color:c.red}], "step.transform":[{id:"data_out",label:"Data Out",color:c.accent},{id:"file_only_out",label:"File Only",desc:"Converted file output",color:c.cyan},{id:"signal_out",label:"⚡ Signal",color:c.amber},{id:"error_out",label:"⚠ Error",desc:"LLM or conversion failure",color:c.red}], "step.red_team":[{id:"data_out",label:"Data Out",color:c.accent},{id:"file_only_out",label:"File Only",desc:"Annotated document file",color:c.cyan},{id:"signal_out",label:"⚡ Signal",color:c.amber},{id:"error_out",label:"⚠ Error",color:c.red}], "step.coding":[{id:"data_out",label:"Summary",desc:"Session summary — what was done, decisions, final state",color:c.accent},{id:"diff_out",label:"Diff",desc:"Structured changeset — files created/modified/deleted",color:c.cyan},{id:"test_results_out",label:"Test Results",desc:"Pass/fail with stdout/stderr",color:c.green},{id:"files_out",label:"Files",desc:"FileRefs to workspace files changed",color:c.amber},{id:"file_only_out",label:"Files Only",desc:"Same FileRefs in ContextBundle format",color:c.dim},{id:"signal_out",label:"⚡ Signal",color:c.amber},{id:"receipt_out",label:"Receipt",desc:"Session metadata — keys, duration, cost",color:c.dim},{id:"error_out",label:"⚠ Error",color:c.red}], "system.experiment":[{id:"variant_a_out",label:"Variant A",desc:"Baseline result",color:"#5b8af5"},{id:"variant_b_out",label:"Variant B",desc:"Variant B result",color:c.amber},{id:"variant_c_out",label:"Variant C",desc:"Variant C result (if configured)",color:c.purple},{id:"comparison_out",label:"⚖ Comparison",desc:"All variants bundled for Judge auto-config",color:c.cyan},{id:"signal_out",label:"⚡ Signal",color:c.amber},{id:"error_out",label:"⚠ Error",color:c.red}], "step.judge":[{id:"scores_out",label:"Scores",desc:"Structured dimension scores with audit trail",color:c.green},{id:"analysis_out",label:"Analysis",desc:"Qualitative assessment text",color:c.cyan},{id:"recommendation_out",label:"Recommendation",desc:"Which variant is stronger and why",color:c.accent},{id:"optimization_out",label:"DSPy Candidate",desc:"Optimized prompt body (when DSPy enabled)",color:c.purple},{id:"signal_out",label:"⚡ Signal",color:c.amber},{id:"error_out",label:"⚠ Error",color:c.red}], "step.panel":[{id:"complete_out",label:"Final Result",color:c.green},{id:"round_out",label:"Round Output",color:c.cyan},{id:"individual_out",label:"Individual Responses",color:c.purple},{id:"signal_out",label:"⚡ Signal",color:c.amber},{id:"error_out",label:"⚠ Error",color:c.red}], "step.user_review_gate":[{id:"approved_out",label:"If Approved",color:c.green},{id:"rejected_out",label:"If Rejected",color:c.red},{id:"revision_out",label:"If Revision",color:c.amber},{id:"signal_out",label:"⚡ Signal",color:c.amber}], "step.agent_review_gate":[{id:"approved_out",label:"If Passed",color:c.green},{id:"failed_out",label:"If Failed",color:c.red},{id:"signal_out",label:"⚡ Signal",color:c.amber},{id:"error_out",label:"⚠ Error",desc:"Agent failed to produce review",color:c.red}], "utility.loop":[{id:"loop_out",label:"Loop Out",desc:"Data to the module that repeats",color:c.cyan},{id:"instruction_out",label:"Loop Instruction",desc:"Dynamic instruction for each pass",color:c.purple},{id:"done_out",label:"Done Out",desc:"Final result after last iteration",color:c.green},{id:"signal_out",label:"⚡ Signal",color:c.amber},{id:"error_out",label:"⚠ Error",color:c.red}], "utility.switch":[{id:"out_a",label:"Route A"},{id:"out_b",label:"Route B"},{id:"out_c",label:"Route C"},{id:"out_d",label:"Route D"},{id:"default_out",label:"Default (no match)"},{id:"signal_any",label:"⚡ Signal: Any route decided",color:c.amber},{id:"signal_a",label:"⚡ Signal: Route A decided",color:c.amber},{id:"signal_b",label:"⚡ Signal: Route B decided",color:c.amber},{id:"signal_c",label:"⚡ Signal: Route C decided",color:c.amber},{id:"signal_d",label:"⚡ Signal: Route D decided",color:c.amber}], "utility.manual_switch":[{id:"out_a",label:"Output A"},{id:"out_b",label:"Output B"},{id:"out_c",label:"Output C"},{id:"out_d",label:"Output D"},{id:"signal_out",label:"⚡ Signal",color:c.amber}], "trigger.manual":[{id:"data_out",label:"Data Out",color:c.accent},{id:"signal_out",label:"⚡ Signal",color:c.amber}], "trigger.schedule":[{id:"data_out",label:"Data Out",color:c.accent},{id:"signal_out",label:"⚡ Signal",color:c.amber}], "step.pass_through":[{id:"data_out",label:"Data Out",color:c.accent},{id:"signal_out",label:"⚡ Signal",color:c.amber}], "utility.junction":[{id:"data_out",label:"Data Out",color:c.accent},{id:"signal_out",label:"⚡ Signal",color:c.amber},{id:"error_out",label:"⚠ Error",color:c.red}], "utility.delay":[{id:"data_out",label:"Data Out",color:c.accent},{id:"signal_out",label:"⚡ Signal",color:c.amber},{id:"error_out",label:"⚠ Error",desc:"Invalid timezone, config error",color:c.red}], "utility.hold":[{id:"data_out",label:"Data Out",color:c.accent},{id:"signal_out",label:"⚡ Signal",color:c.amber},{id:"error_out",label:"⚠ Error",desc:"Timeout with error action",color:c.red}], "utility.context_filter":[{id:"data_out",label:"Data Out",color:c.accent},{id:"signal_out",label:"⚡ Signal",color:c.amber}], "output.email":[{id:"data_out",label:"Pass-through",desc:"Original data_in forwarded",color:c.accent},{id:"receipt_out",label:"Receipt",desc:"Delivery confirmation",color:c.green},{id:"signal_out",label:"⚡ Signal",color:c.amber},{id:"error_out",label:"⚠ Error",color:c.red}], "output.file":[{id:"data_out",label:"Pass-through",color:c.accent},{id:"receipt_out",label:"Receipt",desc:"Save record",color:c.green},{id:"signal_out",label:"⚡ Signal",color:c.amber},{id:"error_out",label:"⚠ Error",color:c.red}], "output.chat":[{id:"data_out",label:"Pass-through",color:c.accent},{id:"receipt_out",label:"Receipt",color:c.green},{id:"signal_out",label:"⚡ Signal",color:c.amber},{id:"error_out",label:"⚠ Error",color:c.red}], "output.notify":[{id:"data_out",label:"Pass-through",color:c.accent},{id:"receipt_out",label:"Receipt",color:c.green},{id:"signal_out",label:"⚡ Signal",color:c.amber},{id:"error_out",label:"⚠ Error",color:c.red}], "output.memory":[{id:"data_out",label:"Pass-through",color:c.accent},{id:"receipt_out",label:"Receipt",color:c.green},{id:"signal_out",label:"⚡ Signal",color:c.amber}], "output.webhook":[{id:"data_out",label:"Pass-through",color:c.accent},{id:"receipt_out",label:"Receipt",desc:"Response payload",color:c.green},{id:"signal_out",label:"⚡ Signal",color:c.amber},{id:"error_out",label:"⚠ Error",color:c.red}], "output.imessage":[{id:"data_out",label:"Pass-through",color:c.accent},{id:"receipt_out",label:"Receipt",color:c.green},{id:"signal_out",label:"⚡ Signal",color:c.amber},{id:"error_out",label:"⚠ Error",color:c.red}], "output.forum":[{id:"data_out",label:"Pass-through",color:c.accent},{id:"receipt_out",label:"Receipt",color:c.green},{id:"signal_out",label:"⚡ Signal",color:c.amber},{id:"error_out",label:"⚠ Error",color:c.red}], "output.task":[{id:"data_out",label:"Pass-through",color:c.accent},{id:"receipt_out",label:"Receipt",desc:"Envelope confirmation",color:c.green},{id:"signal_out",label:"⚡ Signal",color:c.amber},{id:"error_out",label:"⚠ Error",color:c.red}], "source.file":[{id:"data_out",label:"Data Out",color:c.accent},{id:"signal_out",label:"⚡ Signal",color:c.amber},{id:"error_out",label:"⚠ Error",desc:"File not found, permission denied",color:c.red}], "source.bucket":[{id:"data_out",label:"Data Out",color:c.accent},{id:"signal_out",label:"⚡ Signal",color:c.amber},{id:"error_out",label:"⚠ Error",desc:"Bucket unavailable",color:c.red}], "source.project":[{id:"data_out",label:"Data Out",color:c.accent},{id:"signal_out",label:"⚡ Signal",color:c.amber},{id:"error_out",label:"⚠ Error",color:c.red}], }; const loopInputChoices=[ {id:"data_in",label:"Initial Data",desc:"First iteration data",color:c.accent}, {id:"return_in",label:"Continue Looping",desc:"Output from looped module — loop iterates again (unless stop latched)",color:c.cyan}, {id:"stop_in",label:"Stop Looping (latch)",desc:"Signal = finish current pass, then done. Data = done immediately.",color:c.amber}, ]; const holdInputChoices=[ {id:"data_in",label:"Data to Hold",desc:"Content to hold until released",color:c.accent}, {id:"release_in",label:"Release Signal",desc:"When this fires, held data passes through",color:c.amber}, ]; const manualSwitchInputChoices=[ {id:"data_in",label:"Data to Route",desc:"Content routed to whichever output is currently active",color:c.accent}, {id:"switch_a",label:"Switch to A",desc:"Flip routing to output A (signal only — no data passes through)",color:c.amber}, {id:"switch_b",label:"Switch to B",desc:"Flip routing to output B",color:c.amber}, {id:"switch_c",label:"Switch to C",desc:"Flip routing to output C",color:c.amber}, {id:"switch_d",label:"Switch to D",desc:"Flip routing to output D",color:c.amber}, ]; function needsInputPopup(t){return ["step.agent_task","step.agent_review_gate","step.panel","step.red_team","step.coding","step.judge","system.experiment","utility.loop","utility.hold","utility.manual_switch","utility.switch","output.email","output.file","output.chat","output.notify","output.forum"].includes(t);} function getInputChoices(t){ if(t==="utility.loop") return loopInputChoices; if(t==="utility.hold") return holdInputChoices; if(t==="utility.manual_switch") return manualSwitchInputChoices; if(t==="utility.switch") return switchInputChoices; if(t==="step.agent_review_gate") return agentReviewInputChoices; if(t==="step.coding") return codingInputChoices; if(t==="system.experiment") return experimentInputChoices; if(t==="step.judge") return judgeInputChoices; if(t==="step.panel") return panelInputChoices; if(t==="output.email") return emailOutputInputChoices; if(t==="output.chat") return chatOutputInputChoices; if(t==="output.file") return fileOutputInputChoices; if(t==="output.notify") return notifyInputChoices; if(t==="output.forum") return forumOutputInputChoices; return inputChoices; } const switchInputChoices=[ {id:"data_in",label:"Content to Evaluate",desc:"Primary content the conditions are evaluated against.",color:c.accent}, {id:"context_in",label:"Background Context",desc:"Reference material for agent_eval conditions. Files the agent should inspect.",color:c.cyan}, ]; const agentReviewInputChoices=[ {id:"data_in",label:"Content to Review",desc:"Primary material the reviewing agent evaluates.",color:c.accent}, {id:"context_in",label:"Background Context",desc:"Reference material, standards, criteria documents for the reviewer.",color:c.cyan}, {id:"attachment_in",label:"File Attachment",desc:"File(s) the reviewer should inspect alongside the primary content.",color:c.amber}, {id:"instruction_in",label:"Agent Instructions",desc:"Dynamic instructions for the reviewing agent.",color:c.purple}, ]; const codingInputChoices=[ {id:"data_in",label:"Coding Task",desc:"Primary instruction/specification — what to build, fix, or modify.",color:c.accent}, {id:"context_in",label:"Reference Material",desc:"Spec documents, existing code, architecture notes. Add multiple for separate sources.",color:c.cyan}, {id:"instruction_in",label:"Dynamic Instruction",desc:"Per-activation instruction overlay — e.g., revision feedback from a review loop.",color:c.purple}, ]; const experimentInputChoices=[ {id:"target",label:"⚗ Target Module",desc:"Wire FROM an existing module to auto-copy its config as baseline. The module continues running normally.",color:c.orange}, {id:"data_in",label:"Input Data",desc:"Override input data. If unwired, uses the target module's data_in.",color:c.accent}, {id:"context_in",label:"Shared Context",desc:"Reference material shared across all variants.",color:c.cyan}, {id:"instruction_in",label:"Shared Instruction",desc:"Dynamic instruction applied to all variants.",color:c.purple}, ]; const judgeInputChoices=[ {id:"target_in",label:"Target Output",desc:"The primary output being evaluated. Required.",color:c.accent}, {id:"comparison_in",label:"⚖ Comparison",desc:"A/B comparison bundle from Experiment, or a second output for comparison.",color:c.cyan}, {id:"evidence_in",label:"Evidence",desc:"Red team findings, review outputs, reference material. Add multiple evidence sources.",color:c.amber}, ]; const emailOutputInputChoices=[ {id:"data_in",label:"Email Body Content",desc:"Text/data that becomes the email body.",color:c.accent}, {id:"recipient_in",label:"Dynamic Recipient",desc:"Email address(es) — overrides the static To field. Wire from a trigger or agent output.",color:c.green}, {id:"attachment_in",label:"File Attachment",desc:"File(s) to attach to this email. FileRefs attached as-is.",color:c.amber}, {id:"context_in",label:"Delivery Context",desc:"Reference material (e.g., original file for name matching).",color:c.cyan}, {id:"instruction_in",label:"Agent Instructions",desc:"Dynamic instructions for how to compose the email.",color:c.purple}, ]; const chatOutputInputChoices=[ {id:"data_in",label:"Chat Content",desc:"Text/data posted to the chat.",color:c.accent}, {id:"attachment_in",label:"File Attachment",desc:"File(s) to attach in the chat conversation.",color:c.amber}, {id:"context_in",label:"Delivery Context",desc:"Reference material for formatting or context.",color:c.cyan}, {id:"instruction_in",label:"Agent Instructions",desc:"Dynamic instructions for how to format the post.",color:c.purple}, ]; const panelInputChoices=[ {id:"data_in",label:"Discussion Topic",desc:"Content the panel will discuss.",color:c.accent}, {id:"context_in",label:"Background Context",desc:"Reference material for panelists.",color:c.cyan}, ]; const fileOutputInputChoices=[ {id:"data_in",label:"Content to Save",desc:"Text or file to save to disk.",color:c.accent}, {id:"attachment_in",label:"Files to Save",desc:"FileRefs to save alongside or instead of data_in.",color:c.amber}, {id:"context_in",label:"Naming Context",desc:"Original file for name retention, formatting examples.",color:c.cyan}, {id:"instruction_in",label:"Naming Instructions",desc:"Dynamic instructions for agent-determined naming/directory.",color:c.purple}, ]; const notifyInputChoices=[ {id:"data_in",label:"Content to Deliver",desc:"Primary material included in the notification.",color:c.accent}, {id:"context_in",label:"Delivery Context",desc:"Additional context for notification formatting.",color:c.cyan}, ]; const forumOutputInputChoices=[ {id:"data_in",label:"Content to Post",desc:"Text/data posted to the forum or panel.",color:c.accent}, {id:"context_in",label:"Delivery Context",desc:"Reference material for the post.",color:c.cyan}, {id:"instruction_in",label:"Agent Instructions",desc:"Dynamic instructions for how to compose the post.",color:c.purple}, ]; const outputInputChoices=[ {id:"data_in",label:"Content to Deliver",desc:"Primary material to format and send.",color:c.accent}, {id:"context_in",label:"Delivery Context",desc:"Reference material (e.g., original file for name matching, formatting examples).",color:c.cyan}, {id:"instruction_in",label:"Agent Instructions",desc:"Dynamic instructions for how to compose/format the delivery.",color:c.purple}, ]; const inputChoices=[ {id:"data_in",label:"Process",desc:"Primary material to work on. Chain history from prior steps included automatically.",color:c.accent}, {id:"context_in",label:"Background Context",desc:"Reference material, separate from main flow. Framed as 'for reference' in prompt.",color:c.cyan}, {id:"instruction_in",label:"Agent Instructions",desc:"Dynamic instructions that add to this step's static instruction.",color:c.purple}, ]; // ── PALETTE DATA ── const palTypes = { trigger:[ {t:"trigger.manual",n:"Manual",d:"Fire on click or command"}, {t:"trigger.schedule",n:"Schedule",d:"Timer / recurring interval"}, {t:"trigger.email",n:"Email In",d:"Watch inbox for emails"}, {t:"trigger.file_watcher",n:"File Watcher",d:"Watch folder for changes"}, {t:"trigger.discord",n:"Discord In",d:"Watch channel for messages"}, {t:"trigger.task_complete",n:"Task Event",d:"Another task completes or sends output"}, {t:"trigger.forum_panel",n:"Forum / Panel",d:"Forum post or panel consensus"}, {t:"trigger.webhook",n:"Webhook / API",d:"Receive external POST"}, ], step:[ {t:"step.agent_task",n:"Agent Task",d:"LLM agent processes input"}, {t:"step.transform",n:"Transform",d:"Deterministic processing"}, {t:"step.user_review_gate",n:"Human Review",d:"Pause for your approval"}, {t:"step.agent_review_gate",n:"Agent Review",d:"Automated quality check"}, {t:"step.panel",n:"Panel Discussion",d:"Multi-agent deliberation"}, {t:"step.red_team",n:"Red Team",d:"Send to red team preset"}, {t:"step.coding",n:"Coding Session",d:"ACP coding agent session"}, {t:"step.judge",n:"Judge",d:"Score outputs on configurable dimensions"}, {t:"step.pass_through",n:"Pass-through",d:"Forward data unchanged"}, ], utility:[ {t:"utility.junction",n:"Junction",d:"Combine inputs (AND/OR/MERGE)"}, {t:"utility.switch",n:"Switch / Router",d:"Conditional routing"}, {t:"utility.delay",n:"Delay",d:"Hold signal for a duration"}, {t:"utility.loop",n:"Loop Controller",d:"Iterate until condition"}, {t:"utility.context_filter",n:"Context Filter",d:"Control what chain history passes through"}, {t:"utility.hold",n:"Hold",d:"Hold data until release signal"}, {t:"utility.manual_switch",n:"Manual Switch",d:"Signal-controlled routing (A/B/C/D)"}, ], output:[ {t:"output.email",n:"Email Out",d:"Send email"}, {t:"output.file",n:"File Out",d:"Save to filesystem"}, {t:"output.chat",n:"Chat Out",d:"Post to Q chat"}, {t:"output.notify",n:"Notify",d:"Send notification"}, {t:"output.memory",n:"Memory Out",d:"Save to ELNOR memory"}, {t:"output.webhook",n:"Webhook Out",d:"POST to external URL"}, {t:"output.imessage",n:"iMessage Out",d:"Send via Messages"}, {t:"output.forum",n:"Forum Out",d:"Post to forum"}, {t:"output.task",n:"Task Out",d:"Send data to another task"}, ], source:[ {t:"source.file",n:"File / User Input",d:"Provide a file or typed content"}, {t:"source.bucket",n:"Bucket",d:"DOC7 context bucket"}, {t:"source.project",n:"Project",d:"Project context"}, ], environment:[ {t:"environment.config",n:"Environment",d:"Objective, role, skills, buckets + reference library"}, ], system:[ {t:"system.monitor",n:"Monitor",d:"Telemetry & error catch-all"}, {t:"system.experiment",n:"Experiment",d:"Compare 2-4 variant configs side by side"}, ], }; const typeNames = {}; Object.values(palTypes).flat().forEach(p => { typeNames[p.t] = p.n; }); const typesByCat = {}; Object.entries(palTypes).forEach(([cat, items]) => { typesByCat[cat] = items.map(i => i.t); }); // ── DEMO DATA ── const initModules = [ {id:"m1",cat:"trigger",type:"trigger.manual",name:"Manual",x:60,y:300}, {id:"m2",cat:"step",type:"step.agent_task",name:"Draft Analysis",x:230,y:285,runCount:3,pinned:true}, {id:"exp1",cat:"system",type:"system.experiment",name:"Compare Models",x:480,y:235,expVariants:["Elnor (Baseline)","Nova","Atlas"]}, {id:"m3",cat:"step",type:"step.agent_review_gate",name:"Red Team A",x:480,y:440,runCount:1}, {id:"m4",cat:"step",type:"step.agent_review_gate",name:"Red Team B",x:480,y:570,runCount:1}, {id:"j1",cat:"step",type:"step.judge",name:"Quality Judge",x:750,y:285,judgeScores:{a:0.92,b:0.78,c:0.85}}, {id:"m7",cat:"output",type:"output.notify",name:"Results Notify",x:980,y:285}, {id:"env1",cat:"environment",type:"environment.config",name:"Environment",x:60,y:80}, {id:"m8",cat:"step",type:"step.agent_task",name:"Refine Draft",x:230,y:490,sessionContinue:true}, ]; const initCables = [ {id:"c1",from:"m1",fromPort:"data_out",to:"m2",toPort:"data_in",role:"data"}, {id:"c2",from:"m2",fromPort:"data_out",to:"exp1",toPort:"target",role:"target"}, {id:"c3",from:"exp1",fromPort:"comparison_out",to:"j1",toPort:"comparison_in",role:"data"}, {id:"c4",from:"exp1",fromPort:"variant_a_out",to:"m3",toPort:"data_in",role:"data"}, {id:"c5",from:"exp1",fromPort:"variant_b_out",to:"m4",toPort:"data_in",role:"data"}, {id:"c6",from:"m3",fromPort:"data_out",to:"j1",toPort:"evidence_in",role:"data"}, {id:"c7",from:"m4",fromPort:"data_out",to:"j1",toPort:"evidence_in",role:"data"}, {id:"c8",from:"j1",fromPort:"scores_out",to:"m7",toPort:"data_in",role:"data"}, {id:"c9",from:"m2",fromPort:"data_out",to:"m8",toPort:"data_in",role:"data"}, ]; const runSt = { idle:{}, running:{m1:"done",m2:"done",exp1:"active",m3:"active",m4:"active",j1:"wait",m7:"wait",m8:"wait",env1:"na"}, paused:{m1:"done",m2:"done",exp1:"done",m3:"active",m4:"active",j1:"wait",m7:"wait",m8:"wait",env1:"na"}, complete:{m1:"done",m2:"done",exp1:"done",m3:"done",m4:"done",j1:"done",m7:"done",m8:"done",env1:"na"}, }; const stCol = {done:c.green,active:c.accent,paused:c.amber,error:c.red,wait:c.textTer,na:"transparent"}; // ── SIZING — tighter ── function modW(mod){ if(mod.isMult) return 18; // Two-part measurement: category label is small mono, name is larger sans bold const catPx = (catLabel[mod.cat].length + 2) * 5.0; // mono 8.5px ≈ 5.0px/char, +2 for ": " const namePx = mod.name.length * 7.2; // sans 12px bold ≈ 7.2px/char const pad = 30; // 10px left + 20px right (pin + breathing) const textW = catPx + namePx + pad; return Math.max(100, Math.min(235, textW)); // floor 100, cap 235 (~23 char names) } function modH(mod){ if(mod.isMult) return 60; if(mod.cat==="environment"||mod.cat==="system") return 50; return {trigger:78,step:78,utility:68,output:78,source:68}[mod.cat]||78; } function primaryInPos(mod){return{x:mod.x,y:mod.y+modH(mod)/2};} function primaryOutPos(mod){return{x:mod.x+modW(mod),y:mod.y+modH(mod)/2};} function bez(x1,y1,x2,y2){const dx=Math.abs(x2-x1);const cp=Math.min(Math.max(70,dx*0.35),dx/2);return`M${x1},${y1} C${x1+cp},${y1} ${x2-cp},${y2} ${x2},${y2}`;} // ═══════════════════════════════════════════════════════════════ // DOC20 WORKSPACE SHELL PREVIEW // ═══════════════════════════════════════════════════════════════ function QTaskWorkspaceShell(){ const [browserOpen,setBrowserOpen]=useState(true); const [chatOpen,setChatOpen]=useState(false); return (
); } function TaskBrowserColumn(){ const rows=[ ["Today — May 4, 2026","NOTE","2h"], ["Draft Complaint — Marex","TASK","running"], ["Complaint Evaluation","SAVED TASK","18 runs"], ["Motion Red-Team Segment","SEGMENT","preset"], ["Complaint Red-Team Module","PRESET","11 uses"], ["Marex Filing Monitor","SCHEDULED","5:00 PM"], ["Sanli Expert Report.pdf","DOC","10m"], ["Paramount damages","CHAT","1h"], ]; return