Skip to content

Instantly share code, notes, and snippets.

@mkuchak
Created March 11, 2026 22:48
Show Gist options
  • Select an option

  • Save mkuchak/fa30100485e27b967ed5d06bf09a31ad to your computer and use it in GitHub Desktop.

Select an option

Save mkuchak/fa30100485e27b967ed5d06bf09a31ad to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Agent Action Execution Layer — Architecture Plan</title>
<!-- Fonts -->
<link rel="stylesheet" href="https://api.fontshare.com/v2/css?f[]=clash-display@400,500,600,700&f[]=satoshi@400,500,700&display=swap">
<style>
/* ===========================================
CSS CUSTOM PROPERTIES (THEME)
Dark tech aesthetic with cyan accent
=========================================== */
:root {
/* Colors */
--bg-primary: #080c14;
--bg-secondary: #0e1420;
--bg-card: #111827;
--bg-card-hover: #1a2236;
--border-subtle: rgba(0, 230, 200, 0.08);
--border-accent: rgba(0, 230, 200, 0.2);
--text-primary: #f0f4f8;
--text-secondary: #8899aa;
--text-muted: #556677;
--accent: #00e6c8;
--accent-dim: rgba(0, 230, 200, 0.15);
--accent-glow: rgba(0, 230, 200, 0.25);
--red: #ff5c6e;
--red-dim: rgba(255, 92, 110, 0.12);
--amber: #ffb347;
--amber-dim: rgba(255, 179, 71, 0.12);
--green: #4ade80;
--green-dim: rgba(74, 222, 128, 0.12);
--blue: #60a5fa;
--blue-dim: rgba(96, 165, 250, 0.12);
--purple: #a78bfa;
--purple-dim: rgba(167, 139, 250, 0.12);
/* Typography */
--font-display: 'Clash Display', sans-serif;
--font-body: 'Satoshi', sans-serif;
--title-size: clamp(2rem, 5.5vw, 4.5rem);
--h2-size: clamp(1.4rem, 3.5vw, 2.8rem);
--h3-size: clamp(1rem, 2vw, 1.5rem);
--body-size: clamp(0.75rem, 1.3vw, 1.05rem);
--small-size: clamp(0.65rem, 1vw, 0.85rem);
--code-size: clamp(0.65rem, 0.9vw, 0.82rem);
/* Spacing */
--slide-padding: clamp(1.5rem, 5vw, 5rem);
--content-gap: clamp(0.75rem, 2vw, 2rem);
--element-gap: clamp(0.3rem, 0.8vw, 0.75rem);
/* Animation */
--ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
--ease-out-quart: cubic-bezier(0.25, 1, 0.5, 1);
--duration-normal: 0.7s;
--duration-fast: 0.4s;
}
/* ===========================================
BASE STYLES
=========================================== */
* { margin: 0; padding: 0; box-sizing: border-box; }
html {
scroll-behavior: smooth;
scroll-snap-type: y mandatory;
height: 100%;
overflow-x: hidden;
}
body {
font-family: var(--font-body);
background: var(--bg-primary);
color: var(--text-primary);
overflow-x: hidden;
height: 100%;
-webkit-font-smoothing: antialiased;
}
/* ===========================================
SLIDE CONTAINER
Each slide = exactly one viewport height
=========================================== */
.slide {
width: 100vw;
height: 100vh;
height: 100dvh;
padding: var(--slide-padding);
scroll-snap-align: start;
display: flex;
flex-direction: column;
justify-content: center;
position: relative;
overflow: hidden;
}
.slide-content {
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
max-height: 100%;
overflow: hidden;
max-width: 1300px;
margin: 0 auto;
width: 100%;
}
/* ===========================================
BACKGROUND EFFECTS
=========================================== */
.slide::before {
content: '';
position: absolute;
inset: 0;
background:
radial-gradient(ellipse 60% 50% at 80% 20%, rgba(0, 230, 200, 0.03) 0%, transparent 70%),
radial-gradient(ellipse 40% 60% at 10% 80%, rgba(96, 165, 250, 0.02) 0%, transparent 70%);
pointer-events: none;
}
/* Grid pattern */
.grid-bg::after {
content: '';
position: absolute;
inset: 0;
background-image:
linear-gradient(rgba(0, 230, 200, 0.03) 1px, transparent 1px),
linear-gradient(90deg, rgba(0, 230, 200, 0.03) 1px, transparent 1px);
background-size: 60px 60px;
pointer-events: none;
mask-image: radial-gradient(ellipse 70% 70% at 50% 50%, black 30%, transparent 80%);
-webkit-mask-image: radial-gradient(ellipse 70% 70% at 50% 50%, black 30%, transparent 80%);
}
/* ===========================================
TYPOGRAPHY
=========================================== */
h1 {
font-family: var(--font-display);
font-size: var(--title-size);
font-weight: 700;
line-height: 1.05;
letter-spacing: -0.02em;
}
h2 {
font-family: var(--font-display);
font-size: var(--h2-size);
font-weight: 600;
line-height: 1.15;
letter-spacing: -0.015em;
margin-bottom: var(--content-gap);
}
h3 {
font-family: var(--font-display);
font-size: var(--h3-size);
font-weight: 500;
line-height: 1.3;
color: var(--accent);
}
p, li {
font-size: var(--body-size);
line-height: 1.55;
color: var(--text-secondary);
}
.accent { color: var(--accent); }
.red { color: var(--red); }
.amber { color: var(--amber); }
.green { color: var(--green); }
.blue { color: var(--blue); }
.muted { color: var(--text-muted); }
.white { color: var(--text-primary); }
strong { color: var(--text-primary); font-weight: 600; }
/* ===========================================
LABEL / TAG
=========================================== */
.label {
display: inline-block;
font-family: var(--font-body);
font-size: var(--small-size);
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.12em;
padding: 0.3em 0.9em;
border-radius: 999px;
background: var(--accent-dim);
color: var(--accent);
margin-bottom: var(--content-gap);
}
.label.red-label {
background: var(--red-dim);
color: var(--red);
}
.label.amber-label {
background: var(--amber-dim);
color: var(--amber);
}
.label.green-label {
background: var(--green-dim);
color: var(--green);
}
.label.blue-label {
background: var(--blue-dim);
color: var(--blue);
}
.label.purple-label {
background: var(--purple-dim);
color: var(--purple);
}
/* ===========================================
CARDS & CONTAINERS
=========================================== */
.card {
background: var(--bg-card);
border: 1px solid var(--border-subtle);
border-radius: clamp(8px, 1vw, 14px);
padding: clamp(0.8rem, 1.5vw, 1.5rem);
transition: border-color 0.3s ease, background 0.3s ease;
}
.card:hover {
border-color: var(--border-accent);
background: var(--bg-card-hover);
}
.card h3 {
margin-bottom: var(--element-gap);
}
/* ===========================================
GRID LAYOUTS
=========================================== */
.grid-2 {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: clamp(0.6rem, 1.5vw, 1.2rem);
}
.grid-3 {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: clamp(0.6rem, 1.5vw, 1.2rem);
}
.grid-4 {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: clamp(0.5rem, 1vw, 1rem);
}
@media (max-width: 900px) {
.grid-3 { grid-template-columns: repeat(2, 1fr); }
.grid-4 { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 600px) {
.grid-2 { grid-template-columns: 1fr; }
.grid-3 { grid-template-columns: 1fr; }
.grid-4 { grid-template-columns: 1fr; }
}
/* ===========================================
CODE BLOCKS
=========================================== */
.code-block {
background: #0a0f1a;
border: 1px solid var(--border-subtle);
border-radius: clamp(6px, 0.8vw, 10px);
padding: clamp(0.6rem, 1.2vw, 1.2rem);
font-family: 'SF Mono', 'Fira Code', 'Cascadia Code', monospace;
font-size: var(--code-size);
line-height: 1.6;
color: var(--text-secondary);
overflow: hidden;
white-space: pre;
}
.code-block .keyword { color: var(--purple); }
.code-block .string { color: var(--green); }
.code-block .comment { color: var(--text-muted); font-style: italic; }
.code-block .fn { color: var(--blue); }
.code-block .accent { color: var(--accent); }
.code-block .type { color: var(--amber); }
code {
font-family: 'SF Mono', 'Fira Code', monospace;
font-size: 0.9em;
background: var(--accent-dim);
color: var(--accent);
padding: 0.15em 0.45em;
border-radius: 4px;
}
/* ===========================================
FLOW DIAGRAM
=========================================== */
.flow {
display: flex;
align-items: center;
gap: clamp(0.3rem, 0.8vw, 0.8rem);
flex-wrap: wrap;
}
.flow-step {
background: var(--bg-card);
border: 1px solid var(--border-subtle);
border-radius: 8px;
padding: clamp(0.4rem, 0.8vw, 0.7rem) clamp(0.6rem, 1vw, 1rem);
font-size: var(--small-size);
font-weight: 500;
color: var(--text-primary);
white-space: nowrap;
}
.flow-step.active {
border-color: var(--accent);
background: var(--accent-dim);
color: var(--accent);
}
.flow-arrow {
color: var(--text-muted);
font-size: var(--small-size);
}
/* ===========================================
TABLE
=========================================== */
.table-wrap {
overflow: hidden;
border-radius: clamp(6px, 0.8vw, 10px);
border: 1px solid var(--border-subtle);
}
table {
width: 100%;
border-collapse: collapse;
font-size: var(--small-size);
}
th {
background: var(--bg-card);
color: var(--accent);
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.06em;
padding: clamp(0.4rem, 0.8vw, 0.7rem) clamp(0.5rem, 1vw, 1rem);
text-align: left;
border-bottom: 1px solid var(--border-accent);
font-size: var(--small-size);
}
td {
padding: clamp(0.35rem, 0.7vw, 0.6rem) clamp(0.5rem, 1vw, 1rem);
border-bottom: 1px solid var(--border-subtle);
color: var(--text-secondary);
vertical-align: top;
}
tr:last-child td { border-bottom: none; }
tr:hover td { background: rgba(0, 230, 200, 0.02); }
/* ===========================================
STATUS BADGES
=========================================== */
.badge {
display: inline-block;
font-size: clamp(0.55rem, 0.75vw, 0.72rem);
font-weight: 600;
padding: 0.2em 0.6em;
border-radius: 4px;
text-transform: uppercase;
letter-spacing: 0.04em;
}
.badge-red { background: var(--red-dim); color: var(--red); }
.badge-green { background: var(--green-dim); color: var(--green); }
.badge-amber { background: var(--amber-dim); color: var(--amber); }
.badge-blue { background: var(--blue-dim); color: var(--blue); }
.badge-accent { background: var(--accent-dim); color: var(--accent); }
/* ===========================================
BULLET LIST
=========================================== */
.bullet-list {
list-style: none;
display: flex;
flex-direction: column;
gap: var(--element-gap);
}
.bullet-list li {
padding-left: 1.4em;
position: relative;
}
.bullet-list li::before {
content: '';
position: absolute;
left: 0;
top: 0.55em;
width: 6px;
height: 6px;
border-radius: 50%;
background: var(--accent);
}
/* ===========================================
LAYER INDICATOR
=========================================== */
.layer-indicator {
display: flex;
gap: clamp(0.3rem, 0.6vw, 0.5rem);
margin-bottom: var(--content-gap);
}
.layer-dot {
width: clamp(28px, 3vw, 44px);
height: clamp(4px, 0.4vw, 6px);
border-radius: 999px;
background: var(--border-subtle);
transition: background 0.4s ease;
}
.layer-dot.active { background: var(--accent); }
/* ===========================================
SEPARATOR
=========================================== */
.sep {
width: 60px;
height: 3px;
border-radius: 999px;
background: var(--accent);
margin: var(--content-gap) 0;
opacity: 0.6;
}
/* ===========================================
TITLE SLIDE SPECIFIC
=========================================== */
.title-slide .subtitle {
font-size: clamp(0.9rem, 1.8vw, 1.35rem);
color: var(--text-secondary);
margin-top: clamp(0.5rem, 1.2vw, 1.2rem);
font-weight: 400;
max-width: 700px;
}
.title-slide .meta {
font-size: var(--small-size);
color: var(--text-muted);
margin-top: clamp(1rem, 2vw, 2rem);
display: flex;
gap: clamp(1rem, 2vw, 2rem);
}
.title-slide .meta span {
display: flex;
align-items: center;
gap: 0.4em;
}
/* Glowing accent line under title */
.title-accent {
width: clamp(60px, 8vw, 120px);
height: 3px;
background: linear-gradient(90deg, var(--accent), transparent);
border-radius: 999px;
margin-top: clamp(0.8rem, 1.5vw, 1.5rem);
box-shadow: 0 0 20px var(--accent-glow);
}
/* ===========================================
SPLIT LAYOUT
=========================================== */
.split {
display: grid;
grid-template-columns: 1fr 1fr;
gap: clamp(1.5rem, 3vw, 3rem);
align-items: center;
}
@media (max-width: 800px) {
.split { grid-template-columns: 1fr; }
}
/* ===========================================
VISUAL FLOW DIAGRAM (VERTICAL)
=========================================== */
.v-flow {
display: flex;
flex-direction: column;
gap: 0;
position: relative;
}
.v-flow-step {
display: flex;
align-items: flex-start;
gap: clamp(0.6rem, 1.2vw, 1.2rem);
position: relative;
padding-bottom: clamp(0.5rem, 1vh, 1rem);
}
.v-flow-num {
width: clamp(24px, 2.5vw, 34px);
height: clamp(24px, 2.5vw, 34px);
border-radius: 50%;
background: var(--accent-dim);
border: 1px solid var(--accent);
display: flex;
align-items: center;
justify-content: center;
font-size: var(--small-size);
font-weight: 700;
color: var(--accent);
flex-shrink: 0;
position: relative;
z-index: 1;
}
.v-flow-step:not(:last-child)::before {
content: '';
position: absolute;
left: calc(clamp(24px, 2.5vw, 34px) / 2 - 1px);
top: clamp(24px, 2.5vw, 34px);
bottom: 0;
width: 2px;
background: var(--border-accent);
}
.v-flow-content h3 {
font-size: var(--body-size);
margin-bottom: 0.2em;
}
.v-flow-content p {
font-size: var(--small-size);
color: var(--text-muted);
}
/* ===========================================
ANIMATIONS
=========================================== */
.reveal {
opacity: 0;
transform: translateY(25px);
transition: opacity var(--duration-normal) var(--ease-out-expo),
transform var(--duration-normal) var(--ease-out-expo);
}
.reveal-left {
opacity: 0;
transform: translateX(-30px);
transition: opacity var(--duration-normal) var(--ease-out-expo),
transform var(--duration-normal) var(--ease-out-expo);
}
.reveal-right {
opacity: 0;
transform: translateX(30px);
transition: opacity var(--duration-normal) var(--ease-out-expo),
transform var(--duration-normal) var(--ease-out-expo);
}
.reveal-scale {
opacity: 0;
transform: scale(0.92);
transition: opacity var(--duration-normal) var(--ease-out-expo),
transform var(--duration-normal) var(--ease-out-expo);
}
.slide.visible .reveal,
.slide.visible .reveal-left,
.slide.visible .reveal-right,
.slide.visible .reveal-scale {
opacity: 1;
transform: translateY(0) translateX(0) scale(1);
}
/* Stagger children */
.stagger > :nth-child(1) { transition-delay: 0.05s; }
.stagger > :nth-child(2) { transition-delay: 0.12s; }
.stagger > :nth-child(3) { transition-delay: 0.19s; }
.stagger > :nth-child(4) { transition-delay: 0.26s; }
.stagger > :nth-child(5) { transition-delay: 0.33s; }
.stagger > :nth-child(6) { transition-delay: 0.40s; }
.stagger > :nth-child(7) { transition-delay: 0.47s; }
.stagger > :nth-child(8) { transition-delay: 0.54s; }
/* ===========================================
PROGRESS BAR
=========================================== */
.progress-bar {
position: fixed;
top: 0;
left: 0;
height: 3px;
background: linear-gradient(90deg, var(--accent), var(--blue));
z-index: 1000;
transition: width 0.3s var(--ease-out-quart);
box-shadow: 0 0 10px var(--accent-glow);
}
/* ===========================================
NAV DOTS
=========================================== */
.nav-dots {
position: fixed;
right: clamp(10px, 1.5vw, 24px);
top: 50%;
transform: translateY(-50%);
display: flex;
flex-direction: column;
gap: clamp(6px, 0.8vh, 10px);
z-index: 100;
}
.nav-dot {
width: clamp(6px, 0.5vw, 8px);
height: clamp(6px, 0.5vw, 8px);
border-radius: 50%;
background: var(--text-muted);
opacity: 0.3;
cursor: pointer;
transition: all 0.3s ease;
border: none;
padding: 0;
}
.nav-dot:hover { opacity: 0.6; }
.nav-dot.active {
opacity: 1;
background: var(--accent);
box-shadow: 0 0 8px var(--accent-glow);
transform: scale(1.3);
}
/* ===========================================
SLIDE COUNTER
=========================================== */
.slide-counter {
position: fixed;
bottom: clamp(12px, 1.5vw, 24px);
right: clamp(16px, 2vw, 32px);
font-family: var(--font-body);
font-size: var(--small-size);
color: var(--text-muted);
z-index: 100;
font-variant-numeric: tabular-nums;
}
.slide-counter .current { color: var(--accent); font-weight: 600; }
/* ===========================================
KEYBOARD HINT
=========================================== */
.keyboard-hint {
position: fixed;
bottom: clamp(12px, 1.5vw, 24px);
left: clamp(16px, 2vw, 32px);
font-size: clamp(0.6rem, 0.8vw, 0.72rem);
color: var(--text-muted);
opacity: 0.4;
z-index: 100;
display: flex;
align-items: center;
gap: 0.5em;
}
.key {
display: inline-flex;
align-items: center;
justify-content: center;
min-width: 1.6em;
padding: 0.15em 0.35em;
border: 1px solid var(--text-muted);
border-radius: 3px;
font-size: 0.9em;
line-height: 1;
}
/* ===========================================
RESPONSIVE BREAKPOINTS
=========================================== */
@media (max-height: 700px) {
:root {
--slide-padding: clamp(1rem, 3.5vw, 2.5rem);
--content-gap: clamp(0.5rem, 1.5vw, 1.2rem);
--title-size: clamp(1.5rem, 5vw, 3rem);
--h2-size: clamp(1.2rem, 3vw, 2rem);
}
}
@media (max-height: 600px) {
:root {
--slide-padding: clamp(0.75rem, 3vw, 2rem);
--content-gap: clamp(0.4rem, 1vw, 0.8rem);
--title-size: clamp(1.3rem, 4.5vw, 2.2rem);
--body-size: clamp(0.7rem, 1.1vw, 0.9rem);
}
.nav-dots, .keyboard-hint { display: none; }
}
@media (max-height: 500px) {
:root {
--slide-padding: clamp(0.5rem, 2.5vw, 1.5rem);
--title-size: clamp(1.1rem, 4vw, 1.8rem);
--h2-size: clamp(0.95rem, 2.5vw, 1.4rem);
--body-size: clamp(0.65rem, 1vw, 0.8rem);
}
}
@media (max-width: 600px) {
:root {
--title-size: clamp(1.4rem, 8vw, 2.5rem);
}
}
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
transition-duration: 0.2s !important;
}
html { scroll-behavior: auto; }
}
/* ===========================================
PRINT / PDF STYLES
Forces landscape pages, one slide per page,
preserves dark theme with background colors
=========================================== */
@page {
size: 13.333in 7.5in; /* 16:9 widescreen — matches PowerPoint */
margin: 0;
}
@media print {
html, body {
height: auto;
overflow: visible;
-webkit-print-color-adjust: exact !important;
print-color-adjust: exact !important;
color-adjust: exact !important;
}
html {
scroll-snap-type: none;
}
.slide {
width: 100vw;
height: 100vh;
overflow: hidden;
page-break-after: always;
break-after: page;
page-break-inside: avoid;
break-inside: avoid;
scroll-snap-align: unset;
}
.slide:last-child {
page-break-after: auto;
break-after: auto;
}
/* Show all reveal elements immediately in print */
.reveal, .reveal-left, .reveal-right, .reveal-scale {
opacity: 1 !important;
transform: none !important;
transition: none !important;
}
/* Hide interactive UI chrome */
.progress-bar,
.nav-dots,
.slide-counter,
.keyboard-hint {
display: none !important;
}
/* Ensure backgrounds print */
.slide, .card, .code-block, .flow-step, .table-wrap,
.label, .badge, .v-flow-num, th, td, body {
-webkit-print-color-adjust: exact !important;
print-color-adjust: exact !important;
}
/* Grid backgrounds via ::before and ::after */
.grid-bg::after {
-webkit-print-color-adjust: exact !important;
print-color-adjust: exact !important;
}
}
</style>
</head>
<body>
<!-- Progress Bar -->
<div class="progress-bar" id="progressBar"></div>
<!-- Navigation Dots -->
<nav class="nav-dots" id="navDots"></nav>
<!-- Slide Counter -->
<div class="slide-counter">
<span class="current" id="currentSlide">01</span>
<span>/</span>
<span id="totalSlides">15</span>
</div>
<!-- Keyboard Hint -->
<div class="keyboard-hint">
<span class="key">&darr;</span> <span class="key">&uarr;</span> navigate
</div>
<!-- ==========================================
SLIDE 1: TITLE
========================================== -->
<section class="slide title-slide grid-bg">
<div class="slide-content">
<span class="label reveal">Architecture Plan</span>
<h1 class="reveal">Agent Action<br><span class="accent">Execution Layer</span></h1>
<div class="title-accent reveal"></div>
<p class="subtitle reveal">Closing the gap between classification and execution in the agent-service pipeline</p>
<div class="meta reveal">
<span>Marcos Kuchak</span>
<span>March 2026</span>
<span>Draft</span>
</div>
</div>
</section>
<!-- ==========================================
SLIDE 2: THE PROBLEM
========================================== -->
<section class="slide grid-bg">
<div class="slide-content stagger">
<span class="label red-label reveal">The Problem</span>
<h2 class="reveal">The pipeline classifies actions<br>but <span class="red">never executes them</span></h2>
<div class="grid-2 reveal" style="margin-top: var(--content-gap);">
<div class="card">
<h3 style="color: var(--red);">Auto-Execute Path</h3>
<p>The <code>auto_executed</code> label logs "success" in the action log &mdash; <strong>no MCP tool is called</strong>. No side effect occurs.</p>
</div>
<div class="card">
<h3 style="color: var(--red);">Inbox Approval Path</h3>
<p>User approves an inbox item &mdash; <strong>PATCH updates status in MongoDB</strong>. Nothing happens. No tool executes.</p>
</div>
</div>
<div class="code-block reveal" style="margin-top: var(--content-gap);">Handler returns ProposedAction[]
<span class="comment">→ enforceGate() classifies each action</span>
<span class="comment">→ Tier 1 (safe): logs "success" → NOTHING EXECUTES</span>
<span class="comment">→ Tier 2 (medium): logs "success" → NOTHING EXECUTES</span>
<span class="comment">→ Tier 3 (risky): logs "pending_review" → NOTHING EXECUTES</span>
User approves inbox item
<span class="comment">→ PATCH /v1/inbox/:id → status updated → NOTHING EXECUTES</span></div>
</div>
</section>
<!-- ==========================================
SLIDE 3: THREE LAYERS OVERVIEW
========================================== -->
<section class="slide grid-bg">
<div class="slide-content stagger">
<span class="label reveal">Solution</span>
<h2 class="reveal">Three layers to close the gap</h2>
<div class="grid-3 reveal" style="margin-top: var(--content-gap);">
<div class="card" style="border-top: 3px solid var(--accent);">
<div style="display:flex; justify-content:space-between; align-items:center;">
<h3>Layer 1</h3>
<span class="badge badge-accent">~80%</span>
</div>
<p style="margin-top:0.5em;"><strong class="white">Wrapped Tools</strong></p>
<p style="margin-top:0.3em;">Every mutation MCP tool wrapped with inline confidence gate. Agent calls tool with <code>confidence</code> param. Wrapper decides: execute or defer.</p>
</div>
<div class="card" style="border-top: 3px solid var(--blue);">
<div style="display:flex; justify-content:space-between; align-items:center;">
<h3 style="color: var(--blue);">Layer 2</h3>
<span class="badge badge-blue">~20%</span>
</div>
<p style="margin-top:0.5em;"><strong class="white">Post-Handler Gate</strong></p>
<p style="margin-top:0.3em;">Existing flow, unchanged. For content-only outputs (Morning Brief, reports) that aren't tool calls. ProposedAction[] &rarr; gate &rarr; inbox.</p>
</div>
<div class="card" style="border-top: 3px solid var(--purple);">
<div style="display:flex; justify-content:space-between; align-items:center;">
<h3 style="color: var(--purple);">Layer 3</h3>
<span class="badge badge-accent">Deferred</span>
</div>
<p style="margin-top:0.5em;"><strong class="white">Executor on Approval</strong></p>
<p style="margin-top:0.3em;">When Layer 1 or 2 defers to inbox and user approves, the executor calls the corresponding MCP tool with stored payload.</p>
</div>
</div>
<p class="reveal" style="margin-top: var(--content-gap); color: var(--text-muted); font-style: italic; font-size: var(--small-size);">
Key insight: the agent calls tools. The tools themselves are smart enough to gate their own execution.
</p>
</div>
</section>
<!-- ==========================================
SLIDE 4: LAYER 1 — CONCEPT
========================================== -->
<section class="slide grid-bg">
<div class="slide-content stagger">
<div class="layer-indicator reveal">
<div class="layer-dot active"></div>
<div class="layer-dot"></div>
<div class="layer-dot"></div>
</div>
<h2 class="reveal">Layer 1: <span class="accent">Wrapped Tools</span></h2>
<p class="reveal" style="max-width: 750px;">Every mutation MCP tool is wrapped before being given to the agent. The wrapper adds <code>confidence</code> and <code>reasoning</code> to the tool's input schema. The agent calls the tool naturally &mdash; the wrapper gates execution deterministically.</p>
<div class="split reveal" style="margin-top: var(--content-gap);">
<div>
<h3 style="font-size: var(--body-size); color: var(--text-primary); margin-bottom: 0.5em;">What the agent sees</h3>
<div class="code-block"><span class="fn">create_task</span>({
<span class="string">loanApplicationId</span>: <span class="string">"loan-123"</span>,
<span class="string">title</span>: <span class="string">"Upload W2"</span>,
<span class="accent">confidence</span>: <span class="type">0.92</span>,
<span class="accent">reasoning</span>: <span class="string">"Condition requires W2"</span>
})</div>
</div>
<div>
<h3 style="font-size: var(--body-size); color: var(--text-primary); margin-bottom: 0.5em;">Per-tool, per-workflow config</h3>
<ul class="bullet-list">
<li>R2 wraps <code>create_task</code> with threshold <strong class="green">0</strong> (always execute)</li>
<li>R1 wraps <code>send_email</code> with threshold <strong class="amber">0.95</strong> (high bar)</li>
<li>P4 wraps <code>send_email</code> with threshold <strong class="blue">0.85</strong> (routine follow-ups)</li>
</ul>
</div>
</div>
</div>
</section>
<!-- ==========================================
SLIDE 5: LAYER 1 — DECISION FLOW
========================================== -->
<section class="slide grid-bg">
<div class="slide-content stagger">
<div class="layer-indicator reveal">
<div class="layer-dot active"></div>
<div class="layer-dot"></div>
<div class="layer-dot"></div>
</div>
<h2 class="reveal">Wrapper Decision Flow</h2>
<div class="v-flow reveal" style="margin-top: var(--content-gap);">
<div class="v-flow-step">
<div class="v-flow-num">1</div>
<div class="v-flow-content">
<h3><span class="red">Compliance Blocked?</span></h3>
<p>If action is in the NEVER_AUTO_EXECUTE set &rarr; write inbox item, return <code>"pending_approval"</code>. Agent adapts messaging.</p>
</div>
</div>
<div class="v-flow-step">
<div class="v-flow-num">2</div>
<div class="v-flow-content">
<h3><span class="green">Confidence &ge; Threshold &amp; autoExecute?</span></h3>
<p>Call real MCP tool &rarr; log success &rarr; return tool result to agent. Optionally create FYI inbox item.</p>
</div>
</div>
<div class="v-flow-step">
<div class="v-flow-num">3</div>
<div class="v-flow-content">
<h3><span class="amber">Fallback Strategy</span></h3>
<p><strong>inbox_review</strong> &rarr; pending item, urgency high &nbsp;|&nbsp; <strong>draft</strong> &rarr; draft item, urgency medium &nbsp;|&nbsp; <strong>skip</strong> &rarr; log skipped, no item</p>
</div>
</div>
</div>
<div class="grid-2 reveal" style="margin-top: var(--content-gap);">
<div class="card" style="border-left: 3px solid var(--green);">
<p style="font-size: var(--small-size);"><strong class="green">When executed</strong></p>
<p style="font-size: var(--small-size); margin-top:0.3em; color:var(--text-muted);">Agent: "I created a task for uploading the W2."</p>
</div>
<div class="card" style="border-left: 3px solid var(--amber);">
<p style="font-size: var(--small-size);"><strong class="amber">When deferred</strong></p>
<p style="font-size: var(--small-size); margin-top:0.3em; color:var(--text-muted);">Agent: "I've drafted the email but it needs your approval."</p>
</div>
</div>
</div>
</section>
<!-- ==========================================
SLIDE 6: LAYER 2 — POST-HANDLER GATE
========================================== -->
<section class="slide grid-bg">
<div class="slide-content stagger">
<div class="layer-indicator reveal">
<div class="layer-dot"></div>
<div class="layer-dot active"></div>
<div class="layer-dot"></div>
</div>
<h2 class="reveal">Layer 2: <span class="blue">Post-Handler Gate</span></h2>
<p class="reveal" style="max-width:700px;">For content-only outputs that aren't tool calls. The existing <code>ProposedAction[]</code> &rarr; <code>enforceGate()</code> &rarr; inbox flow. <strong>Unchanged.</strong></p>
<div class="grid-2 reveal" style="margin-top: var(--content-gap);">
<div>
<div class="table-wrap">
<table>
<thead><tr><th>Workflow</th><th>Output</th><th>Why not Layer 1</th></tr></thead>
<tbody>
<tr>
<td><strong class="white">P1</strong> Morning Brief</td>
<td>Risk summary</td>
<td class="muted">The brief IS the content</td>
</tr>
<tr>
<td><strong class="white">P2</strong> At-Risk Detection</td>
<td>Risk report</td>
<td class="muted">Content delivery, no mutation</td>
</tr>
<tr>
<td><strong class="white">Future</strong></td>
<td>Aggregated reports</td>
<td class="muted">Post-execution summaries</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="card" style="border-left: 3px solid var(--blue);">
<h3 style="color: var(--blue); font-size: var(--body-size);">Mixed Mode</h3>
<p style="margin-top: 0.4em;">Workflows can use <strong>both</strong> layers:</p>
<ul class="bullet-list" style="margin-top: 0.5em;">
<li>Wrapped tools for mutations <span class="muted">(Layer 1)</span></li>
<li>ProposedActions for content <span class="muted">(Layer 2)</span></li>
</ul>
<p style="margin-top: 0.6em; font-size: var(--small-size); color: var(--text-muted);">Uses global <code>confidence.ts</code> config</p>
</div>
</div>
</div>
</section>
<!-- ==========================================
SLIDE 7: LAYER 3 — EXECUTOR ON APPROVAL
========================================== -->
<section class="slide grid-bg">
<div class="slide-content stagger">
<div class="layer-indicator reveal">
<div class="layer-dot"></div>
<div class="layer-dot"></div>
<div class="layer-dot active"></div>
</div>
<h2 class="reveal">Layer 3: <span class="purple">Executor on Approval</span></h2>
<p class="reveal" style="max-width:700px;">When Layer 1 or 2 defers an action and the user approves, the executor dispatches the real MCP tool call.</p>
<div class="split reveal" style="margin-top: var(--content-gap);">
<div>
<div class="flow" style="flex-direction: column; align-items: stretch; gap: var(--element-gap);">
<div class="flow-step" style="white-space:normal;">User approves inbox item</div>
<div style="text-align:center; color: var(--text-muted);">&darr;</div>
<div class="flow-step active" style="white-space:normal;">PATCH /v1/inbox/:id &rarr; Executor reads payload + action type</div>
<div style="text-align:center; color: var(--text-muted);">&darr;</div>
<div class="flow-step" style="white-space:normal;">Calls MCP tool via ephemeral client</div>
<div style="text-align:center; color: var(--text-muted);">&darr;</div>
<div class="flow-step" style="white-space:normal;">Updates action_log + inbox with result</div>
</div>
</div>
<div>
<h3 style="font-size: var(--body-size); color: var(--text-primary); margin-bottom: 0.6em;">MCP Connection</h3>
<p style="margin-bottom: var(--element-gap);">The executor creates an ephemeral <code>McpClientManager</code> scoped to the tenant, shares the global tool metadata cache, and cleans up in a <code>finally</code> block.</p>
<h3 style="font-size: var(--body-size); color: var(--text-primary); margin-bottom: 0.4em; margin-top: 0.6em;">Error Handling</h3>
<p>If execution fails, inbox item is still marked approved. <code>executionStatus: "failed"</code> signals frontend to show retry.</p>
</div>
</div>
</div>
</section>
<!-- ==========================================
SLIDE 8: STALE PAYLOAD STRATEGIES
========================================== -->
<section class="slide grid-bg">
<div class="slide-content stagger">
<span class="label amber-label reveal">Layer 3 Detail</span>
<h2 class="reveal">Stale Payload <span class="amber">Strategies</span></h2>
<p class="reveal" style="max-width:700px;">Payload is frozen at proposal time. User may approve hours later. Each action type declares its execution strategy:</p>
<div class="grid-3 reveal" style="margin-top: var(--content-gap);">
<div class="card" style="border-top: 3px solid var(--green);">
<h3 style="color: var(--green);">Direct</h3>
<p style="margin-top:0.3em;">Execute with stored payload as-is. For additive actions where staleness doesn't matter.</p>
<p style="margin-top:0.5em; font-size: var(--small-size); color: var(--text-muted);">CREATE_TASK, CREATE_COMMENT, SEND_EMAIL, DRAFT_EMAIL, FLAG_TASK</p>
</div>
<div class="card" style="border-top: 3px solid var(--amber);">
<h3 style="color: var(--amber);">Pre-Check</h3>
<p style="margin-top:0.3em;">Fetch current state via MCP, compare against payload, reject if data changed since proposal.</p>
<p style="margin-top:0.5em; font-size: var(--small-size); color: var(--text-muted);">UPDATE_LOAN_DATA, UPDATE_FILE_PROGRESS, UPDATE_TASK_COMPLETE</p>
</div>
<div class="card" style="border-top: 3px solid var(--text-muted);">
<h3>None</h3>
<p style="margin-top:0.3em;">No execution needed. The inbox item IS the content delivery.</p>
<p style="margin-top:0.5em; font-size: var(--small-size); color: var(--text-muted);">MORNING_BRIEF</p>
</div>
</div>
<div class="card reveal" style="margin-top: var(--content-gap); border-left: 3px solid var(--amber); background: rgba(255,179,71,0.04);">
<p style="font-size: var(--small-size);"><strong class="amber">Pre-check fail example:</strong> Agent proposes <code>closingDate: "April 15"</code> at 7 AM. LO emails new date at 10 AM. User approves at 1 PM &rarr; executor fetches current state &rarr; sees field changed &rarr; rejects with reason. No data regression.</p>
</div>
</div>
</section>
<!-- ==========================================
SLIDE 9: TIER MAPPING — TIER 1
========================================== -->
<section class="slide grid-bg">
<div class="slide-content stagger">
<span class="label green-label reveal">Tier Mapping</span>
<h2 class="reveal">Tier 1: <span class="green">Always Auto-Execute</span></h2>
<p class="reveal" style="max-width: 600px; margin-bottom: var(--content-gap);">Low-risk additive actions. Wrapped with threshold 0 by default &mdash; always execute unless a workflow overrides.</p>
<div class="table-wrap reveal">
<table>
<thead>
<tr><th>Action</th><th>Threshold</th><th>Auto</th><th>Fallback</th><th>Rationale</th></tr>
</thead>
<tbody>
<tr><td><strong class="white">CREATE_TASK</strong></td><td><span class="green">0</span></td><td><span class="badge badge-green">Yes</span></td><td>skip</td><td>Additive, easy to modify/delete</td></tr>
<tr><td><strong class="white">CREATE_COMMENT</strong></td><td><span class="green">0</span></td><td><span class="badge badge-green">Yes</span></td><td>skip</td><td>Informational, no data mutation</td></tr>
<tr><td><strong class="white">UPDATE_TASK_REVIEW</strong></td><td><span class="green">0</span></td><td><span class="badge badge-green">Yes</span></td><td>skip</td><td>State transition tracking</td></tr>
<tr><td><strong class="white">FLAG_TASK</strong></td><td><span class="green">0</span></td><td><span class="badge badge-green">Yes</span></td><td>skip</td><td>Attention flag, easily reversed</td></tr>
<tr><td><strong class="white">DRAFT_EMAIL</strong></td><td><span class="green">0</span></td><td><span class="badge badge-green">Yes</span></td><td>skip</td><td>Creates draft, doesn't send</td></tr>
<tr><td><strong class="white">DRAFT_LO_UPDATE</strong></td><td><span class="green">0</span></td><td><span class="badge badge-green">Yes</span></td><td>skip</td><td>Creates draft for review</td></tr>
</tbody>
</table>
</div>
</div>
</section>
<!-- ==========================================
SLIDE 10: TIER MAPPING — TIER 2 & 3
========================================== -->
<section class="slide grid-bg">
<div class="slide-content stagger">
<h2 class="reveal">Tier 2 <span class="amber">&amp;</span> Tier 3</h2>
<div class="grid-2 reveal" style="margin-top: var(--content-gap);">
<div>
<h3 style="color: var(--amber); margin-bottom: 0.6em;">Tier 2: High Confidence Required</h3>
<div class="table-wrap">
<table>
<thead><tr><th>Action</th><th>Threshold</th><th>Fallback</th></tr></thead>
<tbody>
<tr><td><strong class="white">UPDATE_TASK_COMPLETE</strong></td><td><span class="amber">0.95</span></td><td>inbox_review</td></tr>
<tr><td><strong class="white">SEND_EMAIL</strong></td><td><span class="amber">0.95</span></td><td>draft</td></tr>
</tbody>
</table>
</div>
<div class="card" style="margin-top: var(--element-gap); border-left: 2px solid var(--amber);">
<p style="font-size: var(--small-size);"><strong class="amber">Example:</strong> Agent calls <code>send_email</code> with confidence 0.97 &rarr; executes. With 0.82 &rarr; defers to inbox as draft.</p>
</div>
</div>
<div>
<h3 style="color: var(--red); margin-bottom: 0.6em;">Tier 3: Always Require Approval</h3>
<div class="table-wrap">
<table>
<thead><tr><th>Action</th><th>Threshold</th><th>Fallback</th></tr></thead>
<tbody>
<tr><td><strong class="white">UPDATE_FILE_PROGRESS</strong></td><td><span class="red">1.0</span></td><td>inbox_review</td></tr>
<tr><td><strong class="white">UPDATE_LOAN_DATA</strong></td><td><span class="red">1.0</span></td><td>inbox_review</td></tr>
<tr><td><strong class="white">SEND_LO_UPDATE</strong></td><td><span class="red">1.0</span></td><td>inbox_review</td></tr>
</tbody>
</table>
</div>
<div class="card" style="margin-top: var(--element-gap); border-left: 2px solid var(--red);">
<p style="font-size: var(--small-size);"><span class="red"><strong>Compliance blocked.</strong></span> Wrapper NEVER executes, regardless of confidence. Execution only via Layer 3.</p>
</div>
</div>
</div>
</div>
</section>
<!-- ==========================================
SLIDE 11: wrapMcpTool API
========================================== -->
<section class="slide grid-bg">
<div class="slide-content stagger">
<span class="label reveal">API Design</span>
<h2 class="reveal">The <code>wrapMcpTool</code> Helper</h2>
<div class="split reveal" style="margin-top: var(--content-gap);">
<div class="code-block"><span class="keyword">type</span> <span class="type">WrapToolConfig</span> = {
<span class="string">tool</span>: ToolDef;
<span class="string">actionType</span>: <span class="type">string</span>; <span class="comment">// "CREATE_TASK"</span>
<span class="string">threshold</span>: <span class="type">number</span>; <span class="comment">// per-tool, per-workflow</span>
<span class="string">autoExecute</span>: <span class="type">boolean</span>;
<span class="string">fallback</span>: <span class="string">"draft"</span> | <span class="string">"inbox_review"</span> | <span class="string">"skip"</span>;
<span class="string">complianceBlocked</span>?: <span class="type">boolean</span>;
<span class="string">actionLogRepo</span>: ActionLogRepo;
<span class="string">inboxRepo</span>: InboxRepo;
<span class="string">tenantId</span>: <span class="type">string</span>;
<span class="string">workflowId</span>: <span class="type">string</span>;
<span class="string">loanApplicationId</span>?: <span class="type">string</span>;
<span class="string">targetUserId</span>?: <span class="type">string</span>;
};
<span class="keyword">function</span> <span class="fn">wrapMcpTool</span>(config): <span class="type">ToolDef</span>;</div>
<div>
<ul class="bullet-list">
<li><strong class="white">Centralized mechanism</strong> &mdash; every workflow uses the same helper</li>
<li><strong class="white">Gate logic in one place</strong> &mdash; compliance &rarr; threshold &rarr; fallback</li>
<li><strong class="white">Workflows only configure</strong> WHICH tools and WHAT thresholds</li>
<li><strong class="white">Schema extension</strong> &mdash; adds <code>confidence</code> + <code>reasoning</code> to input schema automatically</li>
<li><strong class="white">Strips extra params</strong> before passing to real MCP tool</li>
</ul>
</div>
</div>
</div>
</section>
<!-- ==========================================
SLIDE 12: INBOX LIFECYCLE
========================================== -->
<section class="slide grid-bg">
<div class="slide-content stagger">
<span class="label blue-label reveal">Inbox</span>
<h2 class="reveal">Inbox Item Lifecycle</h2>
<div class="grid-3 reveal" style="margin-top: var(--content-gap);">
<div class="card" style="border-top: 3px solid var(--accent);">
<h3 style="font-size: var(--body-size); color: var(--accent);">Informational</h3>
<p style="font-size: var(--small-size); margin-top: 0.3em; color: var(--text-muted);">"Agent did this"</p>
<p style="font-size: var(--small-size); margin-top: 0.5em;">Created by Layer 1 wrapper on auto-execute (optional FYI)</p>
<div class="flow" style="margin-top: 0.6em;">
<span class="flow-step" style="font-size: clamp(0.55rem, 0.7vw, 0.7rem);">pending</span>
<span class="flow-arrow">&rarr;</span>
<span class="flow-step" style="font-size: clamp(0.55rem, 0.7vw, 0.7rem);">reviewed / dismissed</span>
</div>
</div>
<div class="card" style="border-top: 3px solid var(--amber);">
<h3 style="font-size: var(--body-size); color: var(--amber);">Decisional</h3>
<p style="font-size: var(--small-size); margin-top: 0.3em; color: var(--text-muted);">"Approve this?"</p>
<p style="font-size: var(--small-size); margin-top: 0.5em;">Created by Layer 1 (deferred) or Layer 2 gate</p>
<div class="flow" style="margin-top: 0.6em;">
<span class="flow-step" style="font-size: clamp(0.55rem, 0.7vw, 0.7rem);">pending</span>
<span class="flow-arrow">&rarr;</span>
<span class="flow-step active" style="font-size: clamp(0.55rem, 0.7vw, 0.7rem);">approved &rarr; executor</span>
</div>
</div>
<div class="card" style="border-top: 3px solid var(--blue);">
<h3 style="font-size: var(--body-size); color: var(--blue);">Content</h3>
<p style="font-size: var(--small-size); margin-top: 0.3em; color: var(--text-muted);">"Here's your brief"</p>
<p style="font-size: var(--small-size); margin-top: 0.5em;">Created by Layer 2 gate (content delivery)</p>
<div class="flow" style="margin-top: 0.6em;">
<span class="flow-step" style="font-size: clamp(0.55rem, 0.7vw, 0.7rem);">pending</span>
<span class="flow-arrow">&rarr;</span>
<span class="flow-step" style="font-size: clamp(0.55rem, 0.7vw, 0.7rem);">reviewed / dismissed</span>
</div>
</div>
</div>
<div class="table-wrap reveal" style="margin-top: var(--content-gap);">
<table>
<thead><tr><th>Source</th><th>executionStatus</th><th>UI Behavior</th></tr></thead>
<tbody>
<tr><td>Wrapper auto-executed (FYI)</td><td><span class="badge badge-green">executed</span></td><td>Show as done, dismiss option</td></tr>
<tr><td>Wrapper deferred</td><td><span class="badge badge-amber">pending_approval</span></td><td>Show approve/reject buttons</td></tr>
<tr><td>Layer 2 content</td><td><span class="badge badge-blue">not_applicable</span></td><td>Show review/dismiss</td></tr>
<tr><td>Approved + executor ran</td><td><span class="badge badge-green">executed</span></td><td>Show as completed</td></tr>
<tr><td>Approved + executor failed</td><td><span class="badge badge-red">failed</span></td><td>Show retry option</td></tr>
</tbody>
</table>
</div>
</div>
</section>
<!-- ==========================================
SLIDE 13: PER-WORKFLOW IMPACT
========================================== -->
<section class="slide grid-bg">
<div class="slide-content stagger">
<span class="label purple-label reveal">Impact</span>
<h2 class="reveal">Per-Workflow Impact</h2>
<div class="table-wrap reveal" style="margin-top: var(--content-gap);">
<table>
<thead><tr><th>Workflow</th><th>Layer 1 (Wrapped Tools)</th><th>Layer 2 (Content)</th><th>Status</th></tr></thead>
<tbody>
<tr><td><strong class="white">P1</strong> Morning Brief</td><td class="muted">&mdash; (reads only)</td><td>Risk summary per processor</td><td><span class="badge badge-green">No change</span></td></tr>
<tr><td><strong class="white">P5</strong> Tasks Aging</td><td><code>flag_task</code>, <code>create_comment</code></td><td class="muted">&mdash;</td><td><span class="badge badge-amber">Update</span></td></tr>
<tr><td><strong class="white">R2</strong> Cond. Approval</td><td><code>create_task</code>, <code>update_loan</code></td><td class="muted">&mdash;</td><td><span class="badge badge-amber">In progress</span></td></tr>
<tr><td><strong class="white">P3</strong> LO Status</td><td><code>create_lo_update</code>, <code>send_lo_update</code></td><td class="muted">&mdash;</td><td><span class="badge badge-amber">In progress</span></td></tr>
<tr><td><strong class="white">R1</strong> Draft Email</td><td><code>draft_email</code>, <code>send_email</code> (0.95)</td><td class="muted">&mdash;</td><td><span class="badge badge-blue">Future</span></td></tr>
<tr><td><strong class="white">R3</strong> Doc Matching</td><td><code>create_comment</code>, <code>update_task</code> (0.95)</td><td class="muted">&mdash;</td><td><span class="badge badge-blue">Future</span></td></tr>
<tr><td><strong class="white">P2</strong> At-Risk</td><td><code>flag_task</code>, <code>create_comment</code></td><td>Risk report summary</td><td><span class="badge badge-blue">Future</span></td></tr>
</tbody>
</table>
</div>
</div>
</section>
<!-- ==========================================
SLIDE 14: IMPLEMENTATION PHASES
========================================== -->
<section class="slide grid-bg">
<div class="slide-content stagger">
<span class="label reveal">Roadmap</span>
<h2 class="reveal">Implementation Phases</h2>
<div class="grid-3 reveal" style="margin-top: var(--content-gap);">
<div class="card" style="border-top: 3px solid var(--accent);">
<div style="display:flex; justify-content:space-between; align-items:center;">
<h3>Phase 1</h3>
<span class="badge badge-accent">Unblocks all</span>
</div>
<p style="margin-top:0.4em;"><strong class="white">Tool Wrapper</strong></p>
<ul class="bullet-list" style="margin-top:0.4em;">
<li>Create <code>wrapMcpTool()</code> helper</li>
<li>Schema extension logic</li>
<li>Expose repos to handlers</li>
<li>Unit tests (all gate paths)</li>
<li>P5 proof-of-concept</li>
</ul>
</div>
<div class="card" style="border-top: 3px solid var(--purple);">
<div style="display:flex; justify-content:space-between; align-items:center;">
<h3 style="color: var(--purple);">Phase 2</h3>
<span class="badge badge-accent">Tier 2-3</span>
</div>
<p style="margin-top:0.4em;"><strong class="white">Executor on Approval</strong></p>
<ul class="bullet-list" style="margin-top:0.4em;">
<li>Action executor + registry</li>
<li>Ephemeral MCP client</li>
<li>PATCH endpoint enhancement</li>
<li><code>executionStatus</code> field</li>
<li>Unit tests</li>
</ul>
</div>
<div class="card" style="border-top: 3px solid var(--blue);">
<div style="display:flex; justify-content:space-between; align-items:center;">
<h3 style="color: var(--blue);">Phase 3</h3>
<span class="badge badge-accent">Adoption</span>
</div>
<p style="margin-top:0.4em;"><strong class="white">Per-Workflow Rollout</strong></p>
<ul class="bullet-list" style="margin-top:0.4em;">
<li>R2: Andre</li>
<li>P3: Andres S.</li>
<li>P5: Marcos/Matheus</li>
<li>All new workflows adopt from day one</li>
</ul>
</div>
</div>
</div>
</section>
<!-- ==========================================
SLIDE 15: RISKS & MITIGATIONS
========================================== -->
<section class="slide grid-bg">
<div class="slide-content stagger">
<span class="label red-label reveal">Risks</span>
<h2 class="reveal">Risks &amp; Mitigations</h2>
<div class="grid-2 reveal" style="margin-top: var(--content-gap);">
<div class="card">
<h3 style="color: var(--red); font-size: var(--body-size);">Agent games confidence (always 1.0)</h3>
<p style="margin-top:0.3em; font-size: var(--small-size);">Prompt engineering + <code>complianceBlocked</code> always blocks regardless. Can add max confidence cap per wrapper.</p>
</div>
<div class="card">
<h3 style="color: var(--red); font-size: var(--body-size);">Wrapper executes but logging fails</h3>
<p style="margin-top:0.3em; font-size: var(--small-size);">Try/catch &mdash; if log fails, log error but don't fail the tool. Better done than rolled back.</p>
</div>
<div class="card">
<h3 style="color: var(--red); font-size: var(--body-size);">Executor MCP connection fails on approval</h3>
<p style="margin-top:0.3em; font-size: var(--small-size);">Return error in API response. Set <code>executionStatus: "failed"</code>. Frontend shows retry.</p>
</div>
<div class="card">
<h3 style="color: var(--amber); font-size: var(--body-size);">Per-workflow threshold drift</h3>
<p style="margin-top:0.3em; font-size: var(--small-size);">This is a <strong class="green">feature</strong>, not a bug. Different contexts warrant different thresholds. Document conventions.</p>
</div>
</div>
</div>
</section>
<!-- ==========================================
SLIDE 16: FILES SUMMARY
========================================== -->
<section class="slide grid-bg">
<div class="slide-content stagger">
<span class="label reveal">Scope</span>
<h2 class="reveal">Files Summary</h2>
<div class="grid-2 reveal" style="margin-top: var(--content-gap);">
<div>
<h3 style="color: var(--green); font-size: var(--body-size); margin-bottom: 0.5em;">New Files</h3>
<div class="table-wrap">
<table>
<thead><tr><th>File</th><th>Purpose</th></tr></thead>
<tbody>
<tr><td><code>tool-wrapper.ts</code></td><td>wrapMcpTool() + gate logic</td></tr>
<tr><td><code>tool-wrapper.spec.ts</code></td><td>Unit tests</td></tr>
<tr><td><code>action-executor.ts</code></td><td>Registry + executor + MCP</td></tr>
<tr><td><code>action-executor.spec.ts</code></td><td>Unit tests</td></tr>
</tbody>
</table>
</div>
</div>
<div>
<h3 style="color: var(--amber); font-size: var(--body-size); margin-bottom: 0.5em;">Modified Files</h3>
<div class="table-wrap">
<table>
<thead><tr><th>File</th><th>Change</th></tr></thead>
<tbody>
<tr><td><code>domain/types.ts</code></td><td>Repo access types</td></tr>
<tr><td><code>orchestrator.ts</code></td><td>Pass repos to handlers</td></tr>
<tr><td><code>inbox/update.ts</code></td><td>Executor on approval</td></tr>
<tr><td><code>inbox-item.schema</code></td><td>executionStatus field</td></tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="card reveal" style="margin-top: var(--content-gap); border-left: 3px solid var(--text-muted);">
<p style="font-size: var(--small-size);"><strong>Unchanged:</strong> <code>confidence.ts</code> (Layer 2 only), <code>compliance.ts</code>, <code>confidence-gate.ts</code>, <code>mcp-normalize.ts</code>, <code>mastra/adapter.ts</code></p>
</div>
</div>
</section>
<!-- ==========================================
SLIDE 17: CLOSING
========================================== -->
<section class="slide title-slide grid-bg">
<div class="slide-content" style="align-items: center; text-align: center;">
<h1 class="reveal" style="font-size: clamp(1.5rem, 4vw, 3.5rem);">The agent calls tools.<br><span class="accent">The tools gate themselves.</span></h1>
<div class="title-accent reveal" style="margin: var(--content-gap) auto;"></div>
<p class="reveal" style="color: var(--text-secondary); max-width: 600px; margin: 0 auto;">
Phase 1 unblocks all workflows. Phase 2 closes the approval loop. Phase 3 is per-team adoption.
</p>
<div class="meta reveal" style="justify-content: center;">
<span>Ready for review</span>
</div>
</div>
</section>
<!-- ===========================================
JAVASCRIPT: Slide Controller
=========================================== -->
<script>
class SlidePresentation {
constructor() {
this.slides = document.querySelectorAll('.slide');
this.totalSlides = this.slides.length;
this.currentIndex = 0;
this.isTransitioning = false;
document.getElementById('totalSlides').textContent =
String(this.totalSlides).padStart(2, '0');
this.createNavDots();
this.setupObserver();
this.setupKeyboard();
this.setupWheel();
this.setupTouch();
this.updateProgress();
/* Make first slide visible immediately */
this.slides[0].classList.add('visible');
}
/* --- Navigation Dots --- */
createNavDots() {
const nav = document.getElementById('navDots');
this.slides.forEach((_, i) => {
const dot = document.createElement('button');
dot.classList.add('nav-dot');
if (i === 0) dot.classList.add('active');
dot.setAttribute('aria-label', `Go to slide ${i + 1}`);
dot.addEventListener('click', () => this.goToSlide(i));
nav.appendChild(dot);
});
this.dots = nav.querySelectorAll('.nav-dot');
}
/* --- Intersection Observer for scroll-triggered animations --- */
setupObserver() {
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('visible');
const index = Array.from(this.slides).indexOf(entry.target);
if (index !== -1) {
this.currentIndex = index;
this.updateUI();
}
}
});
}, { threshold: 0.5 });
this.slides.forEach(slide => observer.observe(slide));
}
/* --- Keyboard Navigation --- */
setupKeyboard() {
document.addEventListener('keydown', (e) => {
if (e.key === 'ArrowDown' || e.key === 'ArrowRight' || e.key === ' ') {
e.preventDefault();
this.next();
} else if (e.key === 'ArrowUp' || e.key === 'ArrowLeft') {
e.preventDefault();
this.prev();
} else if (e.key === 'Home') {
e.preventDefault();
this.goToSlide(0);
} else if (e.key === 'End') {
e.preventDefault();
this.goToSlide(this.totalSlides - 1);
}
});
}
/* --- Mouse Wheel with debounce --- */
setupWheel() {
let lastWheelTime = 0;
document.addEventListener('wheel', (e) => {
const now = Date.now();
if (now - lastWheelTime < 800) return;
lastWheelTime = now;
if (e.deltaY > 30) this.next();
else if (e.deltaY < -30) this.prev();
}, { passive: true });
}
/* --- Touch / Swipe --- */
setupTouch() {
let startY = 0;
document.addEventListener('touchstart', (e) => {
startY = e.touches[0].clientY;
}, { passive: true });
document.addEventListener('touchend', (e) => {
const diff = startY - e.changedTouches[0].clientY;
if (Math.abs(diff) > 60) {
if (diff > 0) this.next();
else this.prev();
}
}, { passive: true });
}
/* --- Navigation Methods --- */
next() {
if (this.currentIndex < this.totalSlides - 1) {
this.goToSlide(this.currentIndex + 1);
}
}
prev() {
if (this.currentIndex > 0) {
this.goToSlide(this.currentIndex - 1);
}
}
goToSlide(index) {
this.currentIndex = index;
this.slides[index].scrollIntoView({ behavior: 'smooth' });
this.updateUI();
}
/* --- UI Updates --- */
updateUI() {
this.updateProgress();
this.updateDots();
this.updateCounter();
}
updateProgress() {
const progress = ((this.currentIndex + 1) / this.totalSlides) * 100;
document.getElementById('progressBar').style.width = `${progress}%`;
}
updateDots() {
this.dots.forEach((dot, i) => {
dot.classList.toggle('active', i === this.currentIndex);
});
}
updateCounter() {
document.getElementById('currentSlide').textContent =
String(this.currentIndex + 1).padStart(2, '0');
}
}
/* Initialize on DOM ready */
document.addEventListener('DOMContentLoaded', () => {
new SlidePresentation();
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment