moving
Some checks failed
Installer Smoke / installer-smoke (push) Has been cancelled

This commit is contained in:
Oleg Maslov
2026-09-02 10:10:29 +02:00
commit 0c3e2ead3b
3841 changed files with 970576 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,751 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Waggle OS - Marketplace &amp; Connector Ecosystem</title>
<style>
:root {
--honey: #e5a000;
--honey-dim: #b37d00;
--honey-glow: #ffc233;
--hive-950: #08090c;
--hive-900: #0f1117;
--hive-850: #151720;
--hive-800: #1a1d28;
--hive-700: #252836;
--hive-600: #363a4d;
--hive-500: #555a72;
--hive-400: #7f849e;
--hive-300: #a8adca;
--accent: #a78bfa;
--accent-dim: #7c5fc4;
--green: #34d399;
--green-dim: #059669;
--red: #f87171;
--blue: #60a5fa;
--orange: #fb923c;
--cyan: #22d3ee;
--pink: #f472b6;
--font: 'Segoe UI', system-ui, -apple-system, sans-serif;
--mono: 'Cascadia Code', 'Fira Code', 'Consolas', monospace;
--radius: 10px;
}
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
body {
background: var(--hive-950);
color: var(--hive-300);
font-family: var(--font);
font-size: 14px;
line-height: 1.55;
overflow-x: hidden;
}
#tooltip {
position: fixed;
z-index: 9999;
pointer-events: none;
background: var(--hive-800);
border: 1px solid var(--hive-600);
border-radius: 8px;
padding: 10px 14px;
max-width: 340px;
font-size: 13px;
color: var(--hive-300);
box-shadow: 0 8px 32px rgba(0,0,0,.55);
opacity: 0;
transition: opacity .15s;
}
#tooltip.visible { opacity: 1; }
.page { max-width: 1200px; margin: 0 auto; padding: 32px 24px 64px; }
header { text-align: center; margin-bottom: 40px; }
header h1 { font-size: 28px; font-weight: 700; color: #fff; letter-spacing: -.3px; }
header h1 span { color: var(--honey); }
header .subtitle { color: var(--hive-400); margin-top: 6px; font-size: 15px; }
.tabs {
display: flex; gap: 4px; background: var(--hive-900);
border-radius: var(--radius); padding: 4px; margin-bottom: 32px; overflow-x: auto;
}
.tab {
flex: 1; min-width: 120px; padding: 10px 12px; text-align: center;
border-radius: 7px; cursor: pointer; font-size: 13px; font-weight: 500;
color: var(--hive-400); border: none; background: transparent;
transition: all .2s; white-space: nowrap; font-family: var(--font);
}
.tab:hover { color: var(--hive-300); background: var(--hive-800); }
.tab.active { background: var(--hive-800); color: var(--honey); box-shadow: 0 0 0 1px var(--hive-600); }
.panel { display: none; }
.panel.active { display: block; animation: fadeUp .3s ease; }
@keyframes fadeUp { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
.section-title { font-size: 18px; font-weight: 600; color: #fff; margin-bottom: 6px; }
.section-desc { color: var(--hive-400); margin-bottom: 20px; font-size: 13px; }
.card {
background: var(--hive-900); border: 1px solid var(--hive-700);
border-radius: var(--radius); padding: 20px; margin-bottom: 16px; transition: border-color .2s;
}
.card:hover { border-color: var(--hive-600); }
.card h3 { color: #fff; font-size: 15px; margin-bottom: 8px; }
.card h3 .badge {
display: inline-block; font-size: 11px; padding: 2px 8px;
border-radius: 50px; font-weight: 500; margin-left: 6px; vertical-align: middle;
}
.flow { display: flex; align-items: center; gap: 0; flex-wrap: wrap; margin: 16px 0; justify-content: center; }
.flow-step { display: flex; align-items: center; gap: 0; }
.flow-node {
background: var(--hive-800); border: 1px solid var(--hive-600); border-radius: 8px;
padding: 10px 16px; font-size: 13px; color: #fff; text-align: center;
min-width: 100px; cursor: default; transition: all .2s; position: relative;
}
.flow-node:hover { border-color: var(--honey); box-shadow: 0 0 12px rgba(229,160,0,.15); }
.flow-node .fn-icon { font-size: 20px; display: block; margin-bottom: 4px; }
.flow-node .fn-label { font-size: 12px; color: var(--hive-400); }
.flow-arrow { color: var(--hive-500); font-size: 18px; padding: 0 6px; flex-shrink: 0; }
.col3 { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 16px; }
.col2 { display: grid; grid-template-columns: repeat(auto-fit, minmax(380px, 1fr)); gap: 16px; }
.bg-skill { background: rgba(167,139,250,.15); color: var(--accent); }
.bg-plugin { background: rgba(52,211,153,.15); color: var(--green); }
.bg-mcp { background: rgba(96,165,250,.15); color: var(--blue); }
.bg-connector { background: rgba(251,146,60,.15); color: var(--orange); }
.bg-security { background: rgba(248,113,113,.15); color: var(--red); }
.bg-honey { background: rgba(229,160,0,.15); color: var(--honey); }
.code-block {
background: var(--hive-950); border: 1px solid var(--hive-700); border-radius: 6px;
padding: 12px 16px; font-family: var(--mono); font-size: 12px;
color: var(--hive-300); overflow-x: auto; margin: 10px 0; white-space: pre;
}
.code-block .kw { color: var(--accent); }
.code-block .str { color: var(--green); }
.code-block .cmt { color: var(--hive-500); font-style: italic; }
.code-block .fn { color: var(--honey); }
.code-block .type { color: var(--blue); }
.connector-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 8px; margin: 12px 0; }
.connector-chip {
background: var(--hive-800); border: 1px solid var(--hive-700); border-radius: 8px;
padding: 8px 12px; font-size: 12px; color: #fff; display: flex;
align-items: center; gap: 6px; cursor: default; transition: all .2s;
}
.connector-chip:hover { border-color: var(--honey-dim); background: var(--hive-700); }
.connector-chip .cc-icon { font-size: 16px; flex-shrink: 0; }
.connector-chip .cc-cat { font-size: 10px; color: var(--hive-500); display: block; }
.mcp-cat-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 8px; margin: 12px 0; }
.mcp-cat {
background: var(--hive-800); border: 1px solid var(--hive-700); border-radius: 8px;
padding: 10px; text-align: center; cursor: default; transition: all .2s;
}
.mcp-cat:hover { border-color: var(--blue); }
.mcp-cat .mc-emoji { font-size: 22px; display: block; margin-bottom: 4px; }
.mcp-cat .mc-name { color: #fff; font-size: 12px; font-weight: 500; }
.mcp-cat .mc-count { color: var(--hive-500); font-size: 11px; }
.promotion-chain { display: flex; align-items: center; gap: 0; justify-content: center; margin: 20px 0; flex-wrap: wrap; }
.promo-node { padding: 10px 20px; border-radius: 8px; border: 2px solid; text-align: center; font-size: 13px; font-weight: 600; min-width: 110px; }
.promo-arrow { color: var(--hive-500); font-size: 20px; padding: 0 4px; }
.promo-personal { border-color: var(--accent); color: var(--accent); background: rgba(167,139,250,.08); }
.promo-workspace { border-color: var(--honey); color: var(--honey); background: rgba(229,160,0,.08); }
.promo-team { border-color: var(--green); color: var(--green); background: rgba(52,211,153,.08); }
.promo-enterprise { border-color: var(--blue); color: var(--blue); background: rgba(96,165,250,.08); }
.stats-bar { display: flex; gap: 16px; margin: 16px 0; flex-wrap: wrap; }
.stat {
background: var(--hive-800); border: 1px solid var(--hive-700); border-radius: 8px;
padding: 14px 20px; text-align: center; flex: 1; min-width: 120px;
}
.stat .s-num { font-size: 28px; font-weight: 700; color: var(--honey); }
.stat .s-label { font-size: 12px; color: var(--hive-400); margin-top: 2px; }
.install-stages { display: flex; gap: 0; align-items: stretch; justify-content: center; margin: 20px 0; flex-wrap: wrap; }
.install-stage {
background: var(--hive-800); border: 1px solid var(--hive-700); border-radius: 8px;
padding: 14px 18px; text-align: center; min-width: 130px; transition: all .4s; position: relative;
}
.install-stage.highlight { border-color: var(--honey); box-shadow: 0 0 20px rgba(229,160,0,.2); }
.install-stage .is-num {
position: absolute; top: -10px; left: 50%; transform: translateX(-50%);
background: var(--hive-700); color: var(--honey); font-size: 11px; font-weight: 700;
width: 20px; height: 20px; border-radius: 50%; display: flex; align-items: center; justify-content: center;
}
.install-stage .is-icon { font-size: 22px; margin-bottom: 6px; }
.install-stage .is-title { color: #fff; font-size: 13px; font-weight: 600; }
.install-stage .is-desc { color: var(--hive-400); font-size: 11px; margin-top: 4px; }
.install-arrow { display: flex; align-items: center; color: var(--hive-500); font-size: 20px; padding: 0 4px; }
.extraction-vis {
background: var(--hive-900); border: 1px solid var(--hive-700);
border-radius: var(--radius); padding: 24px; margin: 16px 0;
}
.ext-phase { display: flex; align-items: center; gap: 12px; padding: 12px 0; border-bottom: 1px solid var(--hive-800); }
.ext-phase:last-child { border-bottom: none; }
.ext-num {
width: 32px; height: 32px; border-radius: 50%; display: flex;
align-items: center; justify-content: center; font-weight: 700; font-size: 14px; flex-shrink: 0;
}
.ext-content { flex: 1; }
.ext-content .ext-label { color: #fff; font-weight: 600; font-size: 14px; }
.ext-content .ext-detail { color: var(--hive-400); font-size: 12px; margin-top: 2px; }
.legend { display: flex; gap: 16px; flex-wrap: wrap; margin: 12px 0; }
.legend-item { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--hive-400); }
.legend-dot { width: 10px; height: 10px; border-radius: 50%; }
.lc-item { display: flex; align-items: center; gap: 10px; }
.lc-icon {
width: 36px; height: 36px; border-radius: 8px; display: flex;
align-items: center; justify-content: center; font-size: 18px; flex-shrink: 0;
}
.sig-item { display: flex; align-items: center; gap: 8px; }
.cap-block { margin-bottom: 12px; }
.cap-head { display: flex; align-items: center; gap: 8px; margin-bottom: 4px; }
@media (max-width: 700px) {
.col3, .col2 { grid-template-columns: 1fr; }
.tabs { flex-wrap: wrap; }
.tab { min-width: 80px; font-size: 12px; padding: 8px; }
.flow, .promotion-chain, .install-stages { flex-direction: column; align-items: center; }
.flow-arrow, .promo-arrow, .install-arrow { transform: rotate(90deg); }
}
</style>
</head>
<body>
<div id="tooltip"></div>
<div class="page">
<header>
<h1><span>Waggle</span> Marketplace &amp; Connector Ecosystem</h1>
<p class="subtitle">Skills, Plugins, MCP Servers, 30 Native Connectors, Composio 250+ Integrations</p>
</header>
<div class="stats-bar">
<div class="stat"><div class="s-num">3</div><div class="s-label">Extension Types</div></div>
<div class="stat"><div class="s-num">148</div><div class="s-label">MCP Servers</div></div>
<div class="stat"><div class="s-num">30</div><div class="s-label">Native Connectors</div></div>
<div class="stat"><div class="s-num">250+</div><div class="s-label">Composio Integrations</div></div>
<div class="stat"><div class="s-num">14</div><div class="s-label">MCP Categories</div></div>
</div>
<div class="tabs" role="tablist">
<button class="tab active" data-tab="types" role="tab">Extension Types</button>
<button class="tab" data-tab="marketplace" role="tab">Marketplace</button>
<button class="tab" data-tab="connectors" role="tab">Connectors</button>
<button class="tab" data-tab="custom" role="tab">Custom Skills</button>
<button class="tab" data-tab="extraction" role="tab">Auto-Extraction</button>
<button class="tab" data-tab="mcp" role="tab">MCP Integration</button>
</div>
<!-- ═══════ TAB 1: Extension Types ═══════ -->
<div class="panel active" id="panel-types">
<h2 class="section-title">Three Extension Types</h2>
<p class="section-desc">Waggle supports three distinct extension mechanisms, each with its own loading, validation, and runtime model.</p>
<div class="col3">
<div class="card">
<h3><span class="badge bg-skill">SKILL</span> Markdown Instructions</h3>
<p style="margin-bottom:12px">SKILL.md files contain agent instructions with YAML frontmatter for metadata, permissions, and scope. Loaded at chat-turn time, injected into the system prompt.</p>
<div class="code-block"><span class="cmt">--- frontmatter ---</span>
<span class="kw">name:</span> <span class="str">Deploy Helper</span>
<span class="kw">scope:</span> <span class="str">personal</span>
<span class="kw">permissions:</span>
<span class="kw">codeExecution:</span> <span class="str">true</span>
<span class="kw">network:</span> <span class="str">true</span>
<span class="cmt">--- end ---</span>
<span class="cmt"># Body is injected into system prompt</span></div>
<div class="flow" style="margin-top:12px">
<div class="flow-step"><div class="flow-node" data-tip="SKILL.md file on disk in ~/.waggle/skills/" data-meta="Format: Markdown + YAML frontmatter"><span class="fn-icon">&#128196;</span>SKILL.md</div></div>
<span class="flow-arrow">&#8594;</span>
<div class="flow-step"><div class="flow-node" data-tip="parseSkillFrontmatter() extracts name, description, scope, permissions, promoted_from" data-meta="Source: skill-frontmatter.ts"><span class="fn-icon">&#9881;</span>Parse FM</div></div>
<span class="flow-arrow">&#8594;</span>
<div class="flow-step"><div class="flow-node" data-tip="Scope + permission check ensures skill is available for the current workspace" data-meta="Scopes: personal | workspace | team | enterprise"><span class="fn-icon">&#10003;</span>Validate</div></div>
<span class="flow-arrow">&#8594;</span>
<div class="flow-step"><div class="flow-node" data-tip="Skill body injected into agent system prompt for the current chat turn" data-meta="Available to the agent as contextual instructions"><span class="fn-icon">&#129302;</span>Agent</div></div>
</div>
</div>
<div class="card">
<h3><span class="badge bg-plugin">PLUGIN</span> JS/TS Code Modules</h3>
<p style="margin-bottom:12px">Plugins are code packages with a plugin.json manifest. They contribute tools, skills, and lifecycle hooks. Managed by PluginRuntime with a state machine (installed &gt; enabled &gt; active).</p>
<div class="code-block"><span class="cmt">// plugin.json manifest</span>
{ <span class="kw">"name"</span>: <span class="str">"my-plugin"</span>,
<span class="kw">"tools"</span>: [{ <span class="kw">"name"</span>: <span class="str">"deploy"</span> }],
<span class="kw">"skills"</span>: [<span class="str">"deploy.md"</span>] }
<span class="cmt">// Lifecycle: installed &gt; enabled &gt; active</span></div>
<div class="flow" style="margin-top:12px">
<div class="flow-step"><div class="flow-node" data-tip="Plugin directory at ~/.waggle/plugins/{name}/ with plugin.json manifest" data-meta="Contains code, skills, and manifest"><span class="fn-icon">&#128230;</span>Package</div></div>
<span class="flow-arrow">&#8594;</span>
<div class="flow-step"><div class="flow-node" data-tip="PluginRuntime reads manifest, validates tool definitions, checks permissions" data-meta="Source: plugin-runtime.ts"><span class="fn-icon">&#128270;</span>Manifest</div></div>
<span class="flow-arrow">&#8594;</span>
<div class="flow-step"><div class="flow-node" data-tip="State machine: installed then enabled then active. Tools registered on activation." data-meta="States: installed | enabled | active | disabled | error"><span class="fn-icon">&#9889;</span>Activate</div></div>
<span class="flow-arrow">&#8594;</span>
<div class="flow-step"><div class="flow-node" data-tip="Plugin tools appear in agent tool pool alongside native tools" data-meta="PluginToolDef: name + description + parameters"><span class="fn-icon">&#128295;</span>Tool Pool</div></div>
</div>
</div>
<div class="card">
<h3><span class="badge bg-mcp">MCP</span> External Processes</h3>
<p style="margin-bottom:12px">MCP servers run as separate processes, connected via stdio or SSE. They expose tools, resources, and prompt templates through the Model Context Protocol standard.</p>
<div class="code-block"><span class="cmt">// .mcp.json configuration</span>
{ <span class="kw">"servers"</span>: {
<span class="str">"filesystem"</span>: {
<span class="kw">"command"</span>: <span class="str">"npx"</span>,
<span class="kw">"args"</span>: [<span class="str">"@mcp/filesystem"</span>]
}
}
}</div>
<div class="flow" style="margin-top:12px">
<div class="flow-step"><div class="flow-node" data-tip="MCP server entry in .mcp.json with command + args for stdio, or URL for SSE" data-meta="Transport: stdio | sse"><span class="fn-icon">&#127760;</span>Config</div></div>
<span class="flow-arrow">&#8594;</span>
<div class="flow-step"><div class="flow-node" data-tip="Process spawned and handshake performed. Capabilities negotiated (tools, resources, prompts)" data-meta="Protocol: JSON-RPC over stdio/SSE"><span class="fn-icon">&#128260;</span>Spawn</div></div>
<span class="flow-arrow">&#8594;</span>
<div class="flow-step"><div class="flow-node" data-tip="Server exposes tools/list, resources/list, prompts/list to the client" data-meta="Standard MCP discovery endpoints"><span class="fn-icon">&#128269;</span>Discover</div></div>
<span class="flow-arrow">&#8594;</span>
<div class="flow-step"><div class="flow-node" data-tip="MCP tools merged into agent tool pool with mcp__{server}__{tool} naming" data-meta="Unified with native + plugin tools"><span class="fn-icon">&#129302;</span>Merged</div></div>
</div>
</div>
</div>
<div class="legend" style="margin-top:20px; justify-content: center;">
<div class="legend-item"><div class="legend-dot" style="background:var(--accent)"></div> Skill (Markdown)</div>
<div class="legend-item"><div class="legend-dot" style="background:var(--green)"></div> Plugin (Code)</div>
<div class="legend-item"><div class="legend-dot" style="background:var(--blue)"></div> MCP Server (Process)</div>
<div class="legend-item"><div class="legend-dot" style="background:var(--orange)"></div> Connector (API)</div>
</div>
</div>
<!-- ═══════ TAB 2: Marketplace Catalog ═══════ -->
<div class="panel" id="panel-marketplace">
<h2 class="section-title">Marketplace Catalog</h2>
<p class="section-desc">SQLite-backed package catalog with 148 MCP entries, SecurityGate multi-layer validation, auto-seed from bundled registry data, and full search/filter capabilities.</p>
<div class="col2">
<div class="card">
<h3>Catalog Architecture</h3>
<div class="code-block"><span class="type">MarketplaceDB</span> (SQLite)
<span class="kw">tables:</span> sources, packages, packs, installed
<span class="fn">auto-seed</span>: mcp-registry.ts inserts 148 entries
<span class="fn">dedup</span>: assertCatalogUnique at load time
<span class="type">Package Types:</span>
<span class="str">skill</span> | <span class="str">plugin</span> | <span class="str">mcp_server</span> | <span class="str">template</span> | <span class="str">pack</span>
<span class="type">Source Types:</span>
<span class="str">marketplace</span> | <span class="str">registry</span> | <span class="str">github_org</span>
<span class="str">npm_registry</span> | <span class="str">community_repo</span> | ...</div>
</div>
<div class="card">
<h3><span class="badge bg-security">SECURITY</span> SecurityGate Validation</h3>
<div class="code-block"><span class="type">4-Layer Security Pipeline</span>
<span class="kw">Layer 1:</span> <span class="fn">Gen Trust Hub API</span>
Cloud URL pre-check (fast, free)
<span class="kw">Layer 2:</span> <span class="fn">Cisco Skill Scanner</span>
Local deep analysis (pattern + behavioral + LLM)
<span class="kw">Layer 3:</span> <span class="fn">MCP Guardian</span>
Inline tool description pattern matching
<span class="kw">Layer 4:</span> <span class="fn">Built-in Heuristics</span>
Waggle-specific threat pattern rules</div>
<div style="margin-top: 10px">
<div class="legend">
<div class="legend-item"><div class="legend-dot" style="background:var(--red)"></div> CRITICAL: Block</div>
<div class="legend-item"><div class="legend-dot" style="background:var(--orange)"></div> HIGH: Block (override)</div>
<div class="legend-item"><div class="legend-dot" style="background:var(--honey)"></div> MEDIUM: Warn</div>
<div class="legend-item"><div class="legend-dot" style="background:var(--green)"></div> LOW/CLEAN: Allow</div>
</div>
</div>
</div>
</div>
<h3 style="color: #fff; margin: 24px 0 12px;">Installation Flow</h3>
<div class="install-stages">
<div class="install-stage" id="is-1" data-tip="User searches the marketplace by name, category, or package type. SQLite FTS enables fast filtering." data-meta="MarketplaceDB.search() with category + type filters">
<div class="is-num">1</div><div class="is-icon">&#128269;</div><div class="is-title">Browse</div><div class="is-desc">Search catalog by name, category, type</div>
</div>
<div class="install-arrow">&#8594;</div>
<div class="install-stage" id="is-2" data-tip="SecurityGate runs all 4 layers. Findings with CRITICAL or HIGH severity block installation. SHA-256 hash computed for integrity." data-meta="11 threat categories: prompt_injection, data_exfiltration, malicious_code, etc.">
<div class="is-num">2</div><div class="is-icon">&#128737;</div><div class="is-title">Security Scan</div><div class="is-desc">4-layer validation pipeline</div>
</div>
<div class="install-arrow">&#8594;</div>
<div class="install-stage" id="is-3" data-tip="MarketplaceInstaller routes to type-specific handler: skill copies MD, plugin clones dir + manifest, MCP writes .mcp.json config" data-meta="Paths: ~/.waggle/skills/ | ~/.waggle/plugins/ | .mcp.json">
<div class="is-num">3</div><div class="is-icon">&#128229;</div><div class="is-title">Install</div><div class="is-desc">Type-specific handler writes files</div>
</div>
<div class="install-arrow">&#8594;</div>
<div class="install-stage" id="is-4" data-tip="Server notified via PUT /api/skills or POST /api/plugins/install. Tools and skills become available to the agent in the next chat turn." data-meta="Hot-reload: no restart required">
<div class="is-num">4</div><div class="is-icon">&#9989;</div><div class="is-title">Available</div><div class="is-desc">Tools appear in agent pool</div>
</div>
</div>
<div class="card" style="margin-top: 20px">
<h3>Threat Categories Detected</h3>
<div class="connector-grid">
<div class="connector-chip" data-tip="Attempts to override system prompt or inject malicious instructions" data-meta="SecurityCategory"><span class="cc-icon">&#128165;</span><span>Prompt Injection</span></div>
<div class="connector-chip" data-tip="Attempts to send data to external endpoints without user consent" data-meta="SecurityCategory"><span class="cc-icon">&#128228;</span><span>Data Exfiltration</span></div>
<div class="connector-chip" data-tip="Dynamic code execution or obfuscated executable code patterns" data-meta="SecurityCategory"><span class="cc-icon">&#128520;</span><span>Malicious Code</span></div>
<div class="connector-chip" data-tip="Attempts to escalate file system or network permissions beyond declared scope" data-meta="SecurityCategory"><span class="cc-icon">&#128274;</span><span>Privilege Escalation</span></div>
<div class="connector-chip" data-tip="MCP tool descriptions that manipulate agent behavior via hidden instructions" data-meta="SecurityCategory"><span class="cc-icon">&#129440;</span><span>Tool Poisoning</span></div>
<div class="connector-chip" data-tip="Cross-origin resource access or scope escape attempts" data-meta="SecurityCategory"><span class="cc-icon">&#127760;</span><span>Cross-Origin</span></div>
<div class="connector-chip" data-tip="Package that changes behavior after install to introduce malicious functionality" data-meta="SecurityCategory"><span class="cc-icon">&#128163;</span><span>Rug Pull</span></div>
<div class="connector-chip" data-tip="Code obfuscation techniques designed to hide malicious intent" data-meta="SecurityCategory"><span class="cc-icon">&#128065;</span><span>Obfuscation</span></div>
</div>
</div>
</div>
<!-- ═══════ TAB 3: Connector Architecture ═══════ -->
<div class="panel" id="panel-connectors">
<h2 class="section-title">Connector Architecture</h2>
<p class="section-desc">30 native connectors with Vault-based credential management, plus Composio meta-connector bridging 250+ external services.</p>
<div class="flow" style="margin-bottom: 24px">
<div class="flow-step"><div class="flow-node" data-tip="ConnectorRegistry holds all 30 native connector instances, indexed by id" data-meta="Source: connectors/index.ts"><span class="fn-icon">&#128218;</span>Registry<span class="fn-label">30 connectors</span></div></div>
<span class="flow-arrow">&#8594;</span>
<div class="flow-step"><div class="flow-node" data-tip="VaultStore lookup by connector.id to retrieve API key, OAuth token, or bearer token" data-meta="Source: packages/core/src/mind/vault.ts"><span class="fn-icon">&#128272;</span>Vault Lookup<span class="fn-label">Credential fetch</span></div></div>
<span class="flow-arrow">&#8594;</span>
<div class="flow-step"><div class="flow-node" data-tip="Authenticated HTTP request to external API. Auth types: bearer, oauth2, api_key, basic" data-meta="BaseConnector.executeAction()"><span class="fn-icon">&#128640;</span>API Call<span class="fn-label">Authenticated</span></div></div>
<span class="flow-arrow">&#8594;</span>
<div class="flow-step"><div class="flow-node" data-tip="ConnectorResult { success, data?, error? } returned to the agent as tool output" data-meta="Standardized response format"><span class="fn-icon">&#129302;</span>Agent Result<span class="fn-label">Tool output</span></div></div>
</div>
<div class="col2">
<div class="card">
<h3>Native Connectors <span class="badge bg-connector">30</span></h3>
<div class="connector-grid" id="native-connectors"></div>
</div>
<div class="card">
<h3>Composio Meta-Connector <span class="badge bg-honey">250+</span></h3>
<p style="margin-bottom: 10px">Single API key bridges to 250+ external services. Actions discovered dynamically and executed through approval gates.</p>
<div class="code-block"><span class="type">ComposioConnector</span> <span class="kw">extends</span> <span class="type">BaseConnector</span>
<span class="kw">authType:</span> <span class="str">'api_key'</span> (X-API-KEY header)
<span class="kw">api:</span> <span class="str">backend.composio.dev/api/v1</span>
<span class="fn">Actions:</span>
<span class="str">list_integrations</span> <span class="cmt">// connected services</span>
<span class="str">list_actions</span> <span class="cmt">// available operations</span>
<span class="str">execute_action</span> <span class="cmt">// run (risk: HIGH)</span>
<span class="str">get_action_schema</span> <span class="cmt">// input/output defs</span></div>
</div>
</div>
<div class="card" style="margin-top: 16px">
<h3>Connector SDK Interface</h3>
<div class="code-block"><span class="kw">interface</span> <span class="type">WaggleConnector</span> {
<span class="kw">readonly</span> id: <span class="type">string</span> <span class="cmt">// 'github', 'slack', ...</span>
<span class="kw">readonly</span> name: <span class="type">string</span> <span class="cmt">// Display name</span>
<span class="kw">readonly</span> authType: <span class="str">'bearer'</span> | <span class="str">'oauth2'</span> | <span class="str">'api_key'</span> | <span class="str">'basic'</span>
<span class="kw">readonly</span> substrate: <span class="str">'waggle'</span> | <span class="str">'kvark'</span>
<span class="kw">readonly</span> actions: <span class="type">ConnectorAction</span>[]
<span class="fn">connect</span>(vault: <span class="type">VaultStore</span>): <span class="type">Promise</span>&lt;<span class="type">void</span>&gt;
<span class="fn">executeAction</span>(name: <span class="type">string</span>, input: <span class="type">unknown</span>): <span class="type">Promise</span>&lt;<span class="type">ConnectorResult</span>&gt;
<span class="fn">healthCheck</span>(): <span class="type">Promise</span>&lt;<span class="type">ConnectorHealth</span>&gt;
}</div>
</div>
</div>
<!-- ═══════ TAB 4: Custom Skill Sources ═══════ -->
<div class="panel" id="panel-custom">
<h2 class="section-title">Custom Skill Lifecycle</h2>
<p class="section-desc">User-created SKILL.md files with hot-reload, usage tracking, auto-retirement after 90 days idle, and promotion from personal to enterprise scope.</p>
<div class="col2">
<div class="card">
<h3>Skill File Structure</h3>
<div class="code-block"><span class="cmt">~/.waggle/skills/my-skill.md</span>
<span class="kw">---</span>
<span class="kw">name:</span> <span class="str">Deploy Helper</span>
<span class="kw">description:</span> <span class="str">Helps deploy apps</span>
<span class="kw">scope:</span> <span class="str">personal</span>
<span class="kw">permissions:</span>
<span class="kw">fileSystem:</span> <span class="str">true</span>
<span class="kw">network:</span> <span class="str">true</span>
<span class="kw">codeExecution:</span> <span class="str">true</span>
<span class="kw">externalServices:</span> <span class="str">false</span>
<span class="kw">secrets:</span> <span class="str">false</span>
<span class="kw">browserAutomation:</span> <span class="str">false</span>
<span class="kw">---</span>
<span class="cmt"># Deploy Helper</span>
<span class="cmt">You are a deployment specialist...</span></div>
</div>
<div class="card">
<h3>Lifecycle Stages</h3>
<div style="display:flex; flex-direction: column; gap: 10px; margin-top: 8px;">
<div class="lc-item"><div class="lc-icon" style="background:rgba(167,139,250,.15)">&#9998;</div><div><strong style="color:#fff">Create</strong><br><span style="font-size:12px">User writes SKILL.md in ~/.waggle/skills/</span></div></div>
<div class="lc-item"><div class="lc-icon" style="background:rgba(52,211,153,.15)">&#128065;</div><div><strong style="color:#fff">Hot-Reload</strong><br><span style="font-size:12px">fs.watch detects changes, re-parses frontmatter instantly</span></div></div>
<div class="lc-item"><div class="lc-icon" style="background:rgba(229,160,0,.15)">&#128200;</div><div><strong style="color:#fff">Usage Tracking</strong><br><span style="font-size:12px">Each invocation logged with timestamp for activity analysis</span></div></div>
<div class="lc-item"><div class="lc-icon" style="background:rgba(248,113,113,.15)">&#128337;</div><div><strong style="color:#fff">Auto-Retirement</strong><br><span style="font-size:12px">Skills idle 90+ days flagged for cleanup to prevent bloat</span></div></div>
</div>
</div>
</div>
<h3 style="color: #fff; margin: 24px 0 12px;">Promotion Chain</h3>
<p class="section-desc">Skills are promoted one step at a time. Each promotion is recorded in <code style="color:var(--honey)">promoted_from[]</code> for audit trail. Demotion is not supported.</p>
<div class="promotion-chain">
<div class="promo-node promo-personal" data-tip="Initial scope. Only the creating user can see and use this skill." data-meta="Default scope for new skills">&#128100; Personal</div>
<span class="promo-arrow">&#8594;</span>
<div class="promo-node promo-workspace" data-tip="Available to all agents in the current workspace. Promoted by workspace admin." data-meta="promoted_from: ['personal']">&#128187; Workspace</div>
<span class="promo-arrow">&#8594;</span>
<div class="promo-node promo-team" data-tip="Shared across all workspaces for the team. Requires team admin approval." data-meta="promoted_from: ['personal', 'workspace']">&#128101; Team</div>
<span class="promo-arrow">&#8594;</span>
<div class="promo-node promo-enterprise" data-tip="Organization-wide standard. Available in KVARK deployments." data-meta="promoted_from: ['personal', 'workspace', 'team']">&#127970; Enterprise</div>
</div>
<div class="card" style="margin-top: 20px">
<h3>SkillFrontmatter Interface</h3>
<div class="code-block"><span class="kw">type</span> <span class="type">SkillScope</span> = <span class="str">'personal'</span> | <span class="str">'workspace'</span> | <span class="str">'team'</span> | <span class="str">'enterprise'</span>
<span class="kw">interface</span> <span class="type">SkillFrontmatter</span> {
name?: <span class="type">string</span>
description?: <span class="type">string</span>
scope?: <span class="type">SkillScope</span> <span class="cmt">// defaults to 'personal'</span>
promoted_from?: <span class="type">SkillScope</span>[] <span class="cmt">// append-only audit trail</span>
permissions?: {
fileSystem, network, codeExecution,
externalServices, secrets, browserAutomation
}
}</div>
</div>
</div>
<!-- ═══════ TAB 5: Skill Auto-Extraction ═══════ -->
<div class="panel" id="panel-extraction">
<h2 class="section-title">Skill Auto-Extraction Pipeline</h2>
<p class="section-desc">Agent detects repeated patterns across conversations, extracts them into reusable SKILL.md files, and optionally enriches with LLM synthesis.</p>
<div class="extraction-vis">
<div class="ext-phase">
<div class="ext-num" style="background:rgba(167,139,250,.2); color:var(--accent)">1</div>
<div class="ext-content"><div class="ext-label">Pattern Detection</div><div class="ext-detail">Agent analyzes conversation history for repeated instruction patterns, common tool chains, and recurring workflows. Threshold: 3+ occurrences across sessions triggers extraction candidacy.</div></div>
</div>
<div class="ext-phase">
<div class="ext-num" style="background:rgba(229,160,0,.2); color:var(--honey)">2</div>
<div class="ext-content"><div class="ext-label">Skill Extraction</div><div class="ext-detail"><code style="color:var(--honey)">generateSkillMarkdown()</code> creates a structured SKILL.md with frontmatter (name, description, permissions) and body (instructions, examples, constraints).</div></div>
</div>
<div class="ext-phase">
<div class="ext-num" style="background:rgba(52,211,153,.2); color:var(--green)">3</div>
<div class="ext-content"><div class="ext-label">File Creation</div><div class="ext-detail">Writes to <code style="color:var(--honey)">~/.waggle/skills/{name}.md</code> with <code>scope: personal</code>. fs.watch triggers hot-reload so the skill is immediately available without restart.</div></div>
</div>
<div class="ext-phase">
<div class="ext-num" style="background:rgba(96,165,250,.2); color:var(--blue)">4</div>
<div class="ext-content"><div class="ext-label">LLM Enrichment (Optional)</div><div class="ext-detail">If enabled, the extracted skill is refined by an LLM pass: clearer instructions, better examples, edge case handling, and permission tightening. Costs one Haiku call (~$0.001).</div></div>
</div>
<div class="ext-phase">
<div class="ext-num" style="background:rgba(244,114,182,.2); color:var(--pink)">5</div>
<div class="ext-content"><div class="ext-label">Promotion Pipeline</div><div class="ext-detail">High-usage personal skills are candidates for promotion. Each step requires admin approval and appends to <code style="color:var(--honey)">promoted_from[]</code>.</div></div>
</div>
</div>
<div class="col2" style="margin-top: 16px">
<div class="card">
<h3>Detection Signals</h3>
<div style="display:flex;flex-direction:column;gap:8px;margin-top:8px">
<div class="sig-item"><span style="color:var(--accent);font-size:16px">&#9679;</span><span><strong style="color:#fff">Repeated instructions</strong> - Same phrasing across 3+ conversations</span></div>
<div class="sig-item"><span style="color:var(--honey);font-size:16px">&#9679;</span><span><strong style="color:#fff">Tool chains</strong> - Same sequence of tool calls in recurring patterns</span></div>
<div class="sig-item"><span style="color:var(--green);font-size:16px">&#9679;</span><span><strong style="color:#fff">Workflow templates</strong> - Multi-step processes that follow a fixed order</span></div>
<div class="sig-item"><span style="color:var(--blue);font-size:16px">&#9679;</span><span><strong style="color:#fff">Style preferences</strong> - Consistent formatting, tone, or output rules</span></div>
</div>
</div>
<div class="card">
<h3>Generated Skill Example</h3>
<div class="code-block"><span class="kw">---</span>
<span class="kw">name:</span> <span class="str">Git PR Workflow</span>
<span class="kw">description:</span> <span class="str">Standard PR creation flow</span>
<span class="kw">scope:</span> <span class="str">personal</span>
<span class="kw">permissions:</span>
<span class="kw">codeExecution:</span> <span class="str">true</span>
<span class="kw">---</span>
<span class="cmt"># Git PR Workflow</span>
<span class="cmt">When creating a pull request:</span>
<span class="cmt">1. Run git diff to review changes</span>
<span class="cmt">2. Write descriptive commit message</span>
<span class="cmt">3. Push to feature branch</span>
<span class="cmt">4. Create PR with summary + test plan</span></div>
</div>
</div>
</div>
<!-- ═══════ TAB 6: MCP Integration ═══════ -->
<div class="panel" id="panel-mcp">
<h2 class="section-title">MCP Integration</h2>
<p class="section-desc">148 curated MCP servers across 14 categories. Tool discovery, resource access, and prompt templates unified into the agent's tool pool.</p>
<div class="card">
<h3>MCP Server Catalog <span class="badge bg-mcp">148 entries</span></h3>
<p style="margin-bottom: 12px">Cross-referenced from 4 sources: official Anthropic repo, punkpeye/awesome-mcp-servers (77K stars), appcypher collection, and tolkonepiu/best-of (450 ranked, 34 categories). Dedup enforced via <code style="color:var(--honey)">assertCatalogUnique</code> at module load.</p>
<div class="mcp-cat-grid" id="mcp-categories"></div>
</div>
<div class="col2" style="margin-top: 16px">
<div class="card">
<h3>McpServer Interface</h3>
<div class="code-block"><span class="kw">interface</span> <span class="type">McpServer</span> {
id: <span class="type">string</span>
name: <span class="type">string</span>
description: <span class="type">string</span>
author: <span class="type">string</span>
category: <span class="type">string</span> <span class="cmt">// one of 14 categories</span>
url: <span class="type">string</span>
installCmd: <span class="type">string</span> <span class="cmt">// npx @mcp/...</span>
capabilities: <span class="type">string</span>[] <span class="cmt">// tools | resources | prompts</span>
official?: <span class="type">boolean</span>
logo?: <span class="type">string</span> <span class="cmt">// emoji or brand initial</span>
}</div>
</div>
<div class="card">
<h3>MCP Capabilities</h3>
<div style="display:flex;flex-direction:column;gap:12px;margin-top:8px">
<div class="cap-block"><div class="cap-head"><span style="font-size:18px">&#128295;</span><strong style="color:var(--blue)">Tools</strong></div><span style="font-size:12px">Executable functions exposed by the server. Appear in agent tool pool with <code style="color:var(--honey)">mcp__{server}__{tool}</code> naming. Called via JSON-RPC <code>tools/call</code>.</span></div>
<div class="cap-block"><div class="cap-head"><span style="font-size:18px">&#128196;</span><strong style="color:var(--green)">Resources</strong></div><span style="font-size:12px">Data endpoints the server exposes (files, database rows, API results). Agent can read via <code>resources/read</code>. Supports subscriptions for live updates.</span></div>
<div class="cap-block"><div class="cap-head"><span style="font-size:18px">&#128172;</span><strong style="color:var(--accent)">Prompt Templates</strong></div><span style="font-size:12px">Pre-built prompt structures the server offers. Retrieved via <code>prompts/get</code>. Injected into system prompt alongside skill content.</span></div>
</div>
</div>
</div>
<h3 style="color: #fff; margin: 24px 0 12px;">Tool Pool Unification</h3>
<p class="section-desc">All extension types merge into a single tool pool that the agent sees. filterToolsForContext() applies persona allowlist/denylist before each chat turn.</p>
<div class="flow">
<div class="flow-step"><div class="flow-node" style="border-color: var(--accent)" data-tip="Skills inject instructions into system prompt. They guide agent behavior without adding callable tools." data-meta="Loaded from ~/.waggle/skills/"><span class="fn-icon" style="color:var(--accent)">&#128220;</span>Skills<span class="fn-label">System prompt</span></div></div>
<span class="flow-arrow">+</span>
<div class="flow-step"><div class="flow-node" style="border-color: var(--green)" data-tip="Plugin tools registered during activation. PluginToolDef: name + description + parameters + execute function." data-meta="Source: plugin-runtime.ts"><span class="fn-icon" style="color:var(--green)">&#128230;</span>Plugin Tools<span class="fn-label">Code modules</span></div></div>
<span class="flow-arrow">+</span>
<div class="flow-step"><div class="flow-node" style="border-color: var(--blue)" data-tip="MCP tools discovered via tools/list and added with mcp__{server}__{tool} prefix for namespace isolation." data-meta="Transport: stdio | SSE"><span class="fn-icon" style="color:var(--blue)">&#127760;</span>MCP Tools<span class="fn-label">External processes</span></div></div>
<span class="flow-arrow">+</span>
<div class="flow-step"><div class="flow-node" style="border-color: var(--orange)" data-tip="Connector actions registered as tools when connected and authenticated via Vault." data-meta="30 native + Composio 250+"><span class="fn-icon" style="color:var(--orange)">&#128268;</span>Connectors<span class="fn-label">API bridges</span></div></div>
<span class="flow-arrow">&#8594;</span>
<div class="flow-step"><div class="flow-node" style="border-color: var(--honey)" data-tip="filterToolsForContext() from tool-filter.ts applies persona allowlist/denylist. Only permitted tools reach the agent." data-meta="Source: tool-filter.ts"><span class="fn-icon" style="color:var(--honey)">&#9881;</span>filterTools<span class="fn-label">Persona filter</span></div></div>
<span class="flow-arrow">&#8594;</span>
<div class="flow-step"><div class="flow-node" style="border-color: #fff" data-tip="Agent sees the filtered tool pool for the current chat turn. Tools presented via LLM tool-use protocol." data-meta="Ready for tool_use calls"><span class="fn-icon">&#129302;</span>Agent<span class="fn-label">Unified pool</span></div></div>
</div>
</div>
</div>
<script>
(function() {
'use strict';
var tabs = document.querySelectorAll('.tab');
var panels = document.querySelectorAll('.panel');
tabs.forEach(function(tab) {
tab.addEventListener('click', function() {
var target = this.getAttribute('data-tab');
tabs.forEach(function(t) { t.classList.remove('active'); });
panels.forEach(function(p) { p.classList.remove('active'); });
this.classList.add('active');
var panel = document.getElementById('panel-' + target);
if (panel) panel.classList.add('active');
});
});
var tooltipEl = document.getElementById('tooltip');
function safeText(s) {
var d = document.createElement('div');
d.textContent = s;
return d.innerHTML;
}
function positionTip(e) {
var x = e.clientX + 14, y = e.clientY + 14;
var w = tooltipEl.offsetWidth, h = tooltipEl.offsetHeight;
if (x + w > window.innerWidth - 12) x = e.clientX - w - 10;
if (y + h > window.innerHeight - 12) y = e.clientY - h - 10;
if (x < 4) x = 4;
if (y < 4) y = 4;
tooltipEl.style.left = x + 'px';
tooltipEl.style.top = y + 'px';
}
function showTip(el, e) {
var tip = el.getAttribute('data-tip');
var meta = el.getAttribute('data-meta');
if (!tip) return;
while (tooltipEl.firstChild) tooltipEl.removeChild(tooltipEl.firstChild);
var titleDiv = document.createElement('div');
titleDiv.style.cssText = 'color:#e5a000;font-weight:600;margin-bottom:4px';
titleDiv.textContent = tip;
tooltipEl.appendChild(titleDiv);
if (meta) {
var metaDiv = document.createElement('div');
metaDiv.style.cssText = 'color:#7f849e;font-size:12px';
metaDiv.textContent = meta;
tooltipEl.appendChild(metaDiv);
}
tooltipEl.classList.add('visible');
positionTip(e);
}
function attachTip(el) {
el.addEventListener('mouseenter', function(e) { showTip(this, e); });
el.addEventListener('mousemove', positionTip);
el.addEventListener('mouseleave', function() { tooltipEl.classList.remove('visible'); });
}
document.querySelectorAll('[data-tip]').forEach(attachTip);
// Build connector chips using DOM API
var connectors = [
['GitHub','\uD83D\uDC19','development'],['GitLab','\uD83E\uDD8A','development'],
['Bitbucket','\uD83E\uDE63','development'],['Slack','\uD83D\uDCAC','communication'],
['Discord','\uD83C\uDFAE','communication'],['MS Teams','\uD83D\uDCE2','communication'],
['Jira','\uD83D\uDCCB','productivity'],['Linear','\u26A1','productivity'],
['Asana','\u2705','productivity'],['Trello','\uD83D\uDCCC','productivity'],
['Monday','\uD83D\uDCC5','productivity'],['Notion','\uD83D\uDCD3','productivity'],
['Confluence','\uD83D\uDCD6','productivity'],['Obsidian','\uD83D\uDC8E','productivity'],
['HubSpot','\uD83E\uDD1D','crm'],['Salesforce','\u2601\uFE0F','crm'],
['Pipedrive','\uD83D\uDCCA','crm'],['Airtable','\uD83D\uDDC3\uFE0F','data'],
['Postgres','\uD83D\uDDC4\uFE0F','data'],['Gmail','\u2709\uFE0F','communication'],
['Email','\uD83D\uDCE7','communication'],['Outlook','\uD83D\uDCEC','communication'],
['Google Cal','\uD83D\uDCC6','productivity'],['Google Docs','\uD83D\uDDD2\uFE0F','productivity'],
['Google Drive','\uD83D\uDCC2','storage'],['Google Sheets','\uD83D\uDCCA','data'],
['Dropbox','\uD83D\uDCE6','storage'],['OneDrive','\u2601\uFE0F','storage'],
['Composio','\uD83C\uDF10','integration']
];
var cg = document.getElementById('native-connectors');
if (cg) {
connectors.forEach(function(c) {
var chip = document.createElement('div');
chip.className = 'connector-chip';
chip.setAttribute('data-tip', c[0] + ' connector - ' + c[2] + ' category');
chip.setAttribute('data-meta', 'Auth: Vault-based credential lookup');
var icon = document.createElement('span');
icon.className = 'cc-icon';
icon.textContent = c[1];
var wrap = document.createElement('span');
var nameText = document.createTextNode(c[0]);
var catSpan = document.createElement('span');
catSpan.className = 'cc-cat';
catSpan.textContent = c[2];
wrap.appendChild(nameText);
wrap.appendChild(catSpan);
chip.appendChild(icon);
chip.appendChild(wrap);
cg.appendChild(chip);
attachTip(chip);
});
}
// Build MCP category tiles using DOM API
var cats = [
['\uD83D\uDCBE','Database',18],['\uD83D\uDCC1','Files',12],
['\uD83C\uDF10','Web',14],['\uD83D\uDCBB','Code',16],
['\uD83D\uDCAC','Communication',8],['\uD83D\uDCCB','Productivity',15],
['\uD83D\uDCCA','Analytics',10],['\u2601\uFE0F','Cloud',11],
['\uD83D\uDD27','DevTools',13],['\uD83D\uDCBC','Business',9],
['\uD83E\uDD16','AI & ML',8],['\uD83D\uDD12','Security',5],
['\uD83C\uDFA8','Media',4],['\u2699\uFE0F','Utilities',5]
];
var mg = document.getElementById('mcp-categories');
if (mg) {
cats.forEach(function(c) {
var el = document.createElement('div');
el.className = 'mcp-cat';
el.setAttribute('data-tip', c[1] + ' category: ' + c[2] + ' MCP servers curated from 4 community sources');
el.setAttribute('data-meta', 'MCP_CATEGORIES from mcp-catalog.ts');
var emoji = document.createElement('span');
emoji.className = 'mc-emoji';
emoji.textContent = c[0];
var name = document.createElement('div');
name.className = 'mc-name';
name.textContent = c[1];
var count = document.createElement('div');
count.className = 'mc-count';
count.textContent = c[2] + ' servers';
el.appendChild(emoji);
el.appendChild(name);
el.appendChild(count);
mg.appendChild(el);
attachTip(el);
});
}
// Animated install flow highlight
var stages = document.querySelectorAll('.install-stage');
var cur = 0;
function animateInstall() {
stages.forEach(function(s) { s.classList.remove('highlight'); });
if (stages[cur]) stages[cur].classList.add('highlight');
cur = (cur + 1) % stages.length;
}
if (stages.length > 0) { animateInstall(); setInterval(animateInstall, 2000); }
})();
</script>
</body>
</html>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,720 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Waggle OS - Templates &amp; Personas</title>
<style>
:root {
--honey: #e5a000;
--honey-dim: #b38200;
--honey-glow: #f5c842;
--hive-950: #08090c;
--hive-900: #0f1117;
--hive-850: #161820;
--hive-800: #1c1f2a;
--hive-700: #282c3a;
--hive-600: #3a3f52;
--hive-500: #6b7280;
--hive-400: #9ca3af;
--hive-300: #d1d5db;
--accent: #a78bfa;
--accent-dim: #7c5cbf;
--green: #34d399;
--red: #f87171;
--blue: #60a5fa;
--orange: #fb923c;
}
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: 'Segoe UI', -apple-system, BlinkMacSystemFont, sans-serif;
background: var(--hive-950);
color: var(--hive-300);
line-height: 1.5;
overflow-x: hidden;
}
/* ── Tooltip (body-level, floating) ── */
#tooltip {
position: fixed;
z-index: 9999;
pointer-events: none;
background: var(--hive-800);
border: 1px solid var(--hive-600);
border-radius: 8px;
padding: 10px 14px;
max-width: 320px;
font-size: 12px;
color: var(--hive-300);
box-shadow: 0 8px 32px rgba(0,0,0,.6);
opacity: 0;
transition: opacity .15s;
}
#tooltip.visible { opacity: 1; }
#tooltip .tt-label { color: var(--honey); font-weight: 600; font-size: 11px; text-transform: uppercase; letter-spacing: .5px; margin-bottom: 2px; }
#tooltip .tt-body { color: var(--hive-300); }
/* ── Header ── */
header {
text-align: center;
padding: 48px 24px 32px;
border-bottom: 1px solid var(--hive-700);
background: linear-gradient(180deg, var(--hive-900) 0%, var(--hive-950) 100%);
}
header h1 { font-size: 28px; color: #fff; font-weight: 700; margin-bottom: 6px; }
header h1 span { color: var(--honey); }
header p { color: var(--hive-500); font-size: 14px; max-width: 600px; margin: 0 auto; }
/* ── Navigation ── */
nav {
display: flex; gap: 4px; justify-content: center; flex-wrap: wrap;
padding: 16px 24px;
background: var(--hive-900);
border-bottom: 1px solid var(--hive-700);
position: sticky; top: 0; z-index: 100;
}
nav button {
background: transparent; border: 1px solid var(--hive-700); color: var(--hive-400);
padding: 7px 16px; border-radius: 6px; cursor: pointer; font-size: 13px;
transition: all .15s;
}
nav button:hover { border-color: var(--honey-dim); color: var(--honey); }
nav button.active { background: var(--honey); color: var(--hive-950); border-color: var(--honey); font-weight: 600; }
/* ── Sections ── */
section { padding: 40px 24px; max-width: 1200px; margin: 0 auto; display: none; }
section.active { display: block; }
section h2 { font-size: 20px; color: #fff; margin-bottom: 4px; }
section h2 span { color: var(--honey); }
section .subtitle { color: var(--hive-500); font-size: 13px; margin-bottom: 24px; }
/* ── Grid ── */
.grid { display: grid; gap: 12px; }
.grid-3 { grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); }
.grid-4 { grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); }
/* ── Template Card ── */
.tpl-card {
background: var(--hive-850);
border: 1px solid var(--hive-700);
border-radius: 10px;
padding: 16px;
cursor: default;
transition: border-color .15s, transform .12s;
}
.tpl-card:hover { border-color: var(--honey-dim); transform: translateY(-2px); }
.tpl-card .tpl-icon { font-size: 28px; margin-bottom: 8px; }
.tpl-card .tpl-name { font-size: 14px; font-weight: 600; color: #fff; margin-bottom: 2px; }
.tpl-card .tpl-desc { font-size: 12px; color: var(--hive-500); margin-bottom: 8px; }
.tpl-card .tpl-persona { font-size: 11px; color: var(--accent); display: flex; align-items: center; gap: 4px; }
.tpl-card .tpl-hint { font-size: 11px; color: var(--hive-600); font-style: italic; margin-top: 6px; border-top: 1px solid var(--hive-700); padding-top: 6px; }
/* ── Persona Card ── */
.persona-card {
background: var(--hive-850);
border: 1px solid var(--hive-700);
border-radius: 10px;
padding: 14px;
cursor: pointer;
transition: border-color .15s, transform .12s;
position: relative;
}
.persona-card:hover { border-color: var(--honey-dim); transform: translateY(-2px); }
.persona-card .pc-icon { font-size: 24px; margin-bottom: 6px; }
.persona-card .pc-name { font-size: 13px; font-weight: 600; color: #fff; margin-bottom: 2px; }
.persona-card .pc-tagline { font-size: 11px; color: var(--hive-500); margin-bottom: 6px; min-height: 30px; }
.persona-card .pc-meta { display: flex; gap: 8px; flex-wrap: wrap; }
.persona-card .badge {
font-size: 10px; padding: 2px 7px; border-radius: 4px;
background: var(--hive-700); color: var(--hive-400);
}
.persona-card .badge.readonly { background: rgba(248,113,113,.15); color: var(--red); }
.persona-card .badge.tools { background: rgba(96,165,250,.12); color: var(--blue); }
/* ── Tier Labels ── */
.tier-section { margin-bottom: 28px; }
.tier-label {
display: inline-block;
font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px;
padding: 4px 12px; border-radius: 4px; margin-bottom: 12px;
}
.tier-label.universal { background: rgba(229,160,0,.15); color: var(--honey); }
.tier-label.knowledge { background: rgba(167,139,250,.12); color: var(--accent); }
.tier-label.domain { background: rgba(96,165,250,.1); color: var(--blue); }
/* ── Matrix ── */
.matrix-wrap { overflow-x: auto; }
.matrix {
border-collapse: collapse; font-size: 12px; width: 100%; min-width: 900px;
}
.matrix th, .matrix td { padding: 6px 8px; border: 1px solid var(--hive-700); text-align: center; }
.matrix th { background: var(--hive-800); color: var(--hive-400); font-weight: 600; position: sticky; top: 0; }
.matrix th.row-head { text-align: left; min-width: 150px; }
.matrix td.row-head { text-align: left; color: #fff; font-weight: 500; background: var(--hive-850); }
.matrix .dot { display: inline-block; width: 10px; height: 10px; border-radius: 50%; }
.matrix .dot.default { background: var(--honey); }
.matrix .dot.affinity { background: var(--hive-600); }
/* ── Anatomy ── */
.anatomy { max-width: 760px; }
.anatomy-header { display: flex; align-items: center; gap: 12px; margin-bottom: 20px; }
.anatomy-header .icon { font-size: 36px; }
.anatomy-header .info h3 { color: #fff; font-size: 18px; }
.anatomy-header .info p { color: var(--hive-500); font-size: 13px; }
.anatomy-selector { margin-bottom: 20px; }
.anatomy-selector select {
background: var(--hive-800); color: #fff; border: 1px solid var(--hive-600);
padding: 8px 12px; border-radius: 6px; font-size: 13px; cursor: pointer;
}
.field-group { margin-bottom: 16px; }
.field-group .field-label {
font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .5px;
color: var(--honey); margin-bottom: 4px;
}
.field-group .field-value {
background: var(--hive-800); border: 1px solid var(--hive-700); border-radius: 6px;
padding: 10px 12px; font-size: 12px; color: var(--hive-300); line-height: 1.6;
white-space: pre-wrap; font-family: 'Consolas', 'Courier New', monospace;
}
.field-group .tag-list { display: flex; flex-wrap: wrap; gap: 4px; }
.field-group .tag {
font-size: 11px; padding: 3px 8px; border-radius: 4px;
background: var(--hive-700); color: var(--hive-300);
}
.field-group .tag.allow { background: rgba(52,211,153,.12); color: var(--green); }
.field-group .tag.deny { background: rgba(248,113,113,.12); color: var(--red); }
.field-group .tag.fail { background: rgba(251,146,60,.1); color: var(--orange); }
/* ── Override Diagram (Section 5) ── */
.override-flow {
display: flex; align-items: center; gap: 0; flex-wrap: wrap;
justify-content: center; margin: 32px 0;
}
.flow-box {
background: var(--hive-800); border: 1px solid var(--hive-700); border-radius: 8px;
padding: 16px 20px; text-align: center; min-width: 160px;
}
.flow-box .fb-title { font-size: 11px; color: var(--honey); font-weight: 700; text-transform: uppercase; letter-spacing: .5px; margin-bottom: 4px; }
.flow-box .fb-value { font-size: 14px; color: #fff; font-weight: 600; }
.flow-box .fb-sub { font-size: 11px; color: var(--hive-500); margin-top: 2px; }
.flow-arrow { color: var(--hive-600); font-size: 22px; padding: 0 8px; user-select: none; }
.window-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 12px; margin-top: 24px; }
.win-card {
background: var(--hive-850); border: 1px solid var(--hive-700); border-radius: 8px;
padding: 14px; position: relative;
}
.win-card .win-title { font-size: 13px; color: #fff; font-weight: 600; margin-bottom: 4px; display: flex; align-items: center; gap: 6px; }
.win-card .win-persona { font-size: 12px; color: var(--accent); }
.win-card .win-tools { font-size: 11px; color: var(--hive-500); margin-top: 4px; }
.win-card .win-badge {
position: absolute; top: 8px; right: 8px; font-size: 9px;
padding: 2px 6px; border-radius: 3px;
background: rgba(229,160,0,.15); color: var(--honey);
}
.legend { margin-top: 24px; padding: 16px; background: var(--hive-800); border-radius: 8px; border: 1px solid var(--hive-700); }
.legend h4 { font-size: 12px; color: var(--honey); margin-bottom: 8px; text-transform: uppercase; letter-spacing: .5px; }
.legend p { font-size: 12px; color: var(--hive-400); margin-bottom: 4px; }
.legend strong { color: var(--honey); }
@media (max-width: 640px) {
nav { gap: 2px; }
nav button { font-size: 11px; padding: 5px 10px; }
.grid-3, .grid-4 { grid-template-columns: 1fr; }
}
</style>
</head>
<body>
<div id="tooltip"><div class="tt-label"></div><div class="tt-body"></div></div>
<header>
<h1>Waggle <span>OS</span> - Templates &amp; Personas</h1>
<p>Workspace template system and 22 agent personas. Hive DS visual reference.</p>
</header>
<nav>
<button class="active" data-tab="templates">15 Templates</button>
<button data-tab="personas">22 Personas</button>
<button data-tab="mapping">Template-Persona Map</button>
<button data-tab="anatomy">Persona Anatomy</button>
<button data-tab="override">Per-Window Override</button>
</nav>
<!-- SECTION 1: 15 WORKSPACE TEMPLATES -->
<section id="sec-templates" class="active">
<h2><span>15</span> Workspace Templates</h2>
<p class="subtitle">Each template pre-configures a workspace with a default persona, starter hint, and relevant tools.</p>
<div class="grid grid-3" id="template-grid"></div>
</section>
<!-- SECTION 2: 22 AGENT PERSONAS -->
<section id="sec-personas">
<h2><span>22</span> Agent Personas</h2>
<p class="subtitle">Three tiers: Universal Modes (cross-domain), Knowledge Workers (core skills), and Workspace Specialists (domain-specific). Click a card to inspect in Anatomy.</p>
<div class="tier-section" id="tier-universal"></div>
<div class="tier-section" id="tier-knowledge"></div>
<div class="tier-section" id="tier-domain"></div>
</section>
<!-- SECTION 3: TEMPLATE -> PERSONA MAPPING MATRIX -->
<section id="sec-mapping">
<h2>Template <span>&rarr;</span> Persona Mapping</h2>
<p class="subtitle">Gold dot = default persona for that template. Grey dot = workspace affinity overlap.</p>
<div class="matrix-wrap">
<table class="matrix" id="mapping-table"></table>
</div>
</section>
<!-- SECTION 4: PERSONA ANATOMY -->
<section id="sec-anatomy">
<h2>Persona <span>Anatomy</span></h2>
<p class="subtitle">Full internal structure of a persona. Select any persona to inspect all fields.</p>
<div class="anatomy">
<div class="anatomy-selector">
<select id="anatomy-select"></select>
</div>
<div id="anatomy-content"></div>
</div>
</section>
<!-- SECTION 5: PER-WINDOW PERSONA OVERRIDE -->
<section id="sec-override">
<h2>Per-Window <span>Persona Override</span></h2>
<p class="subtitle">Phase A.2 consistency: each window can run a different persona. Workspace default cascades down unless overridden.</p>
<div class="override-flow">
<div class="flow-box">
<div class="fb-title">Workspace Default</div>
<div class="fb-value">Researcher</div>
<div class="fb-sub">Set during onboarding</div>
</div>
<div class="flow-arrow">&rarr;</div>
<div class="flow-box">
<div class="fb-title">Per-Window Override</div>
<div class="fb-value">Any Persona</div>
<div class="fb-sub">Via PersonaSwitcher</div>
</div>
<div class="flow-arrow">&rarr;</div>
<div class="flow-box">
<div class="fb-title">Tool Filtering</div>
<div class="fb-value">filterToolsForContext()</div>
<div class="fb-sub">allowlist + denylist enforced</div>
</div>
</div>
<h3 style="color:#fff; font-size:14px; margin-bottom:12px;">Example: Research Hub workspace with 4 windows</h3>
<div class="window-grid" id="window-examples"></div>
<div class="legend">
<h4>How It Works</h4>
<p><strong>1. Workspace creation:</strong> Template sets a default persona (e.g. Research Hub sets Researcher).</p>
<p><strong>2. Window spawn:</strong> New windows inherit the workspace default persona.</p>
<p><strong>3. Per-window override:</strong> User clicks PersonaSwitcher in any window to change that window's persona independently.</p>
<p><strong>4. Tool filtering:</strong> tool-filter.ts enforces the active persona's allowlist/denylist. A Planner window cannot call write_file even if another window can.</p>
<p><strong>5. Consistency:</strong> Per-session orchestrators track which persona each window uses. The agent-loop reads the active persona from the window context, not the workspace default.</p>
</div>
</section>
<script>
/* ================================================================
DATA -- extracted from persona-data.ts and onboarding/constants.ts
================================================================ */
var TEMPLATES = [
{ id: 'sales-pipeline', name: 'Sales Pipeline', icon: '\uD83C\uDFAF', desc: 'Track deals and prospects', hint: 'Research the top 5 competitors in my industry', persona: 'sales-rep' },
{ id: 'research-project', name: 'Research Hub', icon: '\uD83D\uDD2C', desc: 'Deep dive into any subject', hint: 'Help me design a literature review on my topic', persona: 'researcher' },
{ id: 'code-review', name: 'Engineering', icon: '\uD83D\uDCBB', desc: 'Code, review, and ship', hint: 'Read my project and tell me what you see', persona: 'coder' },
{ id: 'marketing-campaign', name: 'Marketing & Content', icon: '\uD83D\uDCE2', desc: 'Campaigns, copy, and SEO', hint: 'Draft a campaign brief for my product launch', persona: 'marketer' },
{ id: 'product-launch', name: 'Product Management', icon: '\uD83D\uDE80', desc: 'Specs, roadmaps, and launches', hint: 'Help me write a PRD for my next feature', persona: 'product-manager-senior' },
{ id: 'legal-review', name: 'Legal & Compliance', icon: '\u2696\uFE0F', desc: 'Contracts, compliance, and risk', hint: 'Draft a standard NDA template', persona: 'legal-professional' },
{ id: 'agency-consulting', name: 'Consulting', icon: '\uD83C\uDFE2', desc: 'Client delivery and strategy', hint: 'Set up client workspaces for my biggest accounts', persona: 'consultant' },
{ id: 'customer-support', name: 'Customer Support', icon: '\uD83C\uDFA7', desc: 'Tickets, KB, and escalation', hint: 'Help me draft a response to this customer issue', persona: 'support-agent' },
{ id: 'finance-accounting', name: 'Finance', icon: '\uD83D\uDCB0', desc: 'Budgets, reports, and close', hint: 'Prepare a variance analysis for this month', persona: 'finance-owner' },
{ id: 'hr-people', name: 'HR & People', icon: '\uD83D\uDC65', desc: 'Hiring, policy, and onboarding', hint: 'Draft a job description for a senior engineer', persona: 'hr-manager' },
{ id: 'operations-center', name: 'Operations', icon: '\u2699\uFE0F', desc: 'Processes, SOPs, and vendors', hint: 'Create an SOP for our onboarding process', persona: 'ops-manager' },
{ id: 'data-analytics', name: 'Data & Analytics', icon: '\uD83D\uDCC8', desc: 'SQL, dashboards, and insights', hint: 'Write a SQL query to find our top customers', persona: 'data-engineer' },
{ id: 'recruiting-pipeline', name: 'Recruiting', icon: '\uD83E\uDD1D', desc: 'Source, screen, and hire', hint: 'Write a job description and screening scorecard', persona: 'recruiter' },
{ id: 'design-studio', name: 'Design Studio', icon: '\uD83C\uDFA8', desc: 'Briefs, feedback, and brand', hint: 'Write a creative brief for our rebrand', persona: 'creative-director' },
{ id: 'blank', name: 'Blank Workspace', icon: '\u2795', desc: 'Start from scratch', hint: 'Hello! What can you help me with?', persona: 'general-purpose' }
];
var PERSONAS = [
{ id:'general-purpose', name:'General Purpose', icon:'\uD83E\uDDE0', tier:'universal', tagline:'Adapts to whatever you need. Suggests a specialist when one would do better.', tools:['bash','read_file','write_file','edit_file','search_files','search_content','web_search','web_fetch','search_memory','save_memory','generate_docx','create_plan','add_plan_step','execute_step','show_plan','spawn_agent','list_agents','get_agent_result','git_status','git_diff','git_log','git_commit','list_skills','suggest_skill','acquire_capability','install_capability','compose_workflow','orchestrate_workflow','query_knowledge','get_identity','get_awareness'], disallowedTools:[], isReadOnly:false, modelPreference:'claude-sonnet-4-6', workspaceAffinity:['general','mixed','personal','exploration'], failurePatterns:['Staying general when a specialist is warranted','Doing too much in one turn without a plan','Not saving key findings to memory'], bestFor:['Tasks that cross multiple domains','Quick exploratory work','Anything where you want the AI to adapt'], wontDo:'Nothing is structurally off-limits -- suggests switching to a specialist when warranted.', systemPrompt:'Versatile agent that adapts to whatever the user needs. Full tool set.' },
{ id:'planner', name:'Planner', icon:'\uD83D\uDDC2\uFE0F', tier:'universal', tagline:'Draws the blueprint before anyone picks up a tool.', tools:['read_file','search_files','search_content','web_search','web_fetch','search_memory','query_knowledge','get_awareness','create_plan','add_plan_step','show_plan','suggest_skill','list_skills','bash'], disallowedTools:['write_file','edit_file','git_commit','git_push','git_merge','generate_docx','install_capability','spawn_agent','execute_step','save_memory'], isReadOnly:true, modelPreference:'claude-sonnet-4-6', workspaceAffinity:['strategy','planning','architecture','project','research'], failurePatterns:['Planning without reading files/memory first','One-option thinking','Vague steps'], bestFor:['Thinking through approaches before starting','Breaking complex projects into phases','Evaluating approaches with trade-offs'], wontDo:'Will not create or modify any files. Read-only -- thinks and structures only.', systemPrompt:'Planning and architecture specialist. Explores context, analyzes options, designs approaches. Does NOT execute.' },
{ id:'verifier', name:'Verifier', icon:'\uD83D\uDD0D', tier:'universal', tagline:'Your most critical colleague. Finds what is wrong before it matters.', tools:['read_file','search_files','search_content','web_search','web_fetch','search_memory','query_knowledge','bash','show_plan'], disallowedTools:['write_file','edit_file','git_commit','git_push','git_merge','generate_docx','save_memory','install_capability','spawn_agent','execute_step'], isReadOnly:true, modelPreference:'claude-sonnet-4-6', workspaceAffinity:['quality','review','verification','audit'], failurePatterns:['Verification avoidance -- narrating not running','First-80% seduction','Confirmation bias'], bestFor:['Reviewing output for accuracy and completeness','Fact-checking claims against sources','Code review for logic errors and edge cases'], wontDo:'Will not modify anything or produce a fixed version. Identifies problems only.', systemPrompt:'Adversarial QA. Tries to BREAK outputs. VERDICT: PASS/FAIL/PARTIAL.' },
{ id:'coordinator', name:'Coordinator', icon:'\uD83C\uDF9B\uFE0F', tier:'universal', tagline:'Designs the workflow. Directs the specialists. Never picks up a tool itself.', tools:['spawn_agent','list_agents','get_agent_result','search_memory','save_memory','query_knowledge','get_awareness','create_plan','add_plan_step','execute_step','show_plan'], disallowedTools:['read_file','write_file','edit_file','bash','web_search','web_fetch','search_files','search_content','generate_docx','git_status','git_diff','git_log','git_commit'], isReadOnly:false, modelPreference:'claude-sonnet-4-6', workspaceAffinity:['orchestration','complex-projects','multi-phase','coordination'], failurePatterns:['Delegating without synthesizing','Vague worker prompts','Skipping the Verifier'], bestFor:['Complex multi-phase projects','Parallel research feeding sequential execution','AI managing its own workflow end-to-end'], wontDo:'Will not read files, write files, run bash, or search the web. All execution by spawned workers.', systemPrompt:'Pure orchestrator. Delegates to specialists, synthesizes results, never executes directly.' },
{ id:'researcher', name:'Researcher', icon:'\uD83D\uDD2C', tier:'knowledge', tagline:'Finds truth across sources -- never assumes, always cites.', tools:['web_search','web_fetch','search_memory','save_memory','read_file','write_file','search_files','search_content','generate_docx'], disallowedTools:[], isReadOnly:false, modelPreference:'claude-sonnet-4-6', workspaceAffinity:['research','analysis','investigation','due-diligence'], failurePatterns:['Single-source research','Not saving findings','Presenting research as conclusions'], bestFor:['Deep-dive research across web, files, and memory','Literature reviews and competitive intelligence','Fact-checking and source triangulation'], wontDo:'Will not produce final deliverables or make decisions.', systemPrompt:'Deep investigation and multi-source synthesis. Always cite sources.' },
{ id:'writer', name:'Writer', icon:'\u270D\uFE0F', tier:'knowledge', tagline:'Drafts, edits, and polishes -- always asks about audience first.', tools:['read_file','write_file','edit_file','search_files','search_memory','save_memory','generate_docx'], disallowedTools:['bash','git_commit','git_push','spawn_agent'], isReadOnly:false, modelPreference:'claude-sonnet-4-6', workspaceAffinity:['writing','content','documentation','proposals'], failurePatterns:['Drafting before gathering context','Wrong scope','Ignoring workspace tone'], bestFor:['Blog posts, reports, proposals, and documentation','Editing for clarity','Adapting tone for different audiences'], wontDo:'Will not run code, execute bash, or manage git.', systemPrompt:'Document creation, editing, and formatting. Ask about audience and purpose first.' },
{ id:'analyst', name:'Analyst', icon:'\uD83D\uDCCA', tier:'knowledge', tagline:'Turns noise into signal with numbers, not adjectives.', tools:['bash','read_file','write_file','search_files','search_content','web_search','web_fetch','search_memory','save_memory','generate_docx'], disallowedTools:[], isReadOnly:false, modelPreference:'claude-sonnet-4-6', workspaceAffinity:['analysis','data','strategy','reporting'], failurePatterns:['Analysis without data','Conclusions without evidence chain','Report when user asked for analysis'], bestFor:['Data analysis with tables, matrices, and frameworks','Decision support with quantified trade-offs','Processing CSV/JSON data'], wontDo:'Will not produce final documents or take action.', systemPrompt:'Data analysis, pattern recognition, and structured decision-making.' },
{ id:'coder', name:'Coder', icon:'\uD83D\uDCBB', tier:'knowledge', tagline:'Reads before writing, tests alongside implementing.', tools:['bash','read_file','write_file','edit_file','search_files','search_content','git_status','git_diff','git_log','git_commit','git_branch','git_stash','git_push','git_pull','git_merge','git_pr'], disallowedTools:[], isReadOnly:false, modelPreference:'claude-sonnet-4-6', workspaceAffinity:['development','coding','engineering','debugging'], failurePatterns:['Writing new utils without checking existing ones','Changes without reading git_log','Large refactors for small fix requests'], bestFor:['Code review, debugging, and refactoring','Implementing features with test coverage','Understanding codebases'], wontDo:'Will not guess about code it has not read.', systemPrompt:'Software development, debugging, and code architecture.' },
{ id:'project-manager', name:'Project Manager', icon:'\uD83D\uDCCB', tier:'domain', tagline:'Breaks big goals into steps and tracks every one.', tools:['create_plan','add_plan_step','execute_step','show_plan','search_memory','save_memory','read_file','search_files','write_file'], disallowedTools:['git_commit','git_push','bash'], isReadOnly:false, modelPreference:'claude-sonnet-4-6', workspaceAffinity:['project','management','coordination','planning'], failurePatterns:['Plans without reading existing context','Vague task assignments','Not saving status updates'], bestFor:['Breaking complex projects into phased plans','Status reports with blockers','Coordinating multi-step work'], wontDo:'Will not write production code or deploy.', systemPrompt:'Task management, status tracking, and coordination.' },
{ id:'executive-assistant', name:'Executive Assistant', icon:'\uD83D\uDCE7', tier:'domain', tagline:'Drafts, schedules, and prepares -- always confirms before sending.', tools:['search_memory','save_memory','read_file','write_file','web_search','generate_docx'], disallowedTools:['bash','git_commit','git_push','spawn_agent'], isReadOnly:false, modelPreference:'claude-sonnet-4-6', workspaceAffinity:['executive','admin','communication','scheduling'], failurePatterns:['Drafting without searching memory for prior context','Sending without confirmation','Generic briefings'], bestFor:['Email drafting with appropriate tone','Meeting prep with context from memory','Summarizing long documents'], wontDo:'Will not send external communications without explicit confirmation.', systemPrompt:'Executive support -- communication, scheduling, and preparation.' },
{ id:'sales-rep', name:'Sales Rep', icon:'\uD83C\uDFAF', tier:'domain', tagline:'Researches before reaching out, personalizes everything.', tools:['web_search','web_fetch','search_memory','save_memory','read_file','write_file','generate_docx'], disallowedTools:['git_commit','git_push','bash','spawn_agent'], isReadOnly:false, modelPreference:'claude-sonnet-4-6', workspaceAffinity:['sales','outreach','pipeline','prospecting'], failurePatterns:['Outreach without checking memory for prior interactions','Generic value propositions','Not saving prospect research'], bestFor:['Prospect research -- company intel, key contacts','Personalized outreach emails','Pipeline tracking and deal stage management'], wontDo:'Will not send outreach without checking memory for prior interactions.', systemPrompt:'Sales research, outreach, and pipeline management.' },
{ id:'marketer', name:'Marketer', icon:'\uD83D\uDCE2', tier:'domain', tagline:'Creates content that knows its audience and measures its impact.', tools:['web_search','web_fetch','search_memory','save_memory','read_file','write_file','generate_docx'], disallowedTools:['bash','git_commit','git_push','spawn_agent'], isReadOnly:false, modelPreference:'claude-sonnet-4-6', workspaceAffinity:['marketing','content','social-media','brand'], failurePatterns:['Creating content without brand guidelines','Generic copy when audience context exists','Not saving campaign data'], bestFor:['Content aligned with brand voice','Campaign planning with goals and metrics','SEO-optimized web content'], wontDo:'Will not create content without checking brand guidelines first.', systemPrompt:'Marketing content, campaign strategy, and digital presence.' },
{ id:'product-manager-senior', name:'Senior PM', icon:'\uD83D\uDDFA\uFE0F', tier:'domain', tagline:'Structures ambiguity into specs with measurable outcomes.', tools:['search_memory','save_memory','web_search','web_fetch','create_plan','add_plan_step','execute_step','show_plan','generate_docx','search_files','read_file','write_file'], disallowedTools:['bash','git_commit','git_push'], isReadOnly:false, modelPreference:'claude-sonnet-4-6', workspaceAffinity:['product','roadmap','strategy','planning'], failurePatterns:['PRDs without user research','Skipping decision documentation','Vague acceptance criteria'], bestFor:['PRD drafting with RICE scoring','Decision tracking across sessions','Roadmap planning'], wontDo:'Will not write production code or deploy infrastructure.', systemPrompt:'Structured product thinking, decision tracking, and roadmap management.' },
{ id:'hr-manager', name:'HR Manager', icon:'\uD83D\uDC65', tier:'domain', tagline:'Policy-first, compliance-aware, people-focused.', tools:['search_memory','save_memory','create_plan','add_plan_step','show_plan','generate_docx','web_search','read_file','write_file','search_files'], disallowedTools:['bash','git_commit','git_push','spawn_agent'], isReadOnly:false, modelPreference:'claude-sonnet-4-6', workspaceAffinity:['hr','people','policy','compliance'], failurePatterns:['Answering without searching stored policies','Generic job descriptions','Not flagging legal risk areas'], bestFor:['Onboarding checklists and new hire docs','Policy compliance review','Job descriptions with competencies'], wontDo:'Will not provide binding legal advice.', systemPrompt:'HR policy, onboarding, compliance, and employee communications.' },
{ id:'legal-professional', name:'Legal Counsel', icon:'\u2696\uFE0F', tier:'domain', tagline:'Precise language, jurisdiction-aware, always flags assumptions.', tools:['search_memory','save_memory','generate_docx','web_search','web_fetch','read_file','write_file','search_files'], disallowedTools:['bash','git_commit','git_push','spawn_agent'], isReadOnly:false, modelPreference:'claude-sonnet-4-6', workspaceAffinity:['legal','contracts','compliance','risk'], failurePatterns:['Contract review without searching precedents','Jurisdiction-specific advice without flagging','Missing Assumptions Made section'], bestFor:['Contract clause analysis and risk identification','Compliance checklists and regulatory research','Legal correspondence drafting'], wontDo:'Will not provide binding legal advice or represent attorney-client privilege.', systemPrompt:'Contract analysis, legal correspondence, and compliance documentation.' },
{ id:'finance-owner', name:'Business Finance', icon:'\uD83D\uDCB0', tier:'domain', tagline:'Numbers with assumptions stated, projections with sensitivity.', tools:['search_memory','save_memory','generate_docx','web_search','web_fetch','read_file','write_file','search_files','create_plan','add_plan_step','show_plan'], disallowedTools:['bash','git_commit','git_push','spawn_agent'], isReadOnly:false, modelPreference:'claude-sonnet-4-6', workspaceAffinity:['finance','accounting','business','budgets'], failurePatterns:['Numbers without stated assumptions','Analysis without checking stored financial data','Missing sensitivity factors'], bestFor:['Budget analysis and cash flow projections','Variance analysis with explicit assumptions','Financial reporting'], wontDo:'Will not present projections without stating key assumptions.', systemPrompt:'Financial analysis, budgeting, and business finance communications.' },
{ id:'consultant', name:'Strategy Consultant', icon:'\uD83C\uDFAF', tier:'domain', tagline:'Structures everything, cites everything, executive summary first.', tools:['search_memory','save_memory','web_search','web_fetch','generate_docx','read_file','write_file','search_files','create_plan','add_plan_step','execute_step','show_plan','bash'], disallowedTools:[], isReadOnly:false, modelPreference:'claude-sonnet-4-6', workspaceAffinity:['consulting','strategy','analysis','research'], failurePatterns:['Framework-first thinking','Deliverable without executive summary','Research without saving'], bestFor:['Client deliverables with structured frameworks','Multi-source research synthesis','Executive summaries and strategic recommendations'], wontDo:'Will not deliver analysis without an executive summary.', systemPrompt:'Top-tier management consultant. Structure everything. Depth over breadth.' },
{ id:'support-agent', name:'Customer Support', icon:'\uD83C\uDFA7', tier:'domain', tagline:'Resolves fast, escalates smart, turns tickets into KB articles.', tools:['search_memory','save_memory','web_search','web_fetch','read_file','write_file','generate_docx','create_plan','add_plan_step','show_plan'], disallowedTools:[], isReadOnly:false, modelPreference:'claude-sonnet-4-6', workspaceAffinity:['support','customer-success','helpdesk','service'], failurePatterns:['Resolving without checking KB first','Escalating without packaging context','Generic responses'], bestFor:['Resolving issues using KB and memory','Drafting professional support responses','Creating KB articles from resolved tickets'], wontDo:'Will not resolve tickets without checking existing KB and memory first.', systemPrompt:'Customer issue resolution, knowledge management, and escalation handling.' },
{ id:'ops-manager', name:'Operations Manager', icon:'\u2699\uFE0F', tier:'domain', tagline:'Processes, SOPs, and vendor management -- operational excellence.', tools:['search_memory','save_memory','read_file','write_file','generate_docx','create_plan','add_plan_step','execute_step','show_plan','web_search'], disallowedTools:[], isReadOnly:false, modelPreference:'claude-sonnet-4-6', workspaceAffinity:['operations','process','procurement','logistics'], failurePatterns:['Designing processes without baseline measurement','SOPs without version numbers','Vendor evaluations without weighted scoring'], bestFor:['Standard Operating Procedures','Vendor evaluation with weighted scoring','Process optimization'], wontDo:'Will not design processes without measuring the current baseline.', systemPrompt:'Process design, documentation, vendor management, and operational efficiency.' },
{ id:'data-engineer', name:'Data Engineer', icon:'\uD83D\uDCC8', tier:'domain', tagline:'SQL, pipelines, dashboards -- makes data accessible and trustworthy.', tools:['bash','read_file','write_file','edit_file','search_files','search_content','search_memory','save_memory','web_search','generate_docx'], disallowedTools:[], isReadOnly:false, modelPreference:'claude-sonnet-4-6', workspaceAffinity:['data','analytics','bi','reporting'], failurePatterns:['Writing queries without exploring schema','Raw data without context','Not saving working queries'], bestFor:['SQL queries across databases','Data exploration and quality assessment','Dashboard design and visualization planning'], wontDo:'Will not write queries without exploring the schema first.', systemPrompt:'Data access, SQL, pipeline design, and making data useful.' },
{ id:'recruiter', name:'Recruiter', icon:'\uD83E\uDD1D', tier:'domain', tagline:'Sources, screens, and manages candidates through the full pipeline.', tools:['web_search','web_fetch','search_memory','save_memory','read_file','write_file','generate_docx','create_plan','add_plan_step','show_plan'], disallowedTools:[], isReadOnly:false, modelPreference:'claude-sonnet-4-6', workspaceAffinity:['recruiting','hiring','talent','hr'], failurePatterns:['JDs without role-specific competencies','Screening without structured scorecard','Not saving candidate context'], bestFor:['Job descriptions with competencies','Candidate sourcing with structured scorecards','Interview preparation with rubrics'], wontDo:'Will not screen candidates without a structured scorecard.', systemPrompt:'Talent acquisition -- sourcing, screening, job descriptions, and interview preparation.' },
{ id:'creative-director', name:'Creative Director', icon:'\uD83C\uDFA8', tier:'domain', tagline:'Briefs, feedback synthesis, and brand consistency guardian.', tools:['search_memory','save_memory','web_search','web_fetch','read_file','write_file','generate_docx'], disallowedTools:[], isReadOnly:false, modelPreference:'claude-sonnet-4-6', workspaceAffinity:['design','creative','brand','marketing'], failurePatterns:['Creating without brand guidelines','Feedback without structured synthesis','Delivering without version tracking'], bestFor:['Creative briefs with clear objectives','Synthesizing feedback from multiple stakeholders','Brand voice and visual consistency auditing'], wontDo:'Will not create deliverables without checking brand guidelines first.', systemPrompt:'Creative direction -- briefs, feedback management, brand consistency, and design thinking.' }
];
var TEMPLATE_PERSONA = {
'sales-pipeline':'sales-rep', 'research-project':'researcher', 'code-review':'coder',
'marketing-campaign':'marketer', 'product-launch':'product-manager-senior', 'legal-review':'legal-professional',
'agency-consulting':'consultant', 'customer-support':'support-agent', 'finance-accounting':'finance-owner',
'hr-people':'hr-manager', 'operations-center':'ops-manager', 'data-analytics':'data-engineer',
'recruiting-pipeline':'recruiter', 'design-studio':'creative-director', 'blank':'general-purpose'
};
/* ── Tooltip ── */
var ttEl = document.getElementById('tooltip');
var ttLabel = ttEl.querySelector('.tt-label');
var ttBody = ttEl.querySelector('.tt-body');
function showTooltip(e, label, body) {
ttLabel.textContent = label;
ttBody.textContent = '';
/* Build body safely via text nodes and line breaks */
var lines = body.split('\n');
for (var i = 0; i < lines.length; i++) {
if (i > 0) ttBody.appendChild(document.createElement('br'));
ttBody.appendChild(document.createTextNode(lines[i]));
}
ttEl.classList.add('visible');
positionTooltip(e);
}
function positionTooltip(e) {
var pad = 12;
var x = e.clientX + pad, y = e.clientY + pad;
var r = ttEl.getBoundingClientRect();
if (x + r.width > window.innerWidth) x = e.clientX - r.width - pad;
if (y + r.height > window.innerHeight) y = e.clientY - r.height - pad;
ttEl.style.left = x + 'px';
ttEl.style.top = y + 'px';
}
function hideTooltip() { ttEl.classList.remove('visible'); }
document.addEventListener('mousemove', function(e) {
if (ttEl.classList.contains('visible')) positionTooltip(e);
});
/* ── Tab navigation ── */
document.querySelectorAll('nav button').forEach(function(btn) {
btn.addEventListener('click', function() {
document.querySelectorAll('nav button').forEach(function(b) { b.classList.remove('active'); });
document.querySelectorAll('section').forEach(function(s) { s.classList.remove('active'); });
btn.classList.add('active');
document.getElementById('sec-' + btn.dataset.tab).classList.add('active');
});
});
/* ── Helper: create element with classes and text ── */
function el(tag, cls, text) {
var e = document.createElement(tag);
if (cls) e.className = cls;
if (text) e.textContent = text;
return e;
}
/* ================================================================
SECTION 1: Templates Grid
================================================================ */
(function renderTemplates() {
var grid = document.getElementById('template-grid');
TEMPLATES.forEach(function(t) {
var p = PERSONAS.find(function(p) { return p.id === t.persona; });
var card = el('div', 'tpl-card');
card.appendChild(el('div', 'tpl-icon', t.icon));
card.appendChild(el('div', 'tpl-name', t.name));
card.appendChild(el('div', 'tpl-desc', t.desc));
var personaEl = el('div', 'tpl-persona');
personaEl.textContent = (p ? p.icon + ' ' : '') + 'Default: ' + (p ? p.name : t.persona);
card.appendChild(personaEl);
var hintEl = el('div', 'tpl-hint');
hintEl.textContent = '"' + t.hint + '"';
card.appendChild(hintEl);
card.addEventListener('mouseenter', function(e) {
showTooltip(e, t.name,
'ID: ' + t.id + '\nDefault persona: ' + (p ? p.name : t.persona) + '\nStarter hint: ' + t.hint);
});
card.addEventListener('mouseleave', hideTooltip);
grid.appendChild(card);
});
})();
/* ================================================================
SECTION 2: Personas Grid (3-tier)
================================================================ */
function renderPersonaTier(containerId, tierName, tierLabel) {
var container = document.getElementById(containerId);
var personas = PERSONAS.filter(function(p) { return p.tier === tierName; });
var label = el('div', 'tier-label ' + tierName, tierLabel + ' (' + personas.length + ')');
container.appendChild(label);
var grid = el('div', 'grid grid-4');
personas.forEach(function(p) {
var card = el('div', 'persona-card');
card.dataset.pid = p.id;
card.appendChild(el('div', 'pc-icon', p.icon));
card.appendChild(el('div', 'pc-name', p.name));
card.appendChild(el('div', 'pc-tagline', p.tagline));
var meta = el('div', 'pc-meta');
var toolsBadge = el('span', 'badge tools', p.tools.length + ' tools');
meta.appendChild(toolsBadge);
if (p.isReadOnly) {
meta.appendChild(el('span', 'badge readonly', 'READ-ONLY'));
}
if (p.disallowedTools && p.disallowedTools.length > 0) {
meta.appendChild(el('span', 'badge', p.disallowedTools.length + ' denied'));
}
card.appendChild(meta);
card.addEventListener('mouseenter', function(e) {
showTooltip(e, p.name,
'Tagline: ' + p.tagline +
'\n\nBest for:\n- ' + p.bestFor.join('\n- ') +
'\n\nWon\'t do: ' + p.wontDo +
'\nModel: ' + p.modelPreference);
});
card.addEventListener('mouseleave', hideTooltip);
card.addEventListener('click', function() {
document.querySelectorAll('nav button').forEach(function(b) { b.classList.remove('active'); });
document.querySelectorAll('section').forEach(function(s) { s.classList.remove('active'); });
document.querySelector('[data-tab="anatomy"]').classList.add('active');
document.getElementById('sec-anatomy').classList.add('active');
document.getElementById('anatomy-select').value = p.id;
renderAnatomy(p.id);
});
grid.appendChild(card);
});
container.appendChild(grid);
}
renderPersonaTier('tier-universal', 'universal', 'Universal Modes');
renderPersonaTier('tier-knowledge', 'knowledge', 'Knowledge Workers');
renderPersonaTier('tier-domain', 'domain', 'Workspace Specialists');
/* ================================================================
SECTION 3: Mapping Matrix
================================================================ */
(function renderMatrix() {
var table = document.getElementById('mapping-table');
var templateAffinityKeywords = {
'sales-pipeline': ['sales','outreach','pipeline','prospecting'],
'research-project': ['research','analysis','investigation'],
'code-review': ['development','coding','engineering','debugging'],
'marketing-campaign': ['marketing','content','social-media','brand'],
'product-launch': ['product','roadmap','strategy','planning'],
'legal-review': ['legal','contracts','compliance','risk'],
'agency-consulting': ['consulting','strategy','analysis','research'],
'customer-support': ['support','customer-success','helpdesk','service'],
'finance-accounting': ['finance','accounting','business','budgets'],
'hr-people': ['hr','people','policy','compliance'],
'operations-center': ['operations','process','procurement','logistics'],
'data-analytics': ['data','analytics','bi','reporting'],
'recruiting-pipeline': ['recruiting','hiring','talent','hr'],
'design-studio': ['design','creative','brand','marketing'],
'blank': ['general','mixed','personal']
};
/* Header row */
var thead = document.createElement('thead');
var headerRow = document.createElement('tr');
var th0 = document.createElement('th');
th0.className = 'row-head';
th0.textContent = 'Template';
headerRow.appendChild(th0);
PERSONAS.forEach(function(p) {
var th = document.createElement('th');
th.textContent = p.icon;
th.title = p.name;
headerRow.appendChild(th);
});
thead.appendChild(headerRow);
table.appendChild(thead);
/* Body rows */
var tbody = document.createElement('tbody');
TEMPLATES.forEach(function(t) {
var row = document.createElement('tr');
var tdName = document.createElement('td');
tdName.className = 'row-head';
tdName.textContent = t.icon + ' ' + t.name;
row.appendChild(tdName);
var defaultPid = TEMPLATE_PERSONA[t.id];
var keywords = templateAffinityKeywords[t.id] || [];
PERSONAS.forEach(function(p) {
var td = document.createElement('td');
var isDefault = p.id === defaultPid;
var hasAffinity = p.workspaceAffinity.some(function(a) { return keywords.indexOf(a) !== -1; });
if (isDefault) {
var dot = el('span', 'dot default');
dot.title = 'Default persona';
td.appendChild(dot);
} else if (hasAffinity) {
var dot2 = el('span', 'dot affinity');
dot2.title = 'Affinity match';
td.appendChild(dot2);
}
row.appendChild(td);
});
tbody.appendChild(row);
});
table.appendChild(tbody);
})();
/* ================================================================
SECTION 4: Persona Anatomy
================================================================ */
var selectEl = document.getElementById('anatomy-select');
PERSONAS.forEach(function(p) {
var opt = document.createElement('option');
opt.value = p.id;
opt.textContent = p.icon + ' ' + p.name;
selectEl.appendChild(opt);
});
selectEl.addEventListener('change', function() { renderAnatomy(selectEl.value); });
function renderAnatomy(pid) {
var p = PERSONAS.find(function(x) { return x.id === pid; });
if (!p) return;
var c = document.getElementById('anatomy-content');
/* Clear existing content */
while (c.firstChild) c.removeChild(c.firstChild);
/* Header */
var hdr = el('div', 'anatomy-header');
hdr.appendChild(el('div', 'icon', p.icon));
var info = el('div', 'info');
info.appendChild(el('h3', null, p.name));
info.appendChild(el('p', null, p.tagline));
hdr.appendChild(info);
c.appendChild(hdr);
/* System Prompt */
c.appendChild(makeField('System Prompt', null, p.systemPrompt, 'value'));
/* Tools (Allowlist) */
c.appendChild(makeField('Tools (Allowlist) -- ' + p.tools.length + ' tools', p.tools, null, 'tags-allow'));
/* Disallowed Tools */
var denyList = (p.disallowedTools && p.disallowedTools.length) ? p.disallowedTools : null;
if (denyList) {
c.appendChild(makeField('Disallowed Tools (Denylist)', denyList, null, 'tags-deny'));
} else {
c.appendChild(makeField('Disallowed Tools (Denylist)', ['none'], null, 'tags'));
}
/* Read-Only */
c.appendChild(makeField('Read-Only', null,
p.isReadOnly ? 'YES -- Cannot modify files, commit, or generate documents' : 'No -- Full read/write access within tool scope',
'value'));
/* Model */
c.appendChild(makeField('Model Preference', null, p.modelPreference, 'value'));
/* Workspace Affinity */
c.appendChild(makeField('Workspace Affinity', p.workspaceAffinity || [], null, 'tags'));
/* Best For */
c.appendChild(makeField('Best For', p.bestFor, null, 'tags'));
/* Won't Do */
c.appendChild(makeField('Won\'t Do', null, p.wontDo, 'value'));
/* Failure Patterns */
c.appendChild(makeField('Failure Patterns', p.failurePatterns, null, 'tags-fail'));
}
function makeField(label, listItems, textValue, mode) {
var group = el('div', 'field-group');
group.appendChild(el('div', 'field-label', label));
if (mode === 'value') {
group.appendChild(el('div', 'field-value', textValue));
} else {
var tagList = el('div', 'tag-list');
var tagClass = 'tag';
if (mode === 'tags-allow') tagClass = 'tag allow';
else if (mode === 'tags-deny') tagClass = 'tag deny';
else if (mode === 'tags-fail') tagClass = 'tag fail';
(listItems || []).forEach(function(item) {
tagList.appendChild(el('span', tagClass, item));
});
group.appendChild(tagList);
}
return group;
}
renderAnatomy('general-purpose');
/* ================================================================
SECTION 5: Per-Window Override Examples
================================================================ */
(function renderWindowExamples() {
var grid = document.getElementById('window-examples');
var windows = [
{ title: 'Window 1 -- Literature Review', persona: 'researcher', badge: 'DEFAULT', tools: 'web_search, web_fetch, search_memory, save_memory ...' },
{ title: 'Window 2 -- Draft Paper', persona: 'writer', badge: 'OVERRIDE', tools: 'read_file, write_file, edit_file, generate_docx ...' },
{ title: 'Window 3 -- Verify Citations', persona: 'verifier', badge: 'OVERRIDE', tools: 'read_file, search_memory, web_search, bash (read-only) ...' },
{ title: 'Window 4 -- Plan Next Phase', persona: 'planner', badge: 'OVERRIDE', tools: 'read_file, search_files, create_plan, show_plan ...' }
];
windows.forEach(function(w) {
var p = PERSONAS.find(function(x) { return x.id === w.persona; });
var card = el('div', 'win-card');
card.appendChild(el('div', 'win-badge', w.badge));
var titleEl = el('div', 'win-title');
titleEl.textContent = (p ? p.icon + ' ' : '') + w.title;
card.appendChild(titleEl);
var personaText = 'Persona: ' + (p ? p.name : w.persona);
if (p && p.isReadOnly) personaText += ' (read-only)';
card.appendChild(el('div', 'win-persona', personaText));
card.appendChild(el('div', 'win-tools', 'Tools: ' + w.tools));
card.addEventListener('mouseenter', function(e) {
if (!p) return;
showTooltip(e, p.name + ' in this window',
'Tagline: ' + p.tagline +
'\nRead-only: ' + (p.isReadOnly ? 'Yes' : 'No') +
'\nTool count: ' + p.tools.length +
'\nWon\'t do: ' + p.wontDo);
});
card.addEventListener('mouseleave', hideTooltip);
grid.appendChild(card);
});
})();
</script>
</body>
</html>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,950 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>WaggleDance -- Multi-Agent Communication</title>
<style>
:root {
--honey: #e5a000;
--honey-light: #f5c842;
--honey-dim: #b37d00;
--hive-950: #08090c;
--hive-900: #0e1017;
--hive-800: #181b24;
--hive-700: #242834;
--hive-600: #3a3f50;
--hive-500: #555a6e;
--accent: #a78bfa;
--accent-dim: #7c5fd6;
--green: #34d399;
--green-dim: #10b981;
--red: #f87171;
--blue: #60a5fa;
--cyan: #22d3ee;
--orange: #fb923c;
--pink: #f472b6;
--white: #f0f0f0;
--text: #c8cad0;
--text-dim: #8a8d9a;
}
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
background: var(--hive-950);
color: var(--text);
font-family: 'Segoe UI', system-ui, -apple-system, sans-serif;
overflow-x: hidden;
}
/* --- Tooltip --- */
#tooltip {
position: fixed;
z-index: 9999;
pointer-events: none;
background: var(--hive-800);
border: 1px solid var(--honey-dim);
border-radius: 8px;
padding: 10px 14px;
font-size: 13px;
color: var(--text);
max-width: 280px;
line-height: 1.5;
opacity: 0;
transition: opacity 0.2s;
box-shadow: 0 4px 20px rgba(0,0,0,0.5);
}
#tooltip.visible { opacity: 1; }
/* --- Header --- */
header {
text-align: center;
padding: 48px 20px 24px;
position: relative;
}
header h1 {
font-size: 42px;
font-weight: 800;
background: linear-gradient(135deg, var(--honey), var(--honey-light));
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
letter-spacing: -1px;
}
header p {
color: var(--text-dim);
font-size: 16px;
margin-top: 8px;
max-width: 600px;
margin-inline: auto;
}
.badge {
display: inline-block;
background: var(--hive-700);
border: 1px solid var(--hive-600);
border-radius: 20px;
padding: 4px 14px;
font-size: 12px;
color: var(--honey);
margin-top: 12px;
letter-spacing: 0.5px;
text-transform: uppercase;
}
/* --- Navigation --- */
nav {
display: flex;
justify-content: center;
gap: 6px;
padding: 0 20px 32px;
flex-wrap: wrap;
}
nav button {
background: var(--hive-800);
border: 1px solid var(--hive-700);
border-radius: 8px;
color: var(--text-dim);
padding: 8px 16px;
font-size: 13px;
cursor: pointer;
transition: all 0.25s;
font-family: inherit;
}
nav button:hover {
border-color: var(--honey-dim);
color: var(--honey);
}
nav button.active {
background: linear-gradient(135deg, var(--honey-dim), var(--honey));
color: var(--hive-950);
border-color: var(--honey);
font-weight: 600;
}
/* --- Sections --- */
.section {
display: none;
max-width: 1100px;
margin: 0 auto;
padding: 0 20px 60px;
}
.section.active { display: block; }
.section-title {
font-size: 26px;
font-weight: 700;
color: var(--white);
margin-bottom: 6px;
}
.section-sub {
color: var(--text-dim);
font-size: 14px;
margin-bottom: 32px;
line-height: 1.6;
}
/* --- Canvas area --- */
.canvas {
position: relative;
background: var(--hive-900);
border: 1px solid var(--hive-700);
border-radius: 16px;
min-height: 440px;
overflow: hidden;
}
/* --- Shared node styles --- */
.node {
position: absolute;
border-radius: 12px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
text-align: center;
padding: 12px 10px;
font-size: 12px;
font-weight: 600;
transition: transform 0.3s, box-shadow 0.3s;
cursor: default;
}
.node:hover {
transform: scale(1.08);
box-shadow: 0 0 20px rgba(229,160,0,0.25);
}
.node .icon { font-size: 28px; margin-bottom: 4px; }
.node .label { line-height: 1.3; }
.node-user {
background: linear-gradient(135deg, var(--accent-dim), var(--accent));
color: #fff;
border: 2px solid var(--accent);
width: 100px; height: 80px;
}
.node-orch {
background: linear-gradient(135deg, var(--honey-dim), var(--honey));
color: var(--hive-950);
border: 2px solid var(--honey-light);
width: 120px; height: 80px;
}
.node-agent {
background: var(--hive-800);
border: 2px solid var(--hive-600);
color: var(--text);
width: 110px; height: 78px;
}
.node-agent.research { border-color: var(--blue); }
.node-agent.code { border-color: var(--green); }
.node-agent.analysis { border-color: var(--orange); }
.node-agent.writer { border-color: var(--pink); }
.node-agent.reviewer { border-color: var(--cyan); }
.node-result {
background: linear-gradient(135deg, var(--green-dim), var(--green));
color: var(--hive-950);
border: 2px solid var(--green);
width: 130px; height: 72px;
}
.node-memory {
background: var(--hive-800);
border: 2px solid var(--honey);
color: var(--honey-light);
width: 130px; height: 72px;
border-style: dashed;
}
.node-queue {
background: var(--hive-800);
border: 2px solid var(--accent);
color: var(--accent);
width: 120px; height: 70px;
}
/* --- SVG lines --- */
.canvas svg {
position: absolute;
top: 0; left: 0;
width: 100%; height: 100%;
pointer-events: none;
}
.flow-line {
stroke-width: 2;
fill: none;
stroke-dasharray: 8 4;
}
.flow-line.animated {
animation: dash 1.2s linear infinite;
}
@keyframes dash {
to { stroke-dashoffset: -24; }
}
/* --- Pulse ring on nodes --- */
.pulse-ring {
position: absolute;
top: -6px; left: -6px;
right: -6px; bottom: -6px;
border-radius: 16px;
border: 2px solid var(--honey);
opacity: 0;
animation: pulse-out 2.4s ease-out infinite;
pointer-events: none;
}
@keyframes pulse-out {
0% { opacity: 0.6; transform: scale(1); }
100% { opacity: 0; transform: scale(1.25); }
}
/* --- Step labels on canvas --- */
.step-label {
position: absolute;
background: var(--hive-700);
border: 1px solid var(--hive-600);
border-radius: 20px;
padding: 3px 12px;
font-size: 11px;
font-weight: 600;
color: var(--honey);
white-space: nowrap;
pointer-events: none;
}
/* --- Section 5 resource cards --- */
.resource-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: 16px;
margin-top: 20px;
}
.resource-card {
background: var(--hive-800);
border: 1px solid var(--hive-700);
border-radius: 12px;
padding: 20px;
transition: all 0.3s;
cursor: default;
}
.resource-card:hover {
border-color: var(--honey-dim);
transform: translateY(-3px);
box-shadow: 0 8px 24px rgba(0,0,0,0.3);
}
.resource-card .rc-icon { font-size: 32px; margin-bottom: 8px; }
.resource-card .rc-title {
font-weight: 700;
color: var(--white);
font-size: 15px;
margin-bottom: 4px;
}
.resource-card .rc-desc {
font-size: 12px;
color: var(--text-dim);
line-height: 1.5;
}
.resource-card .rc-tag {
display: inline-block;
margin-top: 8px;
background: var(--hive-700);
border-radius: 12px;
padding: 2px 10px;
font-size: 11px;
color: var(--honey);
}
/* --- Section 6 lifecycle --- */
.lifecycle {
display: flex;
flex-direction: column;
gap: 0;
margin-top: 20px;
}
.lc-step {
display: flex;
align-items: flex-start;
gap: 16px;
position: relative;
padding: 16px 0;
}
.lc-step:not(:last-child)::after {
content: '';
position: absolute;
left: 19px;
top: 52px;
bottom: -4px;
width: 2px;
background: var(--hive-600);
}
.lc-num {
width: 40px; height: 40px;
border-radius: 50%;
background: var(--hive-800);
border: 2px solid var(--honey);
display: flex;
align-items: center;
justify-content: center;
font-weight: 700;
font-size: 14px;
color: var(--honey);
flex-shrink: 0;
}
.lc-body { flex: 1; }
.lc-title {
font-weight: 700;
color: var(--white);
font-size: 15px;
margin-bottom: 4px;
}
.lc-detail {
font-size: 13px;
color: var(--text-dim);
line-height: 1.6;
}
.lc-code {
display: inline-block;
background: var(--hive-700);
border-radius: 4px;
padding: 1px 6px;
font-family: 'Cascadia Code', 'Fira Code', monospace;
font-size: 12px;
color: var(--green);
}
/* --- Footer --- */
footer {
text-align: center;
padding: 40px 20px;
color: var(--text-dim);
font-size: 12px;
border-top: 1px solid var(--hive-800);
}
footer span { color: var(--honey); font-weight: 600; }
/* --- Animated dot traveling along path --- */
.traveler {
position: absolute;
width: 8px; height: 8px;
border-radius: 50%;
opacity: 0;
pointer-events: none;
z-index: 10;
}
/* --- Broadcast rings --- */
@keyframes broadcast-ring {
0% { transform: scale(0.3); opacity: 0.8; }
100% { transform: scale(2.5); opacity: 0; }
}
.broadcast-ring {
position: absolute;
width: 60px; height: 60px;
border-radius: 50%;
border: 2px solid var(--honey);
pointer-events: none;
animation: broadcast-ring 2s ease-out infinite;
}
</style>
</head>
<body>
<div id="tooltip"></div>
<header>
<h1>WaggleDance</h1>
<p>Multi-agent communication protocol -- how Waggle OS agents coordinate, share knowledge, and solve problems together.</p>
<div class="badge">@waggle/waggle-dance</div>
</header>
<nav id="nav"></nav>
<!-- ==================== Section 1: Single-User Multi-Agent ==================== -->
<div class="section" id="sec-1">
<div class="section-title">Single-User Multi-Agent</div>
<div class="section-sub">One user, multiple specialist agents working in parallel. The SubagentOrchestrator resolves dependencies, injects context, and synthesizes results into a unified answer.</div>
<div class="canvas" id="canvas-1" style="height:460px;">
<svg id="svg-1"></svg>
<div class="node node-user" style="left:30px;top:190px;" data-tip-title="User" data-tip-body="Asks a complex question that requires multiple specialties to answer completely.">
<div class="icon">&#x1F464;</div>
<div class="label">User</div>
</div>
<div class="node node-orch" style="left:200px;top:185px;" data-tip-title="SubagentOrchestrator" data-tip-body="Analyzes the query, decomposes into sub-tasks, spawns specialist workers via runWorkflow(), manages dependencies.">
<div class="icon">&#x1F3AF;</div>
<div class="label">Orchestrator</div>
<div class="pulse-ring"></div>
</div>
<div class="node node-agent research" style="left:420px;top:40px;" data-tip-title="Research Agent" data-tip-body="Role preset: web_search, web_fetch, search_memory, save_memory. Gathers external information and existing knowledge.">
<div class="icon">&#x1F50D;</div>
<div class="label">Researcher</div>
</div>
<div class="node node-agent code" style="left:420px;top:185px;" data-tip-title="Coder Agent" data-tip-body="Role preset: bash, read_file, write_file, edit_file, git_status, git_diff. Writes and reviews code artifacts.">
<div class="icon">&#x1F4BB;</div>
<div class="label">Coder</div>
</div>
<div class="node node-agent analysis" style="left:420px;top:330px;" data-tip-title="Analyst Agent" data-tip-body="Role preset: bash, read_file, search_files, web_search, web_fetch, search_memory. Processes data and draws conclusions.">
<div class="icon">&#x1F4CA;</div>
<div class="label">Analyst</div>
</div>
<div class="step-label" style="left:130px;top:160px;">1. Decompose</div>
<div class="step-label" style="left:340px;top:12px;">2. Spawn</div>
<div class="step-label" style="left:570px;top:185px;">3. Execute</div>
<div class="node node-result" style="left:680px;top:185px;" data-tip-title="Synthesized Result" data-tip-body="Aggregation modes: concatenate, last, or synthesize. The orchestrator merges all worker outputs into one coherent answer.">
<div class="icon">&#x2714;</div>
<div class="label">Merged Result</div>
</div>
<div class="step-label" style="left:830px;top:160px;">4. Return</div>
<div class="node node-user" style="left:870px;top:190px;" data-tip-title="User" data-tip-body="Receives a comprehensive answer that no single agent could have produced alone.">
<div class="icon">&#x1F464;</div>
<div class="label">User</div>
</div>
</div>
</div>
<!-- ==================== Section 2: Team WaggleDance ==================== -->
<div class="section" id="sec-2">
<div class="section-title">Team WaggleDance</div>
<div class="section-sub">Multiple users share a team memory layer via TeamSync. Knowledge discovered by one agent flows to all team members automatically -- push-on-write, pull-on-activate.</div>
<div class="canvas" id="canvas-2" style="height:480px;">
<svg id="svg-2"></svg>
<div class="node node-user" style="left:40px;top:60px;" data-tip-title="User A" data-tip-body="Discovers new knowledge during a research session. Their agent writes frames to local .mind DB.">
<div class="icon">&#x1F464;</div>
<div class="label">User A</div>
</div>
<div class="node node-agent research" style="left:40px;top:190px;" data-tip-title="Agent A" data-tip-body="Executes save_memory after discovering useful information. Triggers push-on-write to team server.">
<div class="icon">&#x1F41D;</div>
<div class="label">Agent A</div>
</div>
<div class="step-label" style="left:30px;top:160px;">Discovers</div>
<div class="node node-memory" style="left:200px;top:190px;" data-tip-title="Local .mind" data-tip-body="SQLite database with FrameStore, HybridSearch, KnowledgeGraph. Each user has their own local mind.">
<div class="icon">&#x1F9E0;</div>
<div class="label">Local Mind A</div>
</div>
<div class="step-label" style="left:195px;top:158px;">Writes</div>
<div class="node node-orch" style="left:420px;top:200px;width:160px;height:90px;" data-tip-title="Team Memory Server" data-tip-body="Stores memory frames as team entities (entityType='memory_frame'). Push-on-write, pull-on-activate. Last-write-wins at frame level. Frames carry authorId and authorName attribution.">
<div class="icon">&#x1F3E0;</div>
<div class="label">Shared Team Memory</div>
<div class="pulse-ring"></div>
</div>
<div class="step-label" style="left:345px;top:168px;">Push</div>
<div class="step-label" style="left:575px;top:168px;">Pull</div>
<div class="node node-memory" style="left:660px;top:190px;" data-tip-title="Local .mind" data-tip-body="User B's local SQLite database. Pulls new frames from team server when workspace activates.">
<div class="icon">&#x1F9E0;</div>
<div class="label">Local Mind B</div>
</div>
<div class="node node-agent code" style="left:830px;top:190px;" data-tip-title="Agent B" data-tip-body="Automatically has access to knowledge that User A discovered. search_memory returns team-shared frames alongside local ones.">
<div class="icon">&#x1F41D;</div>
<div class="label">Agent B</div>
</div>
<div class="node node-user" style="left:830px;top:60px;" data-tip-title="User B" data-tip-body="Benefits from team knowledge without having to do the research. Sees attributed frames ('discovered by User A').">
<div class="icon">&#x1F464;</div>
<div class="label">User B</div>
</div>
<div class="step-label" style="left:815px;top:160px;">Recalls</div>
<div class="step-label" style="left:380px;top:330px;background:var(--hive-800);border-color:var(--honey-dim);">TeamSync: frameToEntity() -- composite key gopId+t</div>
<div class="node node-user" style="left:420px;top:400px;width:160px;" data-tip-title="User C" data-tip-body="Also connected to the same team memory. The entire team builds shared institutional knowledge over time.">
<div class="icon">&#x1F464;</div>
<div class="label">User C (also synced)</div>
</div>
</div>
</div>
<!-- ==================== Section 3: Task Dispatcher ==================== -->
<div class="section" id="sec-3">
<div class="section-title">Task Dispatcher</div>
<div class="section-sub">The WaggleDanceDispatcher routes messages by type/subtype combination. task_delegation spawns workers, knowledge_check searches memory, skill_request resolves capabilities.</div>
<div class="canvas" id="canvas-3" style="height:460px;">
<svg id="svg-3"></svg>
<div class="node node-queue" style="left:30px;top:50px;" data-tip-title="task_delegation" data-tip-body="Routes to spawnWorker(task, role, context). Creates a new sub-agent with the specified role and tool preset.">
<div class="icon">&#x1F4CB;</div>
<div class="label">Task Delegation</div>
</div>
<div class="node node-queue" style="left:30px;top:170px;border-color:var(--blue);" data-tip-title="knowledge_check" data-tip-body="Routes to searchMemory(query). Searches local and team memory for relevant knowledge frames.">
<div class="icon">&#x2753;</div>
<div class="label" style="color:var(--blue);">Knowledge Check</div>
</div>
<div class="node node-queue" style="left:30px;top:290px;border-color:var(--green);" data-tip-title="skill_request" data-tip-body="Routes to resolveCapability(query). Searches the capability router for matching skills and tools.">
<div class="icon">&#x1F527;</div>
<div class="label" style="color:var(--green);">Skill Request</div>
</div>
<div class="node node-orch" style="left:260px;top:165px;width:160px;height:110px;" data-tip-title="WaggleDanceDispatcher" data-tip-body="Validates message type-subtype combinations against the protocol matrix. Routes to: handleTaskDelegation, handleKnowledgeCheck, handleSkillRequest, handleSkillShare.">
<div class="icon">&#x1F3AF;</div>
<div class="label">Dispatcher</div>
<div class="pulse-ring"></div>
</div>
<div class="node node-agent research" style="left:540px;top:30px;" data-tip-title="Capability Match" data-tip-body="resolveCapability() checks which agents have the skills needed. Returns source, name, description, availability.">
<div class="icon">&#x1F50E;</div>
<div class="label">Cap. Match</div>
</div>
<div class="node node-agent code" style="left:540px;top:160px;" data-tip-title="Worker Spawn" data-tip-body="spawnWorker() picks the right role preset from ROLE_TOOL_PRESETS (researcher, writer, coder, analyst, reviewer, planner, synthesizer, summarizer).">
<div class="icon">&#x2696;</div>
<div class="label">Worker Spawn</div>
</div>
<div class="node node-agent analysis" style="left:540px;top:290px;" data-tip-title="Memory Search" data-tip-body="searchMemory() queries HybridSearch (FTS5 + sqlite-vec, fused via RRF). Returns ranked knowledge frames.">
<div class="icon">&#x1F9E0;</div>
<div class="label">Memory Search</div>
</div>
<div class="node node-agent writer" style="left:750px;top:30px;" data-tip-title="Available Agents" data-tip-body="Filtered list of agents with matching capabilities. Each reports availability status.">
<div class="icon">&#x1F41D;</div>
<div class="label">Agent Pool</div>
</div>
<div class="node node-agent reviewer" style="left:750px;top:160px;" data-tip-title="Spawned Worker" data-tip-body="New sub-agent with role-specific tool preset, parent context injected, and max turn budget.">
<div class="icon">&#x1F41D;</div>
<div class="label">New Worker</div>
</div>
<div class="node node-result" style="left:750px;top:290px;" data-tip-title="DispatchResult" data-tip-body="{ handled: boolean, response?: string, error?: string }. Every dispatch returns a structured result.">
<div class="icon">&#x1F4E6;</div>
<div class="label">Results</div>
</div>
<div class="step-label" style="left:200px;top:400px;background:var(--hive-800);border-color:var(--honey-dim);font-size:10px;">
Protocol: request=[knowledge_check, task_delegation, skill_request] | response=[knowledge_match, task_claim] | broadcast=[discovery, routed_share, skill_share]
</div>
</div>
</div>
<!-- ==================== Section 4: HiveQuery Broadcast ==================== -->
<div class="section" id="sec-4">
<div class="section-title">HiveQuery Broadcast</div>
<div class="section-sub">One agent broadcasts a question to the entire hive. Every agent searches its knowledge, and results are collected, ranked by relevance, and the best answer surfaces. Like a hive mind where every bee contributes.</div>
<div class="canvas" id="canvas-4" style="height:500px;">
<svg id="svg-4"></svg>
<div class="node node-orch" style="left:60px;top:200px;width:130px;" data-tip-title="Broadcast Source" data-tip-body="Sends a HiveQuery with topic and optional scope. The query propagates to all agents in the hive simultaneously.">
<div class="icon">&#x1F4E2;</div>
<div class="label">Broadcast Query</div>
<div class="pulse-ring"></div>
</div>
<div class="step-label" style="left:50px;top:170px;">HiveQuery { topic, scope }</div>
<div class="broadcast-ring" style="left:95px;top:220px;animation-delay:0s;"></div>
<div class="broadcast-ring" style="left:95px;top:220px;animation-delay:0.6s;"></div>
<div class="broadcast-ring" style="left:95px;top:220px;animation-delay:1.2s;"></div>
<div class="node node-agent research" style="left:340px;top:20px;" data-tip-title="Researcher" data-tip-body="Searches web sources and memory for matching knowledge. Returns entities, related tasks, and messages.">
<div class="icon">&#x1F41D;</div>
<div class="label">Researcher</div>
</div>
<div class="node node-agent code" style="left:460px;top:100px;" data-tip-title="Coder" data-tip-body="Checks code-related knowledge, file references, git history. Returns technical context if relevant.">
<div class="icon">&#x1F41D;</div>
<div class="label">Coder</div>
</div>
<div class="node node-agent analysis" style="left:480px;top:240px;" data-tip-title="Analyst" data-tip-body="Processes analytical data, metrics, past findings. Returns statistical or business context.">
<div class="icon">&#x1F41D;</div>
<div class="label">Analyst</div>
</div>
<div class="node node-agent writer" style="left:440px;top:370px;" data-tip-title="Writer" data-tip-body="Checks documents, reports, written content. Returns relevant prose and documentation.">
<div class="icon">&#x1F41D;</div>
<div class="label">Writer</div>
</div>
<div class="node node-agent reviewer" style="left:300px;top:400px;" data-tip-title="Reviewer" data-tip-body="Checks review logs, code quality findings, architectural notes. Returns QA-relevant knowledge.">
<div class="icon">&#x1F41D;</div>
<div class="label">Reviewer</div>
</div>
<div class="node node-orch" style="left:700px;top:140px;width:130px;height:90px;" data-tip-title="Collect and Rank" data-tip-body="HiveQueryResult: entities (name, type, properties), relatedTasks (id, title, status, createdBy), relatedMessages (type, subtype, content). Results ranked by relevance.">
<div class="icon">&#x1F3C6;</div>
<div class="label">Collect + Rank</div>
</div>
<div class="node node-result" style="left:700px;top:290px;" data-tip-title="Best Answer" data-tip-body="The highest-ranked response surfaces as the definitive answer. Lower-ranked results available as supporting context.">
<div class="icon">&#x2B50;</div>
<div class="label">Best Answer</div>
</div>
<div class="step-label" style="left:730px;top:260px;">Surfaces</div>
</div>
</div>
<!-- ==================== Section 5: Shared Resources ==================== -->
<div class="section" id="sec-5">
<div class="section-title">Shared Resources</div>
<div class="section-sub">What flows between agents in the WaggleDance protocol. Every shared resource type maps to a real mechanism in the codebase.</div>
<div class="resource-grid">
<div class="resource-card" data-tip-title="Memory Frames" data-tip-body="FrameStore (I/P/B frames) synced via TeamSync. Push-on-write, pull-on-activate. Composite key: gopId + t. Author attribution preserved. HybridSearch (FTS5 + vec0) across local + team frames.">
<div class="rc-icon">&#x1F9E0;</div>
<div class="rc-title">Memory Frames</div>
<div class="rc-desc">Shared via team-sync.ts. Push-on-write, pull-on-activate. Frames carry author attribution (userId + displayName).</div>
<div class="rc-tag">team-sync.ts</div>
</div>
<div class="resource-card" data-tip-title="Skills" data-tip-body="skill_share message subtype in the WaggleDance protocol. handleSkillShare() returns { action: 'install_shared_skill', skillName, skillContent, sharedBy }. The server persists the skill for the receiving workspace.">
<div class="rc-icon">&#x1F3AF;</div>
<div class="rc-title">Skills</div>
<div class="rc-desc">Shared via skill_share broadcast message. Receiving agents install shared skills into their workspace skill library.</div>
<div class="rc-tag">dispatcher.ts</div>
</div>
<div class="resource-card" data-tip-title="Knowledge Graph" data-tip-body="Entity-relation graph with bitemporal validity. Cross-workspace via global KG queries (MultiMindCache). Entities, relationships, and ontology concepts propagate.">
<div class="rc-icon">&#x1F578;</div>
<div class="rc-title">Knowledge Graph</div>
<div class="rc-desc">Entity-relation graph with bitemporal validity. Global KG queries span all workspaces via MultiMindCache.</div>
<div class="rc-tag">knowledge.ts</div>
</div>
<div class="resource-card" data-tip-title="Evolution Learnings" data-tip-body="Self-improvement results from the evolution pipeline. Persona overrides and behavioral-spec overrides propagate to improve all agents. Accept/reject at run level.">
<div class="rc-icon">&#x1F9EC;</div>
<div class="rc-title">Learnings</div>
<div class="rc-desc">Evolution improvements propagate: persona overrides, behavioral-spec patches. Accepted runs improve all agents globally.</div>
<div class="rc-tag">evolution-deploy.ts</div>
</div>
<div class="resource-card" data-tip-title="Tool Pool" data-tip-body="ROLE_TOOL_PRESETS define per-role tool access: researcher, writer, coder, analyst, reviewer, planner, synthesizer, summarizer. filterToolsForContext() enforces allowlist/denylist per persona.">
<div class="rc-icon">&#x1F6E0;</div>
<div class="rc-title">Tool Pool</div>
<div class="rc-desc">Role-based tool presets shared across agents. 8 roles with curated tool sets. filterToolsForContext() enforces access.</div>
<div class="rc-tag">subagent-orchestrator.ts</div>
</div>
</div>
</div>
<!-- ==================== Section 6: Communication Protocol ==================== -->
<div class="section" id="sec-6">
<div class="section-title">Communication Protocol</div>
<div class="section-sub">The lifecycle of a sub-agent from spawn request to trace recording. Each step maps directly to code in the agent package.</div>
<div class="lifecycle">
<div class="lc-step" data-tip-title="Spawn Request" data-tip-body="WorkflowStep defines: name, role, task, tools, dependsOn, contextFrom, maxTurns. The orchestrator validates dependencies before spawning.">
<div class="lc-num">1</div>
<div class="lc-body">
<div class="lc-title">Spawn Request</div>
<div class="lc-detail">Orchestrator receives a <span class="lc-code">WorkflowStep</span> with role, task, tools, and dependency list. Validates that all <span class="lc-code">dependsOn</span> steps have completed before proceeding.</div>
</div>
</div>
<div class="lc-step" data-tip-title="Agent Creation" data-tip-body="makeWorkerId() generates unique ID. WorkerState created with status='pending'. UI receives 'worker:status' event to show the agent in the workflow plan.">
<div class="lc-num">2</div>
<div class="lc-body">
<div class="lc-title">Agent Creation</div>
<div class="lc-detail">Worker ID generated via <span class="lc-code">makeWorkerId()</span>. WorkerState initialized as <span class="lc-code">pending</span>. The <span class="lc-code">worker:status</span> event fires so UI can show the planned workflow.</div>
</div>
</div>
<div class="lc-step" data-tip-title="Context Injection" data-tip-body="setParentContext() injects: userName, userRole, workspaceName, workspaceDomain, plus behavioral rules (search memory first, be grounded, save findings). contextFrom steps inject prior results.">
<div class="lc-num">3</div>
<div class="lc-body">
<div class="lc-title">Context Injection</div>
<div class="lc-detail"><span class="lc-code">setParentContext()</span> injects user identity, workspace info, and behavioral rules. Results from <span class="lc-code">contextFrom</span> steps are prepended as prior context. Role tool presets resolved from <span class="lc-code">ROLE_TOOL_PRESETS</span>.</div>
</div>
</div>
<div class="lc-step" data-tip-title="Execution" data-tip-body="Worker status transitions: pending -> running -> done/failed. The agent loop runs with injected context, constrained tools, and maxTurns budget. toolsUsed and token usage tracked.">
<div class="lc-num">4</div>
<div class="lc-body">
<div class="lc-title">Execution</div>
<div class="lc-detail">Status transitions: <span class="lc-code">pending -> running -> done|failed</span>. Agent loop runs with constrained tools and turn budget. Token usage tracked in <span class="lc-code">WorkerState.usage</span>.</div>
</div>
</div>
<div class="lc-step" data-tip-title="Result Return" data-tip-body="Worker result stored in WorkerState.result. contextResults map populated for downstream steps. Aggregation runs after all steps complete: concatenate, last, or synthesize.">
<div class="lc-num">5</div>
<div class="lc-body">
<div class="lc-title">Result Return</div>
<div class="lc-detail">Worker result stored in <span class="lc-code">WorkerState.result</span>. Context map updated for downstream steps. Final aggregation mode: <span class="lc-code">concatenate | last | synthesize</span>.</div>
</div>
</div>
<div class="lc-step" data-tip-title="Trace Recording" data-tip-body="TraceRecorder captures the full execution trace: input tokens, output tokens, tools used, latency, model, result quality. Traces feed into the evolution pipeline for self-improvement.">
<div class="lc-num">6</div>
<div class="lc-body">
<div class="lc-title">Trace Recording</div>
<div class="lc-detail"><span class="lc-code">TraceRecorder</span> captures full execution trace: tokens, tools, latency, model, quality. Traces feed into the evolution pipeline -- enabling closed-loop self-improvement.</div>
</div>
</div>
</div>
</div>
<footer>
<span>Waggle OS</span> -- WaggleDance Multi-Agent Protocol | @waggle/waggle-dance | Egzakta Group
</footer>
<script>
(function() {
/* ========== Tab Navigation ========== */
var tabs = [
{ id: 'sec-1', label: 'Multi-Agent' },
{ id: 'sec-2', label: 'Team Dance' },
{ id: 'sec-3', label: 'Dispatcher' },
{ id: 'sec-4', label: 'HiveQuery' },
{ id: 'sec-5', label: 'Shared Resources' },
{ id: 'sec-6', label: 'Protocol' }
];
var navEl = document.getElementById('nav');
tabs.forEach(function(t, i) {
var btn = document.createElement('button');
btn.textContent = t.label;
if (i === 0) btn.classList.add('active');
btn.addEventListener('click', function() {
document.querySelectorAll('.section').forEach(function(s) { s.classList.remove('active'); });
document.querySelectorAll('nav button').forEach(function(b) { b.classList.remove('active'); });
document.getElementById(t.id).classList.add('active');
btn.classList.add('active');
drawMap[t.id] && drawMap[t.id]();
});
navEl.appendChild(btn);
});
document.getElementById('sec-1').classList.add('active');
/* ========== Tooltip (safe DOM methods) ========== */
var tip = document.getElementById('tooltip');
function showTip(el) {
var title = el.getAttribute('data-tip-title');
var body = el.getAttribute('data-tip-body');
tip.textContent = '';
if (title) {
var h = document.createElement('div');
h.style.color = 'var(--honey)';
h.style.fontWeight = '700';
h.style.fontSize = '13px';
h.style.marginBottom = '4px';
h.textContent = title;
tip.appendChild(h);
}
if (body) {
var p = document.createElement('div');
p.textContent = body;
tip.appendChild(p);
}
tip.classList.add('visible');
}
document.addEventListener('mouseover', function(e) {
var el = e.target.closest('[data-tip-title]');
if (!el) { tip.classList.remove('visible'); return; }
showTip(el);
});
document.addEventListener('mousemove', function(e) {
if (!tip.classList.contains('visible')) return;
var x = e.clientX + 14;
var y = e.clientY + 14;
if (x + 290 > window.innerWidth) x = e.clientX - 294;
if (y + 120 > window.innerHeight) y = e.clientY - 130;
tip.style.left = x + 'px';
tip.style.top = y + 'px';
});
document.addEventListener('mouseout', function(e) {
var el = e.target.closest('[data-tip-title]');
if (el && !el.contains(e.relatedTarget)) tip.classList.remove('visible');
});
/* ========== SVG Helpers ========== */
var NS = 'http://www.w3.org/2000/svg';
function svgLine(svg, x1, y1, x2, y2, color, animated) {
var line = document.createElementNS(NS, 'line');
line.setAttribute('x1', x1);
line.setAttribute('y1', y1);
line.setAttribute('x2', x2);
line.setAttribute('y2', y2);
line.setAttribute('stroke', color || 'var(--honey-dim)');
line.classList.add('flow-line');
if (animated) line.classList.add('animated');
svg.appendChild(line);
}
function svgArrow(svg, x, y, angle, color) {
var g = document.createElementNS(NS, 'g');
g.setAttribute('transform', 'translate(' + x + ',' + y + ') rotate(' + angle + ')');
var poly = document.createElementNS(NS, 'polygon');
poly.setAttribute('points', '0,-5 10,0 0,5');
poly.setAttribute('fill', color || 'var(--honey-dim)');
g.appendChild(poly);
svg.appendChild(g);
}
/* ========== Animated traveling dots ========== */
function clearTravelers(container) {
container.querySelectorAll('.traveler').forEach(function(t) { t.remove(); });
}
function addTraveler(container, x1, y1, x2, y2, color, duration, delay) {
var dot = document.createElement('div');
dot.className = 'traveler';
dot.style.background = color || 'var(--honey)';
dot.style.boxShadow = '0 0 8px ' + (color || 'var(--honey)');
container.appendChild(dot);
var startTime = performance.now() + (delay || 0);
var cycleDuration = duration + 1200;
function step(now) {
if (now < startTime) { requestAnimationFrame(step); return; }
var elapsed = (now - startTime) % cycleDuration;
if (elapsed > duration) {
dot.style.opacity = '0';
} else {
var t = elapsed / duration;
var x = x1 + (x2 - x1) * t;
var y = y1 + (y2 - y1) * t;
dot.style.left = (x - 4) + 'px';
dot.style.top = (y - 4) + 'px';
dot.style.opacity = (t < 0.1 ? t / 0.1 : (t > 0.85 ? (1 - t) / 0.15 : 1)).toString();
}
requestAnimationFrame(step);
}
requestAnimationFrame(step);
}
/* ========== Section Drawers ========== */
function drawSection1() {
var svg = document.getElementById('svg-1');
while (svg.firstChild) svg.removeChild(svg.firstChild);
var c = document.getElementById('canvas-1');
clearTravelers(c);
// User -> Orchestrator
svgLine(svg, 130, 230, 200, 225, 'var(--accent)', true);
svgArrow(svg, 195, 225, 0, 'var(--accent)');
// Orchestrator -> agents
svgLine(svg, 320, 210, 420, 80, 'var(--blue)', true);
svgArrow(svg, 415, 83, -52, 'var(--blue)');
svgLine(svg, 320, 225, 420, 225, 'var(--green)', true);
svgArrow(svg, 415, 225, 0, 'var(--green)');
svgLine(svg, 320, 240, 420, 365, 'var(--orange)', true);
svgArrow(svg, 415, 362, 52, 'var(--orange)');
// Agents -> Result
svgLine(svg, 530, 80, 680, 210, 'var(--blue)', true);
svgArrow(svg, 676, 208, 40, 'var(--blue)');
svgLine(svg, 530, 225, 680, 221, 'var(--green)', true);
svgArrow(svg, 675, 221, 0, 'var(--green)');
svgLine(svg, 530, 370, 680, 236, 'var(--orange)', true);
svgArrow(svg, 676, 237, -40, 'var(--orange)');
// Result -> User
svgLine(svg, 810, 221, 870, 225, 'var(--green)', true);
svgArrow(svg, 866, 225, 2, 'var(--green)');
// Traveling dots
addTraveler(c, 130, 230, 200, 225, 'var(--accent)', 800, 0);
addTraveler(c, 320, 210, 420, 80, 'var(--blue)', 900, 400);
addTraveler(c, 320, 225, 420, 225, 'var(--green)', 900, 500);
addTraveler(c, 320, 240, 420, 365, 'var(--orange)', 900, 600);
addTraveler(c, 530, 80, 680, 210, 'var(--blue)', 800, 1600);
addTraveler(c, 530, 225, 680, 221, 'var(--green)', 800, 1800);
addTraveler(c, 530, 370, 680, 236, 'var(--orange)', 800, 2000);
addTraveler(c, 810, 221, 870, 225, 'var(--green)', 600, 3000);
}
function drawSection2() {
var svg = document.getElementById('svg-2');
while (svg.firstChild) svg.removeChild(svg.firstChild);
var c = document.getElementById('canvas-2');
clearTravelers(c);
svgLine(svg, 90, 140, 90, 190, 'var(--accent)', true);
svgArrow(svg, 90, 185, 90, 'var(--accent)');
svgLine(svg, 150, 230, 200, 226, 'var(--blue)', true);
svgArrow(svg, 195, 226, 0, 'var(--blue)');
svgLine(svg, 330, 226, 420, 240, 'var(--honey)', true);
svgArrow(svg, 415, 239, 5, 'var(--honey)');
svgLine(svg, 580, 240, 660, 226, 'var(--honey)', true);
svgArrow(svg, 655, 226, -5, 'var(--honey)');
svgLine(svg, 790, 226, 830, 230, 'var(--blue)', true);
svgArrow(svg, 825, 229, 4, 'var(--blue)');
svgLine(svg, 880, 190, 880, 140, 'var(--accent)', true);
svgArrow(svg, 880, 145, -90, 'var(--accent)');
svgLine(svg, 500, 290, 500, 400, 'var(--honey-dim)', true);
svgArrow(svg, 500, 395, 90, 'var(--honey-dim)');
addTraveler(c, 90, 140, 90, 190, 'var(--accent)', 600, 0);
addTraveler(c, 150, 230, 200, 226, 'var(--blue)', 500, 800);
addTraveler(c, 330, 226, 420, 240, 'var(--honey)', 700, 1500);
addTraveler(c, 580, 240, 660, 226, 'var(--honey)', 700, 2500);
addTraveler(c, 790, 226, 830, 230, 'var(--blue)', 400, 3400);
addTraveler(c, 880, 190, 880, 140, 'var(--accent)', 500, 4000);
}
function drawSection3() {
var svg = document.getElementById('svg-3');
while (svg.firstChild) svg.removeChild(svg.firstChild);
var c = document.getElementById('canvas-3');
clearTravelers(c);
svgLine(svg, 150, 85, 260, 200, 'var(--accent)', true);
svgArrow(svg, 256, 197, 47, 'var(--accent)');
svgLine(svg, 150, 205, 260, 220, 'var(--blue)', true);
svgArrow(svg, 256, 219, 5, 'var(--blue)');
svgLine(svg, 150, 325, 260, 250, 'var(--green)', true);
svgArrow(svg, 256, 252, -30, 'var(--green)');
svgLine(svg, 420, 200, 540, 70, 'var(--accent)', true);
svgArrow(svg, 536, 73, -47, 'var(--accent)');
svgLine(svg, 420, 220, 540, 200, 'var(--blue)', true);
svgArrow(svg, 536, 200, -6, 'var(--blue)');
svgLine(svg, 420, 250, 540, 325, 'var(--green)', true);
svgArrow(svg, 536, 323, 35, 'var(--green)');
svgLine(svg, 650, 70, 750, 65, 'var(--accent)', true);
svgArrow(svg, 746, 65, -2, 'var(--accent)');
svgLine(svg, 650, 200, 750, 195, 'var(--blue)', true);
svgArrow(svg, 746, 195, -2, 'var(--blue)');
svgLine(svg, 650, 325, 750, 325, 'var(--green)', true);
svgArrow(svg, 746, 325, 0, 'var(--green)');
addTraveler(c, 150, 85, 260, 200, 'var(--accent)', 700, 0);
addTraveler(c, 150, 205, 260, 220, 'var(--blue)', 700, 300);
addTraveler(c, 150, 325, 260, 250, 'var(--green)', 700, 600);
addTraveler(c, 420, 200, 540, 70, 'var(--accent)', 600, 1200);
addTraveler(c, 420, 220, 540, 200, 'var(--blue)', 600, 1500);
addTraveler(c, 420, 250, 540, 325, 'var(--green)', 600, 1800);
addTraveler(c, 650, 70, 750, 65, 'var(--accent)', 400, 2200);
addTraveler(c, 650, 200, 750, 195, 'var(--blue)', 400, 2400);
addTraveler(c, 650, 325, 750, 325, 'var(--green)', 400, 2600);
}
function drawSection4() {
var svg = document.getElementById('svg-4');
while (svg.firstChild) svg.removeChild(svg.firstChild);
var c = document.getElementById('canvas-4');
clearTravelers(c);
var agents = [
{ x: 395, y: 60 },
{ x: 515, y: 140 },
{ x: 535, y: 280 },
{ x: 495, y: 410 },
{ x: 355, y: 440 }
];
var colors = ['var(--blue)', 'var(--green)', 'var(--orange)', 'var(--pink)', 'var(--cyan)'];
agents.forEach(function(a, i) {
svgLine(svg, 190, 240, a.x, a.y, colors[i], true);
addTraveler(c, 190, 240, a.x, a.y, colors[i], 1000, i * 200);
});
agents.forEach(function(a, i) {
svgLine(svg, a.x + 40, a.y, 700, 185, colors[i], true);
addTraveler(c, a.x + 40, a.y, 700, 185, colors[i], 900, 1500 + i * 200);
});
svgLine(svg, 765, 230, 765, 290, 'var(--green)', true);
svgArrow(svg, 765, 286, 90, 'var(--green)');
addTraveler(c, 765, 230, 765, 290, 'var(--green)', 500, 3000);
}
var drawMap = {
'sec-1': drawSection1,
'sec-2': drawSection2,
'sec-3': drawSection3,
'sec-4': drawSection4
};
// Initial draw
drawSection1();
})();
</script>
</body>
</html>