# Generate Phase: HTML Migration Report > Loaded by generate.md AFTER generate-artifacts-docs.md completes. **Execute ALL steps in order. Do not skip or optimize.** ## Overview Generate a single self-contained HTML report (`migration-report.html`) combining an executive summary with detailed appendix. The HTML file uses inline CSS — no external dependencies required. Users can open it in any browser and use "Print to PDF" if a PDF is needed. **Output:** - `migration-report.html` — Self-contained HTML report with executive summary and detailed appendix **Non-blocking:** If report generation fails after `VALIDATE_OK` (HTML build error only), log a warning and continue. Validation `GATE_FAIL` is **not** a silent skip — always surface to the user. Do NOT fail the Generate phase for report issues. ## Step 0: Validate Artifacts (Read Only) Load and execute `shared/validate-artifacts.md` **before** building report content. - Run all **required** checks (field presence only — do not rewrite artifact prose). - On any `GATE_FAIL`: output failure lines to the user, **do NOT write** `migration-report.html`, **do NOT patch artifacts**, return to parent `generate.md`. - On `VALIDATE_OK`: proceed to Step 1. ## Prerequisites At least one of these must exist in `$MIGRATION_DIR/`: - Design artifact: `aws-design.json`, `aws-design-ai.json`, or `aws-design-billing.json` - Estimation artifact: `estimation-infra.json`, `estimation-ai.json`, or `estimation-billing.json` - Generation plan: `generation-infra.json`, `generation-ai.json`, or `generation-billing.json` If **none** exist: skip report generation. Output: "Skipping HTML report — no migration artifacts found." ## Data Sources Gather data from all available artifacts. Each section below notes which artifact provides the data. | Data Point | Primary Source | Fallback | | ---------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------- | | GCP services detected | `aws-design.json` clusters[].resources[] | `aws-design-billing.json` services[] | | AWS service mappings | `aws-design.json` resources[].aws_service | `aws-design-billing.json` services[].aws_service | | Rationale per service | `aws-design.json` resources[].rationale | `aws-design-billing.json` services[].rationale | | Current GCP monthly cost | `estimation-infra.json` current_costs.gcp_monthly | `estimation-billing.json` | | Projected AWS monthly cost | `estimation-infra.json` projected_costs.aws_monthly_balanced | `estimation-billing.json` | | Cost breakdown per service | `estimation-infra.json` projected_costs.breakdown | `estimation-billing.json` | | Cost tiers (premium/balanced/optimized) | `estimation-infra.json` cost_comparison | — | | Optimization opportunities | `estimation-infra.json` optimization_opportunities | — | | Migration shape (approach + duration drivers) | `generation-infra.json` migration_plan.duration_drivers | `generation-billing.json` | | Top risks | `generation-infra.json` risk_assessment | `generation-billing.json` | | Human expertise flags | Design artifact resources[].human_expertise_required | — | | AI model mappings | `aws-design-ai.json` | — | | AI cost estimates | `estimation-ai.json` | — | | Migration decision / recommendation | `estimation-infra.json` → `recommendation` | `financial_summary.recommendation` (string fallback) | | Complexity and path shape | `migration-preview.json` → `complexity_signal`, `duration_hint` (legacy `timeline_hint` accepted, week values only with the uncalibrated label) | — | | Key decisions ahead | `migration-preview.json` → `key_decisions_ahead` | — | | User configuration choices | `preferences.json` (read `.value` from wrapped fields) | — | | AI capabilities and integration | `ai-workload-profile.json` → `models[]`, `integration`, `agentic_profile` | — | | Deferred services | Design artifact `resources[].aws_service == "Deferred — specialist engagement"` | — | | Observability cost callout | `estimation-infra.json` → `projected_costs.breakdown` (array: `service` contains "Observability"; object: key contains `observability` or `cloudwatch`) | — | | **Combined AWS monthly run rate (infra + AI)** | Sum `estimation-infra.json` Balanced + `estimation-ai.json` → `cost_comparison.projected_bedrock_monthly` (or `recommended_model.monthly_cost`) | — | | **Security baseline component costs** | `estimation-infra.json` → `projected_costs.breakdown.security_baseline.components` (GuardDuty, cloudtrail_s3, etc.) | Static ranges in Appendix G when JSON absent | | **Terraform validation status** | `validation-report.json` → `status`, `provider_version` | — | | **Pricing confidence / staleness** | `estimation-infra.json` → `pricing_source`, `accuracy_confidence` | `estimation-ai.json` accuracy fields | | **AI optimization opportunities** | `estimation-ai.json` → `optimization_opportunities`, `optimized_projection` | — | | **What-if workshop scenarios** | `scenarios/index.json` + each `scenarios/scenario-NNN.json` manifest (`estimation_summary`, `preferences_subset`, optional `graviton_note`) | — (omit section when workshop unused) | ## Step 1: Build Executive Summary Section **Load `references/shared/report-decision-core.md` and render it in `full` mode.** That file is the single source of truth for every executive-summary section (Decision Summary through "What this assessment rests on") — verdict typography, baseline-quality/not-comparable rules, Activate wording, and readability conventions all live there. Do not restate or paraphrase its rules here. Full-mode notes: - `generation-infra.json` and `terraform/` exist on this path — use them where the core's sections prefer them (migration shape from `migration_plan.duration_drivers`, cluster order in the architecture diagram). - **Replace, never patch:** if `decision-report.html` exists from a prior Decide run, leave it untouched and render `migration-report.html` fresh from the artifacts. Do not splice or extend the decision report's HTML. Note in the Generated Artifacts Catalog that the full report supersedes the decision report. ## Step 2: Build Detailed Appendix The appendix follows the executive summary, clearly separated with an "Appendix: Detailed Migration Analysis" header. ### Appendix Section A — Service Recommendations For each mapped service, include: - GCP service name and type - AWS service recommendation - **How the mapping was chosen** — use **Standard pairing**, **Tailored to your setup**, or **Estimated from billing only** (`design-refs/fast-path.md` → User-facing vocabulary); JSON `confidence` may appear in parentheses for support - Full rationale text from design artifact - If the mapping was **Tailored to your setup** (`inferred`) and `rubric_applied` is present: list the 6 criteria evaluations (appendix detail — optional in executive summary) - If `human_expertise_required: true`: include the specialist guidance callout Source: design artifact (aws-design.json or aws-design-billing.json) ### Appendix Section B — Cost Estimates **Per-service cost breakdown table** with columns: Service Category, AWS Service, Monthly Cost (Balanced), Calculation/Notes. **Mandatory rows when present in `projected_costs.breakdown`:** - compute, database, storage, networking - **security_baseline** — include `mid` cost AND component sub-rows from `components` (e.g. GuardDuty, cloudtrail_s3, budgets) - **observability** — include `mid` and `note` (GCP free-tier comparison) - supporting (Secrets Manager, ECR, etc.) Do NOT collapse security_baseline into "other". Surface GuardDuty explicitly. **GCP baseline breakdown** (when `current_costs.breakdown` exists): table of compute/database/storage/networking/other vs infra total. Source: estimation artifact projected_costs.breakdown, current_costs.breakdown **Three-tier comparison table** with columns: **Tier** (name + subtitle as in Section 3), Monthly Cost, vs GCP Monthly, Annual Difference. Repeat the **How to read cost tiers** callout from Section 3 here or include a one-line pointer: _See executive summary — three tiers are scenario $ only; generated Terraform matches **Balanced** baseline._ Source: estimation artifact cost_comparison **Do not** put the opportunity table only as an `
| `s and header (right-aligned, tabular figures). Mixed cells (a number plus a qualifying ``) still count as numeric.
12. **Corrections and derivations go in disclosures.** When a figure was corrected or derived (e.g. a tier-rule effort estimate replaced by a bottom-up range), the report states the **corrected value plus one clause** in the visible flow and puts the how-we-got-here narrative in a ` ` ("Why this is lower than the automatic estimate"). Internal classification history is machinery, not decision input — same principle as rule 2.
13. **No vague intensifiers.** Quantify instead of amplifying: never `very`, `significantly`, `extremely`, or `vastly` in report prose. "Significantly cheaper" becomes "-32% ($497/mo lower)". If a figure can't be quantified, state the range from the artifact or omit the claim. The validator fails on these words in the rendered body.
14. **Unambiguous dates.** All dates use ISO format `YYYY-MM-DD` (generation date, pricing last-updated, ECD-style targets). Never slash formats (`07/24/2026` reads differently in different locales). The validator fails on `N/N/YYYY` slash dates in the body.
15. **Color is never the only signal.** Verdict, complexity, and confidence badges already carry text labels — keep it that way for any new status element. Cost deltas keep the `+`/`-` prefix and a word ("savings" / "increase") alongside the green/red styling, so the report reads correctly when printed in black-and-white or by a color-blind reader.
16. **Active voice for actions.** Migration steps and next steps name the actor: "You run the cutover script", "Terraform creates the security baseline", "Your AWS account team reviews the BigQuery path" — never "the hosts will be migrated" with no owner.
17. **Denominators with progress metrics.** Any percentage describing coverage or progress states its base: "6 of 8 services (75%)", not "75% of services". Cost percentages keep their baseline visible in the same table row.
18. **Copy-ready leadership brief.** When a monthly estimate exists, render
`exec-share` after the TOC using only decision-summary facts. It contains
one standalone paragraph, no buttons or JavaScript, no new calculations,
and no stronger certainty than the underlying estimate.
19. **Rounded monthly figures (enforces rule 2).** A monthly-scale dollar
figure (whole-dollar part `$2` or higher) never renders with cents —
round to the nearest whole dollar. Cents remain only on genuinely
sub-dollar precision (`$1.50`, `$0.40`) or a per-unit rate (`$0.018/hr`,
`$21.18` per 1-/6-month commitment unit-hour). The validator fails on a
`$X.YY` figure `>= $2.00` with no adjacent rate suffix — this is the
regression class where raw unrounded arithmetic (`$25,684.89/mo`) reaches
the reader and overflows fixed-width metric cards.
> **Section IDs are stable anchors, not placement hints.** Some `appendix-*` IDs render in the executive flow on purpose (notably `appendix-assumptions`). Do not rename IDs to match position — the validator and TOC key on them.
## Step 4: Self-Check and Post-Write Validation
After generating the HTML file, verify:
1. **Required section IDs**: Each required ID appears **exactly once** on ` ` or other elements). See validator script.
2. **TOC integrity**: Every ` |