eaglelandsonce's picture
Update index.html
bf36153 verified
Raw History Blame Contribute Delete
63.7 kB
<!doctype html>
<html lang="en" data-theme="dark">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Modernization Guided Walkthrough · Legacy to Cloud</title>
<style>
:root {
--font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
--font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace;
--bg-primary: #0f172a;
--bg-secondary: #1e293b;
--bg-card: rgba(30, 41, 59, 0.7);
--bg-card-hover: rgba(51, 65, 85, 0.8);
--bg-input: #0f172a;
--text-primary: #f8fafc;
--text-secondary: #94a3b8;
--text-muted: #64748b;
--text-inverse: #0f172a;
--border-color: rgba(255, 255, 255, 0.08);
--border-highlight: rgba(56, 189, 248, 0.3);
--primary: #38bdf8;
--primary-glow: rgba(56, 189, 248, 0.25);
--secondary: #818cf8;
--accent-green: #34d399;
--accent-amber: #fbbf24;
--accent-rose: #f43f5e;
--accent-purple: #c084fc;
--radius-sm: 6px;
--radius-md: 10px;
--radius-lg: 16px;
--radius-full: 9999px;
--shadow-subtle: 0 4px 20px -2px rgba(0, 0, 0, 0.3);
--shadow-glow: 0 0 25px -5px var(--primary-glow);
}
@media (prefers-color-scheme: light) {
:root[data-theme="system"], :root[data-theme="light"] {
--bg-primary: #f8fafc;
--bg-secondary: #ffffff;
--bg-card: rgba(255, 255, 255, 0.85);
--bg-card-hover: #f1f5f9;
--bg-input: #f8fafc;
--text-primary: #0f172a;
--text-secondary: #475569;
--text-muted: #94a3b8;
--text-inverse: #ffffff;
--border-color: rgba(15, 23, 42, 0.08);
--border-highlight: rgba(14, 165, 233, 0.4);
--primary: #0284c7;
--primary-glow: rgba(2, 132, 199, 0.2);
--secondary: #6366f1;
--accent-green: #059669;
--accent-amber: #d97706;
--accent-rose: #e11d48;
--accent-purple: #9333ea;
}
}
:root[data-theme="light"] {
--bg-primary: #f8fafc;
--bg-secondary: #ffffff;
--bg-card: rgba(255, 255, 255, 0.85);
--bg-card-hover: #f1f5f9;
--bg-input: #f8fafc;
--text-primary: #0f172a;
--text-secondary: #475569;
--text-muted: #94a3b8;
--text-inverse: #ffffff;
--border-color: rgba(15, 23, 42, 0.08);
--border-highlight: rgba(14, 165, 233, 0.4);
--primary: #0284c7;
--primary-glow: rgba(2, 132, 199, 0.2);
--secondary: #6366f1;
--accent-green: #059669;
--accent-amber: #d97706;
--accent-rose: #e11d48;
--accent-purple: #9333ea;
}
:root[data-theme="dark"] {
--bg-primary: #0f172a;
--bg-secondary: #1e293b;
--bg-card: rgba(30, 41, 59, 0.7);
--bg-card-hover: rgba(51, 65, 85, 0.8);
--bg-input: #0f172a;
--text-primary: #f8fafc;
--text-secondary: #94a3b8;
--text-muted: #64748b;
--text-inverse: #0f172a;
--border-color: rgba(255, 255, 255, 0.08);
--border-highlight: rgba(56, 189, 248, 0.3);
--primary: #38bdf8;
--primary-glow: rgba(56, 189, 248, 0.25);
--secondary: #818cf8;
--accent-green: #34d399;
--accent-amber: #fbbf24;
--accent-rose: #f43f5e;
--accent-purple: #c084fc;
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: var(--font-sans);
background-color: var(--bg-primary);
color: var(--text-primary);
line-height: 1.5;
padding: 24px 16px;
display: flex;
justify-content: center;
-webkit-font-smoothing: antialiased;
}
.container {
width: 100%;
max-width: 1080px;
display: flex;
flex-direction: column;
gap: 20px;
}
/* Glass Card */
.glass-panel {
background: var(--bg-card);
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
border: 1px solid var(--border-color);
border-radius: var(--radius-lg);
padding: 20px 24px;
box-shadow: var(--shadow-subtle);
transition: border-color 0.2s ease, box-shadow 0.2s ease;
}
/* Header */
.header-bar {
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
gap: 16px;
}
.brand-section {
display: flex;
flex-direction: column;
gap: 4px;
}
.tagline {
display: inline-flex;
align-items: center;
gap: 6px;
font-size: 11px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.08em;
color: var(--primary);
}
.tagline-dot {
width: 7px;
height: 7px;
border-radius: var(--radius-full);
background-color: var(--accent-green);
box-shadow: 0 0 8px var(--accent-green);
animation: pulse-dot 2s infinite;
}
@keyframes pulse-dot {
0%, 100% { transform: scale(1); opacity: 1; }
50% { transform: scale(1.3); opacity: 0.7; }
}
.main-title {
font-size: 24px;
font-weight: 800;
letter-spacing: -0.02em;
background: linear-gradient(135deg, var(--text-primary) 30%, var(--primary) 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.theme-toggle-group {
display: flex;
align-items: center;
gap: 10px;
}
/* Track Selector Tabs */
.track-selector {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 10px;
background: rgba(0, 0, 0, 0.15);
padding: 6px;
border-radius: var(--radius-lg);
border: 1px solid var(--border-color);
}
.track-btn {
display: flex;
align-items: center;
gap: 10px;
padding: 10px 14px;
background: transparent;
border: 1px solid transparent;
border-radius: var(--radius-md);
color: var(--text-secondary);
font-family: inherit;
font-size: 13px;
font-weight: 600;
cursor: pointer;
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
text-align: left;
}
.track-btn:hover {
background: var(--bg-card-hover);
color: var(--text-primary);
}
.track-btn.active {
background: var(--bg-secondary);
color: var(--text-primary);
border-color: var(--border-highlight);
box-shadow: var(--shadow-subtle), 0 0 0 1px var(--primary-glow);
}
.track-btn .track-icon {
font-size: 18px;
display: flex;
align-items: center;
justify-content: center;
}
.track-meta {
display: flex;
flex-direction: column;
}
.track-name {
font-weight: 700;
font-size: 13px;
}
.track-desc {
font-size: 11px;
color: var(--text-muted);
font-weight: 400;
}
/* Stepper Progress Bar */
.stepper-container {
display: flex;
flex-direction: column;
gap: 10px;
}
.stepper-nav {
display: flex;
align-items: center;
justify-content: space-between;
gap: 6px;
overflow-x: auto;
padding-bottom: 6px;
scrollbar-width: none;
}
.stepper-nav::-webkit-scrollbar { display: none; }
.step-node {
flex: 1;
min-width: 105px;
display: flex;
flex-direction: column;
align-items: center;
gap: 6px;
padding: 8px 6px;
background: transparent;
border: 1px solid transparent;
border-radius: var(--radius-md);
cursor: pointer;
transition: all 0.2s ease;
position: relative;
}
.step-node:hover {
background: var(--bg-card-hover);
}
.step-node.active {
background: rgba(56, 189, 248, 0.08);
border-color: var(--border-highlight);
}
.step-pill {
width: 24px;
height: 24px;
border-radius: var(--radius-full);
display: flex;
align-items: center;
justify-content: center;
font-size: 11px;
font-weight: 700;
background: var(--bg-secondary);
color: var(--text-muted);
border: 1px solid var(--border-color);
transition: all 0.2s ease;
}
.step-node.completed .step-pill {
background: var(--accent-green);
color: #ffffff;
border-color: var(--accent-green);
}
.step-node.active .step-pill {
background: var(--primary);
color: var(--text-inverse);
border-color: var(--primary);
box-shadow: 0 0 12px var(--primary-glow);
}
.step-label {
font-size: 11px;
font-weight: 600;
color: var(--text-muted);
white-space: nowrap;
transition: color 0.2s ease;
}
.step-node.active .step-label {
color: var(--primary);
font-weight: 700;
}
.step-node.completed .step-label {
color: var(--text-secondary);
}
/* Orchestration Agent Layer */
.orchestrator-banner {
background: linear-gradient(135deg, rgba(99, 102, 241, 0.12) 0%, rgba(56, 189, 248, 0.08) 100%);
border: 1px solid rgba(129, 140, 248, 0.25);
border-radius: var(--radius-md);
padding: 14px 18px;
display: flex;
flex-direction: column;
gap: 10px;
position: relative;
overflow: hidden;
}
.orchestrator-banner::before {
content: "";
position: absolute;
top: 0;
left: 0;
width: 3px;
height: 100%;
background: linear-gradient(180deg, var(--secondary), var(--primary));
}
.orchestrator-header {
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
gap: 8px;
}
.agent-identity {
display: flex;
align-items: center;
gap: 8px;
font-weight: 700;
font-size: 13px;
color: var(--text-primary);
}
.agent-badge {
font-size: 10px;
padding: 2px 8px;
border-radius: var(--radius-full);
background: rgba(129, 140, 248, 0.2);
color: var(--secondary);
font-weight: 700;
letter-spacing: 0.04em;
}
.orchestrator-spans {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 8px;
}
.span-pill {
padding: 6px 10px;
font-size: 11px;
border-radius: var(--radius-sm);
background: rgba(0, 0, 0, 0.15);
border: 1px solid var(--border-color);
color: var(--text-secondary);
text-align: center;
font-weight: 500;
transition: all 0.2s ease;
}
.span-pill.current {
background: rgba(56, 189, 248, 0.15);
border-color: var(--border-highlight);
color: var(--primary);
font-weight: 700;
}
/* Transformation Flow / Visual Stage */
.stage-hero {
display: flex;
flex-direction: column;
gap: 16px;
}
.stage-title-wrap {
display: flex;
justify-content: space-between;
align-items: flex-start;
flex-wrap: wrap;
gap: 10px;
}
.stage-title-main {
font-size: 18px;
font-weight: 700;
color: var(--text-primary);
}
.stage-category-badge {
font-size: 11px;
padding: 4px 10px;
border-radius: var(--radius-full);
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.05em;
background: rgba(56, 189, 248, 0.12);
color: var(--primary);
border: 1px solid var(--border-highlight);
}
.flow-scene {
display: grid;
grid-template-columns: 1fr 40px 1.2fr 40px 1fr;
align-items: center;
gap: 8px;
background: var(--bg-secondary);
padding: 20px 16px;
border-radius: var(--radius-lg);
border: 1px solid var(--border-color);
position: relative;
}
.flow-card {
display: flex;
flex-direction: column;
gap: 8px;
background: var(--bg-card);
padding: 14px;
border-radius: var(--radius-md);
border: 1px solid var(--border-color);
min-height: 120px;
justify-content: center;
transition: transform 0.2s ease, border-color 0.2s ease;
}
.flow-card:hover {
transform: translateY(-2px);
border-color: var(--border-highlight);
}
.flow-card.center-actor {
background: linear-gradient(135deg, rgba(56, 189, 248, 0.1) 0%, rgba(99, 102, 241, 0.1) 100%);
border-color: var(--border-highlight);
box-shadow: 0 4px 20px -2px rgba(56, 189, 248, 0.15);
}
.card-role-tag {
font-size: 10px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.06em;
color: var(--text-muted);
}
.center-actor .card-role-tag {
color: var(--primary);
}
.card-main-text {
font-size: 13px;
font-weight: 700;
color: var(--text-primary);
line-height: 1.4;
}
.center-actor .card-main-text {
font-size: 15px;
background: linear-gradient(135deg, #38bdf8, #818cf8);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.card-sub-text {
font-size: 11px;
color: var(--text-secondary);
}
.flow-connector {
display: flex;
align-items: center;
justify-content: center;
position: relative;
height: 100%;
}
.connector-line {
width: 100%;
height: 2px;
background: var(--border-color);
position: relative;
}
.connector-pulse {
position: absolute;
top: 50%;
left: 0;
width: 8px;
height: 8px;
border-radius: var(--radius-full);
background: var(--primary);
box-shadow: 0 0 10px var(--primary);
transform: translateY(-50%);
animation: flow-pulse 1.8s infinite cubic-bezier(0.4, 0, 0.2, 1);
}
.flow-connector:nth-child(4) .connector-pulse {
animation-delay: 0.9s;
}
@keyframes flow-pulse {
0% { left: 0%; opacity: 0; transform: translateY(-50%) scale(0.6); }
20% { opacity: 1; transform: translateY(-50%) scale(1.1); }
80% { opacity: 1; transform: translateY(-50%) scale(1.1); }
100% { left: 100%; opacity: 0; transform: translateY(-50%) scale(0.6); }
}
/* Tabs & Deep Dive Viewers */
.viewer-tabs {
display: flex;
gap: 8px;
border-bottom: 1px solid var(--border-color);
padding-bottom: 12px;
margin-top: 4px;
}
.viewer-tab-btn {
padding: 6px 14px;
background: transparent;
border: 1px solid transparent;
border-radius: var(--radius-sm);
color: var(--text-secondary);
font-size: 12px;
font-weight: 600;
cursor: pointer;
transition: all 0.2s ease;
}
.viewer-tab-btn:hover {
color: var(--text-primary);
background: var(--bg-card-hover);
}
.viewer-tab-btn.active {
color: var(--primary);
background: rgba(56, 189, 248, 0.1);
border-color: var(--border-highlight);
}
.tab-content-panel {
display: flex;
flex-direction: column;
gap: 14px;
}
.narrative-box {
background: rgba(0, 0, 0, 0.15);
border-radius: var(--radius-md);
padding: 14px 16px;
border: 1px solid var(--border-color);
font-size: 13px;
color: var(--text-secondary);
line-height: 1.6;
}
.narrative-box strong {
color: var(--text-primary);
}
.example-callout {
display: flex;
align-items: flex-start;
gap: 10px;
background: rgba(56, 189, 248, 0.05);
border-left: 3px solid var(--primary);
padding: 10px 14px;
border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
font-size: 12px;
color: var(--text-secondary);
}
.example-icon {
color: var(--primary);
font-weight: bold;
}
/* Code / Spec Inspector View */
.code-inspector {
background: #090d16;
border-radius: var(--radius-md);
border: 1px solid var(--border-color);
overflow: hidden;
font-family: var(--font-mono);
font-size: 12px;
}
.code-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 8px 14px;
background: rgba(255, 255, 255, 0.03);
border-bottom: 1px solid var(--border-color);
color: var(--text-muted);
font-size: 11px;
}
.code-content {
padding: 14px;
color: #e2e8f0;
line-height: 1.6;
overflow-x: auto;
white-space: pre;
}
.code-content .kw { color: #f472b6; }
.code-content .fn { color: #60a5fa; }
.code-content .str { color: #34d399; }
.code-content .num { color: #fbbf24; }
.code-content .cm { color: #64748b; font-style: italic; }
.code-content .diff-add { color: #34d399; background: rgba(52, 211, 153, 0.1); display: block; }
.code-content .diff-del { color: #f43f5e; background: rgba(244, 63, 94, 0.1); display: block; }
/* Interactive Sandbox (Dual Run / CodMod / DMA) */
.sandbox-card {
background: rgba(15, 23, 42, 0.6);
border: 1px solid var(--border-highlight);
border-radius: var(--radius-md);
padding: 16px;
display: flex;
flex-direction: column;
gap: 12px;
}
.sandbox-title {
display: flex;
justify-content: space-between;
align-items: center;
font-size: 13px;
font-weight: 700;
color: var(--text-primary);
}
.interactive-table {
width: 100%;
border-collapse: collapse;
font-size: 12px;
text-align: left;
}
.interactive-table th, .interactive-table td {
padding: 8px 12px;
border-bottom: 1px solid var(--border-color);
}
.interactive-table th {
color: var(--text-muted);
font-weight: 600;
text-transform: uppercase;
font-size: 10px;
letter-spacing: 0.05em;
}
.status-badge {
display: inline-flex;
align-items: center;
gap: 4px;
padding: 2px 8px;
border-radius: var(--radius-full);
font-size: 11px;
font-weight: 600;
}
.status-badge.match {
background: rgba(52, 211, 153, 0.15);
color: var(--accent-green);
border: 1px solid rgba(52, 211, 153, 0.3);
}
.status-badge.mismatch {
background: rgba(244, 63, 94, 0.15);
color: var(--accent-rose);
border: 1px solid rgba(244, 63, 94, 0.3);
}
/* Control Buttons */
.footer-bar {
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
gap: 12px;
padding-top: 10px;
border-top: 1px solid var(--border-color);
}
.btn-group {
display: flex;
align-items: center;
gap: 8px;
}
.btn {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 6px;
padding: 8px 16px;
font-family: inherit;
font-size: 13px;
font-weight: 600;
border-radius: var(--radius-md);
cursor: pointer;
transition: all 0.2s ease;
border: 1px solid var(--border-color);
background: var(--bg-secondary);
color: var(--text-primary);
user-select: none;
}
.btn:hover:not(:disabled) {
background: var(--bg-card-hover);
border-color: var(--border-highlight);
}
.btn:disabled {
opacity: 0.4;
cursor: not-allowed;
}
.btn-primary {
background: var(--primary);
color: var(--text-inverse);
border-color: var(--primary);
box-shadow: 0 0 15px var(--primary-glow);
}
.btn-primary:hover:not(:disabled) {
background: #0284c7;
border-color: #0284c7;
}
.btn-ghost {
background: transparent;
border-color: transparent;
color: var(--text-secondary);
}
.btn-ghost:hover:not(:disabled) {
color: var(--text-primary);
background: rgba(255, 255, 255, 0.05);
}
.source-credit {
font-size: 11px;
color: var(--text-muted);
}
/* Responsive adjustments */
@media (max-width: 768px) {
.track-selector {
grid-template-columns: 1fr;
}
.flow-scene {
grid-template-columns: 1fr;
gap: 12px;
}
.flow-connector {
height: 30px;
transform: rotate(90deg);
}
.orchestrator-spans {
grid-template-columns: 1fr;
}
.header-bar, .footer-bar {
flex-direction: column;
align-items: stretch;
}
}
</style>
</head>
<body>
<div class="container">
<!-- Header Bar -->
<div class="glass-panel header-bar">
<div class="brand-section">
<div class="tagline">
<span class="tagline-dot"></span>
<span>Google Cloud Modernization Framework</span>
</div>
<h1 class="main-title">Modernization Guided Walkthrough</h1>
</div>
<div class="theme-toggle-group">
<span class="status-badge match" id="step-counter">Step 1 of 6</span>
<button type="button" class="btn btn-ghost" id="theme-btn" title="Toggle Theme">🌓 Theme</button>
</div>
</div>
<!-- Track Selector -->
<div class="track-selector" role="tablist" aria-label="Modernization Pathways">
<button type="button" class="track-btn" data-track="mainframe" id="tab-mainframe">
<span class="track-icon">🏛️</span>
<div class="track-meta">
<span class="track-name">Mainframe Pathway</span>
<span class="track-desc">COBOL · Claims Engine · Dual Run</span>
</div>
</button>
<button type="button" class="track-btn active" data-track="app" id="tab-app">
<span class="track-icon">⚡</span>
<div class="track-meta">
<span class="track-name">Application Pathway</span>
<span class="track-desc">.NET / Java · CodMod · Cloud Run</span>
</div>
</button>
<button type="button" class="track-btn" data-track="data" id="tab-data">
<span class="track-icon">🗄️</span>
<div class="track-meta">
<span class="track-name">Database Pathway</span>
<span class="track-desc">SQL Server / Oracle · DMS · AlloyDB</span>
</div>
</button>
</div>
<!-- Stepper Navigation -->
<div class="glass-panel stepper-container">
<div class="stepper-nav" id="stepper-nav" role="navigation" aria-label="Step progress">
<!-- Injected dynamically -->
</div>
</div>
<!-- Antigravity Orchestrator Banner -->
<div class="orchestrator-banner" id="orchestrator-box">
<div class="orchestrator-header">
<div class="agent-identity">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="color:var(--secondary)"><circle cx="12" cy="12" r="3"></circle><circle cx="19" cy="5" r="2"></circle><circle cx="5" cy="19" r="2"></circle><path d="M10.4 21.9a10 10 0 0 0 9.9-9.9"></path><path d="M13.6 2.1a10 10 0 0 0-9.9 9.9"></path></svg>
<span>Antigravity Orchestration Layer</span>
<span class="agent-badge">Agentic Control Plane</span>
</div>
<span id="agent-active-skill" class="status-badge match">Active Skill: codmod-analyzer</span>
</div>
<div class="orchestrator-spans">
<div class="span-pill" id="span-plan">1. Discovery &amp; Planning</div>
<div class="span-pill" id="span-transform">2. Autonomous Transformation</div>
<div class="span-pill" id="span-validate">3. Continuous Validation</div>
</div>
<div style="font-size: 11px; color: var(--text-secondary);" id="agent-detail-text">
Antigravity orchestrates end-to-end task decomposition, skill invocation, and feedback loops across codebase transformations.
</div>
</div>
<!-- Stage Flow Scene -->
<div class="glass-panel stage-hero">
<div class="stage-title-wrap">
<div>
<div style="font-size: 11px; color: var(--text-muted); text-transform: uppercase; font-weight: 700; letter-spacing: 0.05em;" id="stage-step-num">Step 1</div>
<h2 class="stage-title-main" id="stage-heading">Assess · CodMod Application Advisor</h2>
</div>
<span class="stage-category-badge" id="stage-badge">Application Assessment</span>
</div>
<!-- 3-Box Flow Graph -->
<div class="flow-scene" id="flow-scene">
<div class="flow-card">
<span class="card-role-tag">1. Input Context</span>
<div class="card-main-text" id="flow-input-title">Portal source code</div>
<div class="card-sub-text" id="flow-input-sub">Legacy repo &amp; dependencies</div>
</div>
<div class="flow-connector">
<div class="connector-line"></div>
<div class="connector-pulse"></div>
</div>
<div class="flow-card center-actor">
<span class="card-role-tag" id="flow-actor-role">Active Engine</span>
<div class="card-main-text" id="flow-actor-title">CodMod Modernization Advisor</div>
<div class="card-sub-text" id="flow-actor-sub">Rule parsing &amp; target blueprints</div>
</div>
<div class="flow-connector">
<div class="connector-line"></div>
<div class="connector-pulse"></div>
</div>
<div class="flow-card">
<span class="card-role-tag">3. Generated Artifact</span>
<div class="card-main-text" id="flow-output-title">Modernization Blueprint</div>
<div class="card-sub-text" id="flow-output-sub">Ordered task plan &amp; APIs</div>
</div>
</div>
<!-- Viewer Tabs -->
<div class="viewer-tabs">
<button type="button" class="viewer-tab-btn active" data-vtab="narrative">Overview &amp; Architecture</button>
<button type="button" class="viewer-tab-btn" data-vtab="code">Artifact / Code Inspection</button>
<button type="button" class="viewer-tab-btn" data-vtab="sandbox" id="tab-btn-sandbox">Interactive Simulator</button>
</div>
<!-- Tab 1: Narrative -->
<div class="tab-content-panel" id="panel-narrative">
<div class="narrative-box" id="narrative-text">
CodMod analyzes the monolithic .NET Framework / Java code structure, identifying obsolete API usages, tight coupling to Windows-specific libraries, and external connection strings.
</div>
<div class="example-callout">
<span class="example-icon">💡</span>
<span id="example-text">Example: Identify legacy WCF endpoints and SQL Server connections requiring conversion to REST and AlloyDB.</span>
</div>
</div>
<!-- Tab 2: Code / Spec Inspector -->
<div class="tab-content-panel" id="panel-code" style="display: none;">
<div class="code-inspector">
<div class="code-header">
<span id="code-filename">modernization-spec.yaml</span>
<span id="code-lang-tag">YAML / SPEC</span>
</div>
<div class="code-content" id="code-view-content"></div>
</div>
</div>
<!-- Tab 3: Interactive Sandbox -->
<div class="tab-content-panel" id="panel-sandbox" style="display: none;">
<div class="sandbox-card" id="sandbox-container">
<!-- Dynamic sandbox depending on step -->
</div>
</div>
</div>
<!-- Footer Navigation -->
<div class="glass-panel footer-bar">
<div class="btn-group">
<button type="button" class="btn" id="btn-prev">← Previous</button>
<button type="button" class="btn btn-primary" id="btn-next">Next Step →</button>
<button type="button" class="btn btn-ghost" id="btn-autoplay">▶ Auto-Play</button>
</div>
<div class="source-credit" id="source-citation">
Source: Google Cloud Modernization Framework (Slides 14–21)
</div>
</div>
</div>
<script>
(() => {
// Model Data for Modernization Pathways
const pathways = {
mainframe: {
name: "Mainframe Pathway",
steps: [
{
phase: "Discover",
actor: "Modernize Hub",
role: "ESTATE DISCOVERY",
input: "Mainframe Core Estate",
inputSub: "COBOL, JCL, CICS, VSAM / DB2",
output: "Candidate Workload Assessment",
outputSub: "Priority score & dependency graph",
detail: "Modernize Hub inventories legacy mainframe workloads, analyzes code volume, transactions per second, and recommends starting with bounded batch or claims calculation routines.",
example: "Identify the high-volume claims pricing and deduction engine as candidate #1 for containerized rewrite.",
skill: "estate-inventory-scanner",
span: "plan",
slide: "4–5",
codeFile: "estate-inventory.json",
codeLang: "JSON",
codeSnippet: `{\n <span class="str">"workload"</span>: <span class="str">"CLAIMS_PRICING_ENGINE"</span>,\n <span class="str">"linesOfCode"</span>: <span class="num">142850</span>,\n <span class="str">"subroutines"</span>: [<span class="str">"CLM9000"</span>, <span class="str">"CLM9001"</span>, <span class="str">"POL_VALIDATE"</span>],\n <span class="str">"complexity"</span>: <span class="str">"HIGH"</span>,\n <span class="str">"targetRecommendation"</span>: <span class="str">"Cloud Run / Go Microservice"</span>\n}`,
sandboxType: "none"
},
{
phase: "Assess",
actor: "MAT (Mainframe Assessment Tool)",
role: "BUSINESS RULE EXTRACTION",
input: "Legacy COBOL Source Code",
inputSub: "COPYBOOKs & Procedural Logic",
output: "Parsed Business Logic Rules",
outputSub: "Rule definitions & edge condition matrix",
detail: "MAT parses legacy COBOL statements (EVALUATE, COMPUTE, PERFORM) and extracts strict business logic, removing hardware-tied assembler details.",
example: "Extract rule determining deductible waiver on catastrophic threshold limits exceeding $10,000.",
skill: "cobol-rule-extractor",
span: "plan",
slide: "6–7",
codeFile: "CLM9000.CBL",
codeLang: "COBOL",
codeSnippet: `<span class="cm">* EXTRACTED FROM LEGACY CLAIMS CORE</span>\n<span class="kw">IDENTIFICATION DIVISION</span>.\n<span class="kw">PROGRAM-ID</span>. CLM9000.\n<span class="kw">PROCEDURE DIVISION</span>.\n <span class="kw">IF</span> CLAIM-AMOUNT > 10000 <span class="kw">AND</span> POLICY-TIER = <span class="str">'PLATINUM'</span>\n <span class="kw">MOVE</span> 0 <span class="kw">TO</span> DEDUCTIBLE-DUE\n <span class="kw">ELSE</span>\n <span class="kw">COMPUTE</span> DEDUCTIBLE-DUE = CLAIM-AMOUNT * 0.10\n <span class="kw">END-IF</span>.`,
sandboxType: "none"
},
{
phase: "Specify",
actor: "Mainframe Agents",
role: "PRD & SPECIFICATION",
input: "Extracted Business Logic",
inputSub: "Decision tables & data dictionaries",
output: "Modern PRD & Acceptance Tests",
outputSub: "Gherkin feature files & OpenAPI schema",
detail: "Mainframe agents transform raw business rules into unambiguous requirements, OpenAPI 3.1 contracts, and executable test specifications for modern engineering teams.",
example: "Convert COBOL decimal arithmetic quirks into IEEE floating-point / BigNumber decimal precision specs.",
skill: "spec-generator",
span: "plan",
slide: "7",
codeFile: "claims-calculation.feature",
codeLang: "Gherkin / Spec",
codeSnippet: `<span class="kw">Feature</span>: Claims Deductible Calculation\n\n <span class="kw">Scenario Outline</span>: Evaluate deductible for policy tiers\n <span class="kw">Given</span> a policy with tier <span class="str">"<tier>"</span>\n <span class="kw">When</span> claim amount is <span class="num"><amount></span>\n <span class="kw">Then</span> the deductible due should be <span class="num"><deductible></span>\n\n <span class="kw">Examples</span>:\n | tier | amount | deductible |\n | STANDARD | 900 | 90 |\n | PLATINUM | 12000 | 0 |`,
sandboxType: "none"
},
{
phase: "Rewrite",
actor: "Gemini CLI + Agents",
role: "CODE TRANSFORMATION",
input: "PRD & Cloud Architecture",
inputSub: "Spring Boot / Go target guidelines",
output: "Modern Microservice Code",
outputSub: "Idiomatic service & unit test suites",
detail: "Gemini CLI orchestrated with specialized modernization skills generates clean, cloud-native microservices matching legacy calculations with 100% precision.",
example: "Generate a Java 21 / Spring Boot service with BigInteger arithmetic for high-speed claims adjudication.",
skill: "cloud-code-transformer",
span: "transform",
slide: "6–7",
codeFile: "ClaimsEngineService.java",
codeLang: "Java",
codeSnippet: `<span class="kw">public class</span> <span class="fn">ClaimsEngineService</span> {\n <span class="kw">public</span> BigDecimal <span class="fn">calculateDeductible</span>(Claim claim) {\n <span class="kw">if</span> (claim.amount().compareTo(BigDecimal.valueOf(10000)) > 0 \n && claim.policy().isPlatinum()) {\n <span class="kw">return</span> BigDecimal.ZERO;\n }\n <span class="kw">return</span> claim.amount().multiply(BigDecimal.valueOf(0.10));\n }\n}`,
sandboxType: "none"
},
{
phase: "Move Data",
actor: "Mainframe Connector",
role: "PARALLEL DATA STREAMING",
input: "Mainframe VSAM / DB2 EBCDIC",
inputSub: "Packed decimal records",
output: "BigQuery / AlloyDB Data Store",
outputSub: "UTF-8 partitioned data lake",
detail: "Mainframe Connector streams and converts mainframe datasets directly into Google Cloud storage without exhausting mainframe MIPS or locking operational tables.",
example: "Stream 50 million historical claims records into BigQuery for analytics and AlloyDB for real-time lookups.",
skill: "mainframe-data-streamer",
span: "transform",
slide: "6–7",
codeFile: "connector-job.yaml",
codeLang: "YAML",
codeSnippet: `apiVersion: <span class="str">mainframe.google.com/v1</span>\nkind: <span class="fn">DataTransferJob</span>\nspec:\n source:\n dataset: <span class="str">"PROD.CLAIMS.VSAM.HIST"</span>\n ebcdicEncoding: <span class="str">"IBM-037"</span>\n target:\n alloyDbInstance: <span class="str">"claims-core-primary"</span>\n table: <span class="str">"claims_historical"</span>`,
sandboxType: "none"
},
{
phase: "Compare",
actor: "Dual Run",
role: "EQUIVALENCE TESTING",
input: "Live Workload Input Feeds",
inputSub: "Mirrored production transactions",
output: "Equivalence Audit Report",
outputSub: "Diff telemetry & edge-case fixes",
detail: "Dual Run sends identical transaction streams in parallel to both the Mainframe and the Google Cloud application, verifying bit-for-bit parity under live volume.",
example: "Catch a boundary condition discrepancy where zero-dollar claims were handled differently in the modern rewrite.",
skill: "dual-run-verifier",
span: "validate",
slide: "7–8",
codeFile: "dual-run-report.json",
codeLang: "JSON",
codeSnippet: `{\n <span class="str">"totalReplayed"</span>: <span class="num">250000</span>,\n <span class="str">"matches"</span>: <span class="num">249999</span>,\n <span class="str">"discrepancies"</span>: <span class="num">1</span>,\n <span class="str">"status"</span>: <span class="str">"ACTION_REQUIRED"</span>\n}`,
sandboxType: "dualrun"
},
{
phase: "Deliver",
actor: "Modern Cloud Native App",
role: "PRODUCTION CUTOVER",
input: "Validated App + Replicated Data",
inputSub: "100% equivalence verified",
output: "Target Cloud Service on GCP",
outputSub: "Auto-scaling Cloud Run & AlloyDB",
detail: "With zero divergence proven via Dual Run, the traffic router cuts over production traffic to Google Cloud, allowing progressive mainframe decommissioning.",
example: "Decommission 450 mainframe MIPS while improving peak claims calculation latency from 450ms to 24ms.",
skill: "production-cutover-manager",
span: "validate",
slide: "7–8",
codeFile: "cutover-status.json",
codeLang: "JSON",
codeSnippet: `{\n <span class="str">"trafficDistribution"</span>: { <span class="str">"googleCloud"</span>: <span class="num">1.00</span>, <span class="str">"mainframe"</span>: <span class="num">0.00</span> },\n <span class="str">"slaCompliance"</span>: <span class="str">"99.999%"</span>,\n <span class="str">"costReduction"</span>: <span class="str">"68% MIPS savings"</span>\n}`,
sandboxType: "none"
}
]
},
app: {
name: "Application Pathway",
steps: [
{
phase: "Discover",
actor: "Modernize Hub",
role: "PORTFOLIO DISCOVERY",
input: "Enterprise Application Repos",
inputSub: ".NET Framework & Java monoliths",
output: "Modernization Suitability Score",
outputSub: "Target container readiness",
detail: "Modernize Hub scans the application portfolio, cataloging framework versions (e.g. .NET Framework 4.7, Java 8, WebLogic) and architectural dependencies.",
example: "Flag customer portal monolith with 12 IIS-dependent services ready for containerization.",
skill: "app-portfolio-analyzer",
span: "plan",
slide: "4–5",
codeFile: "portfolio-scan.json",
codeLang: "JSON",
codeSnippet: `{\n <span class="str">"app"</span>: <span class="str">"CustomerPortal.Web"</span>,\n <span class="str">"framework"</span>: <span class="str">".NET Framework 4.8"</span>,\n <span class="str">"dependencies"</span>: [<span class="str">"System.Web"</span>, <span class="str">"WCF"</span>, <span class="str">"Windows Registry"</span>],\n <span class="str">"targetArchitecture"</span>: <span class="str">".NET 8 / Cloud Run"</span>\n}`,
sandboxType: "none"
},
{
phase: "Assess",
actor: "CodMod Advisor",
role: "APPLICATION ASSESSMENT",
input: "Portal Source Code & Configs",
inputSub: "web.config, *.csproj, solution files",
output: "Target Blueprint & Dependencies",
outputSub: "Breaking changes & migration recipe",
detail: "CodMod (Application Modernization Advisor) evaluates NuGet/Maven dependencies, proprietary APIs, and constructs a step-by-step migration blueprint.",
example: "Identify System.Web session state dependencies needing migration to Redis / Memorystore.",
skill: "codmod-analyzer",
span: "plan",
slide: "17–21",
codeFile: "CodModReport.md",
codeLang: "Markdown",
codeSnippet: `<span class="kw"># CodMod Modernization Plan</span>\n- <span class="str">[CRITICAL]</span> Replace \`System.Web.Session\` with Redis Distributed Cache.\n- <span class="str">[UPDATE]</span> Migrate \`web.config\` appSettings to \`appsettings.json\`.\n- <span class="str">[REFACTOR]</span> Convert WCF SOAP bindings to gRPC / REST WebAPI endpoints.`,
sandboxType: "none"
},
{
phase: "Plan",
actor: "Planning Agent + Skills",
role: "DESIGN & TASK BREAKDOWN",
input: "CodMod Assessment & Blueprint",
inputSub: "Micro-task dependency graph",
output: "Ordered Modernization Backlog",
outputSub: "Step-by-step refactoring tickets",
detail: "Antigravity Planning Agent creates structured transformation tickets with exact file paths, automated tests, and validation gates.",
example: "Sequence project upgrades: 1. Core library, 2. Auth middleware, 3. API controllers, 4. Health checks.",
skill: "task-planner",
span: "plan",
slide: "10, 14, 19",
codeFile: "migration-backlog.yaml",
codeLang: "YAML",
codeSnippet: `tasks:\n - id: <span class="str">task-01</span>\n title: <span class="str">"SDK Project File Upgrade"</span>\n target: <span class="str">"net8.0"</span>\n - id: <span class="str">task-02</span>\n title: <span class="str">"Migrate ASP.NET MVC Controllers to ASP.NET Core"</span>\n skills: [<span class="str">"dotnet-framework-to-core"</span>]`,
sandboxType: "none"
},
{
phase: "Transform",
actor: "Application Agent Skills",
role: "CODE TRANSFORMATION",
input: "Legacy Code + Task Plan",
inputSub: "ASP.NET MVC / Java EE files",
output: "Modern ASP.NET Core 8 / Java 21",
outputSub: "Clean, cross-platform code",
detail: "Specialized agent skills execute code refactoring in place, replacing deprecated namespaces with modern async/await patterns and dependency injection.",
example: "Refactor synchronous HttpHandlers into ASP.NET Core Minimal APIs with built-in telemetry.",
skill: "dotnet-transform-agent",
span: "transform",
slide: "10, 14, 19",
codeFile: "Program.cs",
codeLang: "C# (.NET 8)",
codeSnippet: `<span class="cm">// MODERNIZED .NET 8 MINIMAL API</span>\n<span class="kw">var</span> builder = WebApplication.<span class="fn">CreateBuilder</span>(args);\nbuilder.Services.<span class="fn">AddStackExchangeRedisCache</span>(options => {\n options.Configuration = builder.Configuration[<span class="str">"Redis:Host"</span>];\n});\n\n<span class="kw">var</span> app = builder.<span class="fn">Build</span>();\napp.<span class="fn">MapGet</span>(<span class="str">"/api/claims/{id}"</span>, <span class="kw">async</span> (string id, ClaimsService svc) => \n <span class="kw">await</span> svc.<span class="fn">GetClaimAsync</span>(id));\napp.<span class="fn">Run</span>();`,
sandboxType: "codmod"
},
{
phase: "Test",
actor: "Validation Agent",
role: "AUTOMATED TEST EXECUTION",
input: "Modernized Codebase",
inputSub: "Refactored code & unit suites",
output: "Test Results & Telemetry",
outputSub: "Code coverage & security report",
detail: "Validation agent runs unit, integration, and security scans (container vulnerability check) to ensure regression-free deployment.",
example: "Execute 1,240 automated test suites; automatically patch two broken mocked HTTP endpoints.",
skill: "automated-test-runner",
span: "validate",
slide: "10, 19",
codeFile: "test-summary.log",
codeLang: "Log",
codeSnippet: `[INFO] Running dotnet test /workspace/CustomerPortal.Tests\n[PASS] TestCustomerAuthWithClaimsBearer: PASSED (14ms)\n[PASS] TestClaimSubmissionCalculatesTotal: PASSED (22ms)\n[INFO] Test Run Successful. 1240 passed, 0 failed. Coverage: 94.2%`,
sandboxType: "none"
},
{
phase: "Deploy",
actor: "Cloud Run / GKE",
role: "PRODUCTION DEPLOYMENT",
input: "Tested Container Image",
inputSub: "OCI Artifact Registry Image",
output: "Scalable Cloud Run Service",
outputSub: "Cloud Armor + Global Load Balancer",
detail: "Deploy the modernized application as serverless container instances on Cloud Run with automated scale-to-zero and zero-downtime traffic splitting.",
example: "Deploy to Cloud Run across us-central1 and europe-west1 with Google Cloud Armor DDoS protection.",
skill: "cloud-deployer",
span: "validate",
slide: "16, 21",
codeFile: "service.yaml",
codeLang: "YAML",
codeSnippet: `apiVersion: <span class="str">serving.knative.dev/v1</span>\nkind: <span class="fn">Service</span>\nmetadata:\n name: <span class="str">customer-portal-api</span>\nspec:\n template:\n spec:\n containers:\n - image: <span class="str">gcr.io/my-proj/customer-portal:v2.0.0</span>\n resources:\n limits:\n memory: <span class="str">512Mi</span>\n cpu: <span class="str">"1.0"</span>`,
sandboxType: "none"
}
]
},
data: {
name: "Database Pathway",
steps: [
{
phase: "Discover",
actor: "Modernize Hub",
role: "DATABASE ESTATE SCAN",
input: "Enterprise Database Servers",
inputSub: "SQL Server 2012 / Oracle 11g instances",
output: "Database Assessment Summary",
outputSub: "Storage volume, procedures & compatibility",
detail: "Modernize Hub scans the relational database estate, evaluating schema complexity, proprietary PL/SQL or T-SQL constructs, and licensing liabilities.",
example: "Identify 14 legacy Oracle databases with proprietary stored procedures ripe for AlloyDB PostgreSQL modernization.",
skill: "database-estate-scanner",
span: "plan",
slide: "4, 14",
codeFile: "db-inventory.json",
codeLang: "JSON",
codeSnippet: `{\n <span class="str">"engine"</span>: <span class="str">"Oracle Database 11g Enterprise"</span>,\n <span class="str">"sizeGB"</span>: <span class="num">850</span>,\n <span class="str">"storedProcedures"</span>: <span class="num">142</span>,\n <span class="str">"targetEngine"</span>: <span class="str">"AlloyDB for PostgreSQL"</span>\n}`,
sandboxType: "none"
},
{
phase: "Assess",
actor: "DMA (Database Migration Assessment)",
role: "SCHEMA COMPATIBILITY AUDIT",
input: "DDL & Stored Procedures",
inputSub: "Packages, Triggers & Dialect code",
output: "Compatibility Matrix Report",
outputSub: "Auto-convertible vs Manual effort tasks",
detail: "DMA evaluates proprietary SQL features, complex packages, data types, and generates an automated translation breakdown.",
example: "Flag Oracle NVL2, DECODE, and cursor loops for Gemini-assisted conversion to PostgreSQL dialect.",
skill: "dma-compatibility-analyzer",
span: "plan",
slide: "4, 14",
codeFile: "dma-assessment.json",
codeLang: "JSON",
codeSnippet: `{\n <span class="str">"autoConvertibleObjects"</span>: <span class="num">88.5</span>,\n <span class="str">"geminiAssistedRefactors"</span>: [<span class="str">"PKG_POLICY_UTILS"</span>, <span class="str">"SP_RENEW_CLAIM"</span>],\n <span class="str">"targetCompatibility"</span>: <span class="str">"AlloyDB PostgreSQL 15"</span>\n}`,
sandboxType: "none"
},
{
phase: "Convert",
actor: "DMS + Gemini Assistance",
role: "SCHEMA & PROCEDURE CONVERSION",
input: "Source DDL & PL/SQL Code",
inputSub: "Oracle / T-SQL definitions",
output: "PostgreSQL DDL & Functions",
outputSub: "AlloyDB optimized schema",
detail: "Database Migration Service coupled with Gemini transforms proprietary stored procedures and triggers into idiomatic, performant PL/pgSQL.",
example: "Convert an Oracle recursive cursor into a PostgreSQL WITH RECURSIVE Common Table Expression.",
skill: "dms-schema-converter",
span: "transform",
slide: "12, 14",
codeFile: "converted_procedure.sql",
codeLang: "PL/pgSQL",
codeSnippet: `<span class="cm">-- GEMINI ASSISTED PL/PGSQL CONVERSION</span>\n<span class="kw">CREATE OR REPLACE FUNCTION</span> <span class="fn">sp_calculate_rebate</span>(p_claim_id <span class="kw">INT</span>)\n<span class="kw">RETURNS NUMERIC AS</span> $$\n<span class="kw">DECLARE</span>\n v_rebate <span class="kw">NUMERIC</span>(10,2);\n<span class="kw">BEGIN</span>\n <span class="kw">SELECT</span> COALESCE(amount * 0.05, 0)\n <span class="kw">INTO</span> v_rebate\n <span class="kw">FROM</span> claims\n <span class="kw">WHERE</span> claim_id = p_claim_id;\n \n <span class="kw">RETURN</span> v_rebate;\n<span class="kw">END</span>;\n$$ <span class="kw">LANGUAGE</span> plpgsql;`,
sandboxType: "dms"
},
{
phase: "Migrate",
actor: "DMS (Database Migration Service)",
role: "CONTINUOUS DATA REPLICATION",
input: "Source Database Data",
inputSub: "Initial snapshot + CDC binlog stream",
output: "Target AlloyDB Instance",
outputSub: "Real-time synchronized data",
detail: "DMS handles initial bulk snapshot load followed by sub-second Change Data Capture (CDC) replication with zero source downtime.",
example: "Migrate 850GB of core policy records with continuous replication latency staying below 120ms.",
skill: "dms-cdc-replicator",
span: "transform",
slide: "6, 12, 14",
codeFile: "dms-connection-profile.yaml",
codeLang: "YAML",
codeSnippet: `apiVersion: <span class="str">datamigration.cnrm.cloud.google.com/v1beta1</span>\nkind: <span class="fn">MigrationJob</span>\nspec:\n type: <span class="str">CONTINUOUS</span>\n source: <span class="str">"oracle-onprem-prod"</span>\n destination: <span class="str">"alloydb-cluster-primary"</span>\n state: <span class="str">RUNNING_CDC</span>`,
sandboxType: "none"
},
{
phase: "Connect",
actor: "Application Modernization",
role: "DATA ACCESS REFACTORING",
input: "AlloyDB Instance + Modern App",
inputSub: "Updated connection strings & drivers",
output: "Integrated Modern Stack",
outputSub: "Npgsql / JDBC PostgreSQL connectivity",
detail: "CodMod and agents update application data access layers (Entity Framework / Hibernate) from proprietary Oracle dialect to PostgreSQL dialect.",
example: "Update EF Core DbContext to use UseNpgsql() with AlloyDB Columnar Engine indexing.",
skill: "app-db-connector",
span: "transform",
slide: "21",
codeFile: "DbContextConfig.cs",
codeLang: "C#",
codeSnippet: `services.<span class="fn">AddDbContext</span>&lt;ClaimsDbContext&gt;(options =>\n options.<span class="fn">UseNpgsql</span>(Configuration.<span class="fn">GetConnectionString</span>(<span class="str">"AlloyDbClaims"</span>),\n o => o.<span class="fn">UseAdminDatabase</span>(<span class="str">"postgres"</span>)));`,
sandboxType: "none"
},
{
phase: "Validate",
actor: "Data Validation Framework",
role: "DATA INTEGRITY VERIFICATION",
input: "Source & Target Data Stores",
inputSub: "Row hashes & aggregate checksums",
output: "100% Data Integrity Certification",
outputSub: "Zero divergence audit report",
detail: "Automated verification pipelines validate row counts, decimal precision tolerances, and query results across source and target database instances.",
example: "Validate 14.8 million transaction records across 42 tables with checksum parity verified.",
skill: "data-checksum-verifier",
span: "validate",
slide: "12, 14, 21",
codeFile: "validation-summary.json",
codeLang: "JSON",
codeSnippet: `{\n <span class="str">"tablesValidated"</span>: <span class="num">42</span>,\n <span class="str">"recordsCompared"</span>: <span class="num">14820000</span>,\n <span class="str">"checksumMatchRate"</span>: <span class="num">1.00000</span>,\n <span class="str">"status"</span>: <span class="str">"VERIFIED"</span>\n}`,
sandboxType: "none"
},
{
phase: "Deliver",
actor: "AlloyDB / Cloud SQL",
role: "MANAGED DATABASE IN PRODUCTION",
input: "Migrated Database on GCP",
inputSub: "High availability multi-zone cluster",
output: "Modern Cloud Database Tier",
outputSub: "AlloyDB with 4x faster analytics queries",
detail: "Switch live application connection pools to AlloyDB for PostgreSQL, leveraging automatic memory management and columnar engine acceleration.",
example: "Experience 4x analytical query acceleration while eliminating proprietary database licensing fees.",
skill: "database-promoter",
span: "validate",
slide: "12, 14",
codeFile: "alloydb-cluster.json",
codeLang: "JSON",
codeSnippet: `{\n <span class="str">"clusterName"</span>: <span class="str">"claims-alloydb-prod"</span>,\n <span class="str">"haStatus"</span>: <span class="str">"MULTI_ZONE_ENABLED"</span>,\n <span class="str">"columnarEngine"</span>: <span class="str">"ENABLED"</span>,\n <span class="str">"readPoolInstances"</span>: <span class="num">3</span>\n}`,
sandboxType: "none"
}
]
}
};
// State
let currentTrack = "app";
let currentStep = 0;
let currentTab = "narrative";
let autoPlayTimer = null;
let dualRunFixed = false;
let dmsConverted = false;
// DOM Elements
const el = id => document.getElementById(id);
function renderStepper() {
const steps = pathways[currentTrack].steps;
const nav = el("stepper-nav");
nav.innerHTML = "";
steps.forEach((s, idx) => {
const node = document.createElement("div");
node.className = `step-node ${idx === currentStep ? "active" : ""} ${idx < currentStep ? "completed" : ""}`;
node.innerHTML = `
<div class="step-pill">${idx < currentStep ? "✓" : idx + 1}</div>
<div class="step-label">${idx + 1}. ${s.phase}</div>
`;
node.onclick = () => {
currentStep = idx;
renderStep();
};
nav.appendChild(node);
});
}
function renderOrchestrator(stepObj) {
el("agent-active-skill").textContent = `Active Skill: ${stepObj.skill}`;
// Spans
["plan", "transform", "validate"].forEach(span => {
const pill = el(`span-${span}`);
if (stepObj.span === span) {
pill.className = "span-pill current";
} else {
pill.className = "span-pill";
}
});
if (stepObj.span === "plan") {
el("agent-detail-text").textContent = "Antigravity decomposes estate discovery and architecture specifications into structured, reviewable milestones.";
} else if (stepObj.span === "transform") {
el("agent-detail-text").textContent = "Antigravity coordinates code rewrite and data transformation agents with specialized skills and contextual awareness.";
} else {
el("agent-detail-text").textContent = "Antigravity runs automated validation, test replays, and parity audits prior to target cloud deployment.";
}
}
function renderSandbox(stepObj) {
const container = el("sandbox-container");
const tabBtn = el("tab-btn-sandbox");
if (stepObj.sandboxType === "dualrun") {
tabBtn.style.display = "inline-block";
tabBtn.textContent = "Interactive Dual-Run Sandbox";
container.innerHTML = `
<div class="sandbox-title">
<span>Dual Run Equivalence Replay Simulator</span>
<span class="status-badge ${dualRunFixed ? "match" : "mismatch"}">${dualRunFixed ? "All Cases Matched" : "Discrepancy Detected"}</span>
</div>
<p style="font-size: 12px; color: var(--text-secondary);">
Dual Run replicates live transaction streams against both Mainframe and Google Cloud microservices to verify functional parity.
</p>
<table class="interactive-table">
<thead>
<tr>
<th>Test Case ID</th>
<th>Workload Payload</th>
<th>Mainframe Output</th>
<th>Modern Cloud App Output</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>CASE-101</code></td>
<td>Standard Claim ($900.00)</td>
<td><strong>$90.00</strong> deductible</td>
<td><strong>$90.00</strong> deductible</td>
<td><span class="status-badge match">✓ Matched</span></td>
</tr>
<tr>
<td><code>CASE-102</code></td>
<td>Boundary Threshold ($10,000.01 Platinum)</td>
<td><strong>$0.00</strong> deductible (waived)</td>
<td id="sandbox-result-val"><strong>${dualRunFixed ? "$0.00" : "$1,000.00"}</strong> ${dualRunFixed ? "deductible (waived)" : "deductible (mismatch)"}</td>
<td id="sandbox-result-badge"><span class="status-badge ${dualRunFixed ? "match" : "mismatch"}">${dualRunFixed ? "✓ Matched" : "✗ Mismatch"}</span></td>
</tr>
</tbody>
</table>
<div style="display:flex; justify-content:flex-end; gap:8px; margin-top:8px;">
<button type="button" class="btn ${dualRunFixed ? "btn-ghost" : "btn-primary"}" id="btn-fix-dualrun">
${dualRunFixed ? "✓ Boundary Rule Corrected & Verified" : "⚡ Apply Agent Rule Fix & Replay"}
</button>
</div>
`;
el("btn-fix-dualrun").onclick = () => {
dualRunFixed = true;
renderStep(false);
};
} else if (stepObj.sandboxType === "codmod") {
tabBtn.style.display = "inline-block";
tabBtn.textContent = "Interactive Refactor Sandbox";
container.innerHTML = `
<div class="sandbox-title">
<span>CodMod Automated Refactoring Engine</span>
<span class="status-badge match">Ready for compilation</span>
</div>
<p style="font-size: 12px; color: var(--text-secondary);">
Test the automated translation of legacy ASP.NET <code>System.Web</code> APIs to .NET 8 modern asynchronous handlers.
</p>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 10px;">
<div style="background: #090d16; padding: 10px; border-radius: 6px; font-family: monospace; font-size: 11px;">
<div style="color: #f43f5e; font-weight: bold; margin-bottom: 4px;">Legacy ASP.NET MVC (Source)</div>
<div style="color: #94a3b8;">
public ActionResult GetClaim(int id) {<br>
&nbsp;&nbsp;var claim = ClaimsDal.Fetch(id);<br>
&nbsp;&nbsp;Session["LastId"] = id;<br>
&nbsp;&nbsp;return Json(claim);<br>
}
</div>
</div>
<div style="background: #090d16; padding: 10px; border-radius: 6px; font-family: monospace; font-size: 11px;">
<div style="color: #34d399; font-weight: bold; margin-bottom: 4px;">Modern ASP.NET Core 8 (Target)</div>
<div style="color: #94a3b8;">
app.MapGet("/api/claims/{id}", async (int id, IClaimsRepo repo, IDistributedCache cache) => {<br>
&nbsp;&nbsp;await cache.SetStringAsync("LastId", id.ToString());<br>
&nbsp;&nbsp;return Results.Ok(await repo.GetAsync(id));<br>
});
</div>
</div>
</div>
<div style="display:flex; justify-content:flex-end; gap:8px; margin-top:8px;">
<button type="button" class="btn btn-primary" id="btn-run-tests">
⚡ Run Validation Test Suite
</button>
</div>
`;
el("btn-run-tests").onclick = () => {
alert("✅ All 12 unit and integration tests passed with 0 warnings!");
};
} else if (stepObj.sandboxType === "dms") {
tabBtn.style.display = "inline-block";
tabBtn.textContent = "Interactive SQL Conversion";
container.innerHTML = `
<div class="sandbox-title">
<span>DMS + Gemini Assisted SQL Translator</span>
<span class="status-badge ${dmsConverted ? "match" : ""}">AlloyDB Dialect</span>
</div>
<p style="font-size: 12px; color: var(--text-secondary);">
Convert Oracle PL/SQL stored procedures with proprietary packages into modern PostgreSQL / AlloyDB PL/pgSQL functions.
</p>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 10px;">
<div style="background: #090d16; padding: 10px; border-radius: 6px; font-family: monospace; font-size: 11px;">
<div style="color: #fbbf24; font-weight: bold; margin-bottom: 4px;">Oracle PL/SQL (Source)</div>
<div style="color: #94a3b8;">
NVL2(v_rebate, v_rebate, 0.00);<br>
DBMS_OUTPUT.PUT_LINE('Done');<br>
SYSDATE;
</div>
</div>
<div style="background: #090d16; padding: 10px; border-radius: 6px; font-family: monospace; font-size: 11px;">
<div style="color: #38bdf8; font-weight: bold; margin-bottom: 4px;">PostgreSQL / AlloyDB (Target)</div>
<div style="color: #94a3b8;">
CASE WHEN v_rebate IS NOT NULL THEN v_rebate ELSE 0.00 END;<br>
RAISE NOTICE 'Done';<br>
CURRENT_TIMESTAMP;
</div>
</div>
</div>
<div style="display:flex; justify-content:flex-end; gap:8px; margin-top:8px;">
<button type="button" class="btn btn-primary" id="btn-verify-sql">
⚡ Verify Syntax in PostgreSQL Parser
</button>
</div>
`;
el("btn-verify-sql").onclick = () => {
dmsConverted = true;
alert("✅ PL/pgSQL syntax validated successfully against AlloyDB PostgreSQL 15 engine!");
};
} else {
tabBtn.style.display = "none";
if (currentTab === "sandbox") {
switchTab("narrative");
}
}
}
function renderStep(resetTab = false) {
const list = pathways[currentTrack].steps;
const s = list[currentStep];
// Counter
el("step-counter").textContent = `Step ${currentStep + 1} of ${list.length}`;
el("stage-step-num").textContent = `Step ${currentStep + 1} · ${s.phase.toUpperCase()}`;
el("stage-heading").textContent = `${s.phase} · ${s.actor}`;
el("stage-badge").textContent = s.role;
// Flow Graph
el("flow-input-title").textContent = s.input;
el("flow-input-sub").textContent = s.inputSub;
el("flow-actor-role").textContent = "ACTIVE ENGINE / TOOL";
el("flow-actor-title").textContent = s.actor;
el("flow-actor-sub").textContent = s.role;
el("flow-output-title").textContent = s.output;
el("flow-output-sub").textContent = s.outputSub;
// Narrative
el("narrative-text").innerHTML = s.detail;
el("example-text").textContent = s.example;
// Code Inspector
el("code-filename").textContent = s.codeFile;
el("code-lang-tag").textContent = s.codeLang;
el("code-view-content").innerHTML = s.codeSnippet;
// Citation
el("source-citation").textContent = `Source: Google Cloud Modernization Framework (Slide ${s.slide}). Interactive execution model.`;
// Buttons
el("btn-prev").disabled = currentStep === 0;
el("btn-next").disabled = currentStep === list.length - 1;
renderStepper();
renderOrchestrator(s);
renderSandbox(s);
if (resetTab && currentTab === "sandbox" && s.sandboxType === "none") {
switchTab("narrative");
}
}
function switchTab(tabName) {
currentTab = tabName;
document.querySelectorAll(".viewer-tab-btn").forEach(btn => {
btn.classList.toggle("active", btn.dataset.vtab === tabName);
});
el("panel-narrative").style.display = tabName === "narrative" ? "flex" : "none";
el("panel-code").style.display = tabName === "code" ? "flex" : "none";
el("panel-sandbox").style.display = tabName === "sandbox" ? "flex" : "none";
}
// Setup Event Listeners
document.querySelectorAll(".track-btn").forEach(btn => {
btn.onclick = () => {
document.querySelectorAll(".track-btn").forEach(b => b.classList.remove("active"));
btn.classList.add("active");
currentTrack = btn.dataset.track;
currentStep = 0;
dualRunFixed = false;
dmsConverted = false;
renderStep(true);
};
});
document.querySelectorAll(".viewer-tab-btn").forEach(btn => {
btn.onclick = () => {
switchTab(btn.dataset.vtab);
};
});
el("btn-prev").onclick = () => {
if (currentStep > 0) {
currentStep--;
renderStep();
}
};
el("btn-next").onclick = () => {
if (currentStep < pathways[currentTrack].steps.length - 1) {
currentStep++;
renderStep();
}
};
// Auto-Play Feature
el("btn-autoplay").onclick = () => {
if (autoPlayTimer) {
clearInterval(autoPlayTimer);
autoPlayTimer = null;
el("btn-autoplay").textContent = "▶ Auto-Play";
el("btn-autoplay").classList.remove("btn-primary");
} else {
el("btn-autoplay").textContent = "⏸ Pause";
el("btn-autoplay").classList.add("btn-primary");
autoPlayTimer = setInterval(() => {
if (currentStep < pathways[currentTrack].steps.length - 1) {
currentStep++;
renderStep();
} else {
clearInterval(autoPlayTimer);
autoPlayTimer = null;
el("btn-autoplay").textContent = "▶ Auto-Play";
el("btn-autoplay").classList.remove("btn-primary");
}
}, 3500);
}
};
// Theme Toggle
el("theme-btn").onclick = () => {
const current = document.documentElement.getAttribute("data-theme");
const next = current === "light" ? "dark" : "light";
document.documentElement.setAttribute("data-theme", next);
};
// Keyboard navigation
window.addEventListener("keydown", (e) => {
if (e.key === "ArrowRight") {
if (currentStep < pathways[currentTrack].steps.length - 1) {
currentStep++;
renderStep();
}
} else if (e.key === "ArrowLeft") {
if (currentStep > 0) {
currentStep--;
renderStep();
}
} else if (e.key === " ") {
e.preventDefault();
el("btn-autoplay").click();
}
});
// Initial render
renderStep();
})();
</script>
</body>
</html>