Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
22dd52f
feat(gcp-to-aws): decision report — shared exec-summary core, rendere…
Jul 24, 2026
adbe9a5
fix(gcp-to-aws): bandit nosec annotations on decide asserter subproce…
Jul 24, 2026
1ba9ffb
fix(gcp-to-aws): inline decision-mode overrides in report core (Grok …
Jul 24, 2026
f4bc5bf
fix(gcp-to-aws): restore readable report layout
Jul 24, 2026
b57728e
fix(gcp-to-aws): strengthen executive summary hierarchy
Jul 24, 2026
e1a7758
fix(gcp-to-aws): correct cost scope and effort sizing
Jul 24, 2026
3bd3292
feat(gcp-to-aws): report readability conventions — numeric alignment,…
Jul 24, 2026
4ff2531
feat(gcp-to-aws): hero-first opening, type scale, structure-is-inform…
Jul 24, 2026
c88d424
feat(gcp-to-aws): pin WCAG AA contrast floor + interaction discipline…
Jul 24, 2026
27aa5dd
feat(gcp-to-aws): report style conventions — intensifier + slash-date…
Jul 24, 2026
5caccbd
feat(gcp-to-aws): remove effort-hours; timelines become stage sequenc…
Jul 25, 2026
80cace8
feat(gcp-to-aws): scenario_deltas — itemize what Premium/Optimized co…
Jul 26, 2026
66567cc
feat(gcp-to-aws): track-scoped outcomes — a failing secondary track d…
Jul 27, 2026
884a1f3
Merge branch 'main' into feat/decision-report-core
leon1418 Aug 4, 2026
ed7d923
Merge branch 'main' into feat/decision-report-core
herosjourney Aug 13, 2026
56c0e3c
Merge branch 'main' into feat/decision-report-core
leon1418 Aug 13, 2026
560b50b
Merge branch 'main' into feat/decision-report-core
leon1418 Aug 13, 2026
32fa2c8
Merge branch 'main' into feat/decision-report-core
leon1418 Aug 13, 2026
ef0c925
Merge branch 'feat/decision-gate' of https://github.com/herosjourney/…
Aug 13, 2026
6bb327f
Merge branch 'main' of https://github.com/awslabs/startups into fix18…
Aug 13, 2026
e92b766
fix(aws-startup-advisor): sync the decision-report changes into the a…
Aug 13, 2026
116cdcc
Merge branch 'main' into feat/decision-report-core
leon1418 Aug 14, 2026
de0dfe3
Merge branch 'main' of https://github.com/awslabs/startups into fix18…
Aug 14, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions advisor/plugins/aws-startup-advisor/fixtures/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ python3 scripts/validate-migration-report.py \
--estimation-ai fixtures/estimation-ai-reference.json
```

`estimation-*-reference.json` are trimmed snapshots aligned with the HTML fixture. Together they exercise security-baseline cross-checks, the security teaser, the verdict banner, and combined-TCO (`exec-tco`) requirements.
`estimation-*-reference.json` are trimmed snapshots aligned with the HTML fixture. Together they exercise security-baseline cross-checks, the security teaser, the verdict banner, and combined AWS monthly run-rate (`exec-tco`, legacy ID) requirements.

## Regression stub

Expand All @@ -31,10 +31,10 @@ python3 scripts/validate-migration-report.py \

The fixture is also the worked example for the readability rules the validator now enforces (not just documents):

- **No numeric "Section N" headings.** Customer-facing `<h2>`/`<h3>` headings use plain titles (e.g. "Total Cost of Ownership", not "Section 1 — …"). The table of contents carries structure: executive sections in an ordered list, appendices in a separate lettered list to avoid double-numbering.
- **No numeric "Section N" headings.** Customer-facing `<h2>`/`<h3>` headings use plain titles (e.g. "Estimated AWS Monthly Run Rate", not "Section 1 — …"). The table of contents carries structure: executive sections in an ordered list, appendices in a separate lettered list to avoid double-numbering.
- **No internal scoring trace.** Per-cluster mapping rationale lives in a collapsible `<details class="why">` ("Why this mapping?") block, never a bare `Rubric:` line.
- **Security teaser up top, full detail in the appendix.** `exec-security-teaser` carries a 2–3 line summary; the full control table and gap analysis are `appendix-security` / `appendix-security-gap`.
- **Consistent money formatting** (whole-dollar monthly figures; cents only where sub-dollar precision matters) and **expanded acronyms** (glossary in the assumptions section).
- **Consistent money formatting** (whole-dollar monthly figures; cents only where sub-dollar precision matters) and **expanded acronyms** (bordered two-column glossary table in the assumptions section).
- **Accessible tables and diagram**: `<caption>` + `scope="col"` on tables; the ASCII architecture diagram is wrapped in a `<figure role="img">` with an `aria-label` text alternative and a `<figcaption>`.
- **Configuration provenance (`appendix-config`).** Four-column table: Question/assumption, Your choice, Source, Design consequence — populated from `preferences.json` `prompt` and `design_consequence` fields (see `references/shared/schema-preferences.md`).
- **Ordered action lists.** `Key decisions ahead` and `Next steps` in `decision-summary` use `<ol>`, not `<ul>`.
Expand All @@ -45,4 +45,4 @@ A few sections carry `appendix-` IDs but render in the executive flow by design

## What REPORT_OK means

`REPORT_OK | structure=complete` means required sections, TOC links, appendix depth, readability rules, and artifact-driven cost/TCO checks passed. It does **not** verify that every dollar figure in the HTML matches the JSON — verify numerics manually or in a future accuracy gate before executive sign-off.
`REPORT_OK | structure=complete` means required sections, TOC links, appendix depth, readability rules, and artifact-driven cloud-service run-rate checks passed. It does **not** verify that every dollar figure in the HTML matches the JSON — verify numerics manually or in a future accuracy gate before executive sign-off.
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,16 @@
"free_controls": 0.5
}
}
},
"scenario_deltas": {
"premium": [
"RDS Multi-AZ instead of single-AZ (+$21/mo) - removes the single-AZ assumption",
"Fargate provisioned headroom, 2x task count (+$12/mo)"
],
"optimized": [
"Drops NAT Gateway (-$18/mo) - tasks move to public subnets or VPC endpoints; security-posture change, not just savings",
"Assumes 1-year Compute Savings Plan (-$12/mo) - requires an upfront commitment decision"
]
}
},
"current_costs": {
Expand All @@ -24,19 +34,51 @@
"outcome": "conditional_go",
"outcome_label": "Go, with conditions",
"conditions": [
"Confirm database availability Multi-AZ was assumed, not confirmed (roughly 2x database cost factor)"
"Confirm database availability \u2014 Multi-AZ was assumed, not confirmed (roughly 2x database cost factor)"
],
"decision_basis": {
"measured": ["GCP billing baseline ($165/mo infra)", "Cloud SQL disk size (10 GB)"],
"assumed": ["Database availability (Multi-AZ default)", "Cloud Run traffic (24/7 default)"],
"measured": [
"GCP billing baseline ($165/mo infra)",
"Cloud SQL disk size (10 GB)"
],
"assumed": [
"Database availability (Multi-AZ default)",
"Cloud Run traffic (24/7 default)"
],
"unknown": []
},
"would_flip_if": [
"Single-AZ acceptable: AWS estimate drops further, strengthens go",
"BigQuery must cut over in the same window: defer for specialist evidence"
],
"migrate_if": ["unified AWS operations"],
"stay_if": ["BigQuery must cut over in the same window as app infra and cannot use a phased analytics track"]
"migrate_if": [
"unified AWS operations"
],
"stay_if": [
"BigQuery must cut over in the same window as app infra and cannot use a phased analytics track"
],
"track_outcomes": [
{
"track": "compute_database",
"outcome": "go",
"note": "Fargate + RDS; the phased backbone"
},
{
"track": "ai_text",
"outcome": "go",
"note": "Nova Lite via provider adapter"
},
{
"track": "ai_image",
"outcome": "conditional_go",
"note": "Keeps current provider via the adapter until the image-quality eval passes; does not gate other tracks"
},
{
"track": "analytics",
"outcome": "defer_for_evidence",
"note": "BigQuery - specialist engagement, parallel track"
}
]
},
"cost_comparison": {
"option_b_balanced": {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"migration_id": "0723-1900",
"last_updated": "2026-07-23T19:22:00Z",
"current_phase": "complete",
"run_mode": "decide",
"phases": {
"discover": "completed",
"clarify": "completed",
"design": "completed",
"estimate": "completed",
"workshop": "completed",
"generate": "pending",
"feedback": "completed"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Migration Decision — GCP to AWS

**Verdict: Go, with conditions** (phased migration · moderate complexity · medium confidence)

Proceed with a phased migration on the Balanced cost scenario once the availability assumption is confirmed.

## Costs (estimated monthly)

| Tier | Est. Monthly AWS |
| -------------------------------------------- | ---------------- |
| Premium | $212/mo |
| **Balanced** (compare GCP to this row first) | **$155/mo** |
| Optimized | $118/mo |

GCP baseline: estimated from resource configs (±20–30%, standing charges only). The stated $1K–$5K/mo spend band measures the whole bill and is not directly comparable.

## Migrate if / Stay if

- **Migrate if:** you want managed compute without Kubernetes operations; consolidating AI usage onto Bedrock matters this year.
- **Stay if:** your GCP committed-use discounts run through 2027.

## Timeline

Phased in dependency order if you execute — long pole: database migration, then cutover in a maintenance window (medium-complexity drivers; no week estimates — uncalibrated).

## Top risks

- Availability posture assumed single-AZ — confirm before cutover sizing.
- BigQuery deferred to specialist engagement; excluded from combined totals.

## What this rests on

Region, database size, and model detection extracted from Terraform and code; availability defaulted to single-AZ per dev-tier signals. Cached pricing dated 2026-07 (±5–10% infra).

---

**Ready to execute?** Say "generate the Terraform and migration scripts" for the full execution pack. _Draft for review._
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>GCP to AWS Migration Assessment — Decision Report</title>
<style>
:root {
--green: #1a7f37; --blue: #0969da; --amber: #bf8700; --red: #cf222e;
--purple: #8250df; --bg: #f6f8fa; --surface: #fff; --text: #1f2328;
--muted: #656d76; --border: #d0d7de; --aws: #232f3e;
}
* { box-sizing: border-box; }
body {
margin: 0; background: var(--bg); color: var(--text); line-height: 1.55;
font: 15px -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
}
.report { max-width: 1040px; margin: 0 auto; padding: 2rem 1.5rem 4rem; }
h1 { font-size: 1.85rem; margin-bottom: 0.25rem; border-bottom: 3px solid #ff9900; padding-bottom: 0.5rem; }
h2 { font-size: 1.3rem; margin-top: 0; border-bottom: 1px solid var(--border); padding-bottom: 0.45rem; }
h3 { font-size: 1.05rem; margin: 1.1rem 0 0.4rem; color: #424a53; }
p, ul, ol { margin-top: 0.45rem; margin-bottom: 0.8rem; }
section {
background: var(--surface); border: 1px solid var(--border); border-radius: 8px;
padding: 1.25rem 1.5rem; margin-bottom: 1rem; scroll-margin-top: 1rem;
}
.verdict-headline {
display: inline-block; margin: 0.35rem 0 0.1rem; padding-bottom: 0.15rem;
border-bottom: 3px solid #0d7377; font-size: 2rem; font-weight: 700;
letter-spacing: -0.02em;
}
.verdict-meta { color: var(--muted); font-size: 0.92rem; margin: 0.2rem 0 0.6rem; }
.verdict { background: #dafbe1; border: 1px solid #4ac26b; border-left: 4px solid var(--green); border-radius: 6px; padding: 0.85rem 1rem; margin: 0.85rem 0; }
.savings { color: var(--green); font-weight: 700; }
.metrics {
display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
gap: 0.75rem; margin: 0.85rem 0;
}
.metric {
background: #f8f9fa; border: 1px solid var(--border); border-radius: 8px;
padding: 0.85rem 1rem;
}
.metric strong { display: block; font-size: 1.45rem; line-height: 1.2; }
.metric span { color: var(--muted); font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.02em; }
.metric small { display: block; color: var(--muted); font-size: 0.78rem; margin-top: 0.2rem; }
table { width: 100%; border-collapse: collapse; margin: 0.75rem 0 1rem; background: #fff; font-size: 0.88rem; }
th, td { border: 1px solid var(--border); padding: 0.45rem 0.65rem; text-align: left; vertical-align: top; }
th { background: #f6f8fa; font-weight: 600; }
tbody tr:nth-child(even) td { background: #fafbfc; }
td.num, th.num { text-align: right; font-variant-numeric: tabular-nums; }
.metric-hero { background: #fff; border: 2px solid #0d7377; }
.metric-hero strong { font-size: 1.9rem; }
.chip-warn { display: inline-block; background: #fff8c5; border: 1px solid #d4a72c; border-radius: 2rem; padding: 0.05rem 0.55rem; font-size: 0.72rem; font-weight: 600; }
.badge { display: inline-block; padding: 0.2rem 0.65rem; border-radius: 2rem; font-size: 0.78rem; font-weight: 600; }
.badge-impact-critical { background: #fce8e6; color: #c5221f; }
.badge-impact-high { background: #fef7e0; color: #b05a00; }
.badge-like-low { background: #f1f3f4; color: #545b64; }
.badge-like-medium { background: #fef7e0; color: #b05a00; }
h2 .toplink { float: right; font-size: 0.75rem; font-weight: 400; color: #656d76; text-decoration: none; }
@media print { h2 .toplink { display: none; } }
.toc {
background: #fff; border: 1px solid var(--border); border-radius: 8px;
padding: 1rem 1.5rem; margin-bottom: 1rem;
}
.toc a { display: inline-block; margin: 0.2rem 0.65rem 0.2rem 0; color: var(--blue); text-decoration: none; }
.toc a:hover { text-decoration: underline; }
a:focus-visible, summary:focus-visible { outline: 3px solid #54aeff; outline-offset: 2px; border-radius: 2px; }
.callout { padding: 0.85rem 1rem; border-radius: 6px; margin: 0.85rem 0; font-size: 0.92rem; }
.callout-warning { background: #fff8c5; border: 1px solid #d4a72c; }
.callout-info { background: #ddf4ff; border: 1px solid #54aeff; }
.callout-ok { background: #dafbe1; border: 1px solid #4ac26b; }
.appendix-header { background: var(--aws); color: #fff; border-radius: 8px; padding: 1rem 1.5rem; margin: 2rem 0 1rem; }
footer { text-align: center; color: var(--muted); font-size: 0.8rem; margin-top: 2rem; padding-top: 1rem; border-top: 1px solid var(--border); }
@media (max-width: 700px) {
.report { padding: 1rem 0.75rem 2rem; }
section { padding: 1rem; }
.metrics { grid-template-columns: 1fr; }
.toc a { display: block; }
table { display: block; overflow-x: auto; }
}
@media print {
body { background: #fff; }
.report { max-width: none; padding: 0; }
.metric, .callout, tr { break-inside: avoid; }
.appendix { break-before: page; }
}
</style>
</head>
<body>
<div class="report"><div class="executive-summary">
<section id="decision-summary">
<h2>Migration Decision Summary <a class="toplink" href="#toc">↑ contents</a></h2>
<p class="verdict-headline">Go, with conditions</p>
<p class="verdict-meta">Execution shape: Phased migration · Complexity: Moderate</p>
<div class="metrics" aria-label="Decision highlights">
<div class="metric metric-hero"><span>Balanced estimate</span><strong>Est. $155/mo</strong><small>Primary AWS comparison scenario</small></div>
<div class="metric metric-hero"><span>Shape if you execute</span><strong>Phased</strong><small>Long pole: database migration (medium-complexity drivers)</small></div>
<div class="metric"><span>Decision status</span><strong>Conditional go</strong><small>Confirm availability before cutover</small></div>
</div>
<div class="callout-info">💡 <strong>AWS Activate Founders:</strong> up to $5,000 in credits — <a href="https://aws.amazon.com/startups/credits/">Apply for AWS Activate credits</a> before incurring eligible charges.</div>
<p>Confidence: Medium — full basis in <a href="#exec-assumptions">What This Assessment Rests On</a>.</p>
<div class="verdict"><strong>Recommendation:</strong> Proceed with a phased migration on the Balanced cost scenario once the availability assumption is confirmed.</div>
<h3>Migrate if</h3>
<ul><li>You want managed compute without Kubernetes operations</li><li>Consolidating AI usage onto Bedrock matters this year</li></ul>
<h3>Stay if</h3>
<ul><li>Your GCP committed-use discounts run through 2027</li></ul>
</section>
<nav class="toc" id="toc">
<a href="#decision-summary">Migration Decision Summary</a>
<a href="#exec-services">Current Stack</a>
<a href="#exec-costs">Cost Comparison</a>
<a href="#exec-timeline">Timeline</a>
<a href="#exec-risks">Top Risks</a>
<a href="#exec-assumptions">What This Assessment Rests On</a>
<a href="#decision-cta">Ready to Execute?</a>
</nav>
<section id="exec-services">
<h2>Current Stack <a class="toplink" href="#toc">↑ contents</a></h2>
<table><caption>Primary GCP services detected</caption><thead><tr><th scope="col">Service</th><th scope="col">Type</th></tr></thead>
<tbody><tr><td>Cloud Run</td><td>compute</td></tr><tr><td>Cloud SQL (PostgreSQL 15)</td><td>database</td></tr><tr><td>Cloud Storage</td><td>storage</td></tr></tbody></table>
</section>
<section id="exec-costs">
<h2>Cost Comparison <a class="toplink" href="#toc">↑ contents</a></h2>
<table><caption>Estimated monthly costs</caption><thead><tr><th scope="col">Tier</th><th scope="col" class="num">Est. Monthly AWS</th></tr></thead>
<tbody><tr><td>Premium</td><td class="num">Est. $212/mo</td></tr><tr><td><strong>Balanced</strong> (compare GCP to this row first)</td><td class="num"><strong>Est. $155/mo</strong></td></tr><tr><td>Optimized</td><td class="num">Est. $118/mo</td></tr></tbody></table>
<p><span class="chip-warn">⚠ not comparable</span> Your GCP baseline: estimated from resource configs (±20–30%, standing charges only). Your stated spend band ($1K–$5K/mo) measures your whole bill and is not directly comparable to the AWS figure above.</p>
</section>
<section id="exec-timeline">
<h2>Timeline <a class="toplink" href="#toc">↑ contents</a></h2>
<p>Phased in dependency order if you execute — long pole: database migration, then cutover in a maintenance window (medium-complexity drivers; the plugin quotes no week estimates — uncalibrated).</p>
</section>
<section id="exec-risks">
<h2>Top Risks <a class="toplink" href="#toc">↑ contents</a></h2>
<table><caption>Highest-severity migration risks</caption>
<thead><tr><th scope="col">Risk</th><th scope="col">Impact</th><th scope="col">Likelihood</th><th scope="col">Mitigation</th></tr></thead>
<tbody>
<tr><td>Availability posture assumed single-AZ</td><td><span class="badge badge-impact-high">High</span></td><td><span class="badge badge-like-medium">Medium</span></td><td>Confirm the availability requirement before cutover sizing</td></tr>
<tr><td>BigQuery excluded from combined totals</td><td><span class="badge badge-impact-high">High</span></td><td><span class="badge badge-like-low">Low</span></td><td>Deferred to specialist engagement; plan the analytics track in parallel</td></tr>
</tbody></table>
</section>
<section id="exec-assumptions">
<h2>What This Assessment Rests On <a class="toplink" href="#toc">↑ contents</a></h2>
<p>Region, database size, and model detection extracted from your Terraform and code; availability defaulted to single-AZ per dev-tier signals. Cached pricing dated 2026-07 (±5–10% infra).</p>
</section>
<section id="decision-cta">
<h2>Ready to execute? <a class="toplink" href="#toc">↑ contents</a></h2>
<p>Say "generate the Terraform and migration scripts" and I'll produce the full execution pack (Terraform, migration scripts, rollback runbook, fill-in checklist) from this same analysis.</p>
<p>This decision report was generated without execution artifacts; the full migration report replaces it if you proceed.</p>
</section>
</div></div>
<footer>Generated by GCP to AWS Migration Advisor — draft for review</footer>
</body>
</html>
Loading
Loading