From 15f6554512fca6db068b535ac6a67ce654355cb1 Mon Sep 17 00:00:00 2001 From: Logan Kleier Date: Thu, 23 Jul 2026 15:41:08 -0700 Subject: [PATCH 1/2] =?UTF-8?q?fix(gcp-to-aws):=20resume=20and=20recovery?= =?UTF-8?q?=20reliability=20=E2=80=94=20stale=20reuse,=20corrupt=20state,?= =?UTF-8?q?=20mid-flow=20read?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - clarify.md Step 0 Case 1: compatibility-check preferences.json before offering reuse (schema currency + discovery match); incompatible files get a keep-valid-answers-and-fill-gaps path instead of dead-ending at GATE_FAIL; start-fresh renames to preferences-superseded.json instead of deleting; Step 5 cleans the backup up - SKILL.md State Validation rule 2: corrupted .phase-status.json is now reconstructed from on-disk artifacts with user confirmation instead of 'delete and restart' (which silently restarted from Discover) - clarify-global.md Q7: use the in-flight Q13b value, not preferences.json, which doesn't exist mid-Clarify (or is a stale prior run's on re-runs) --- .../skills/gcp-to-aws/SKILL.md | 6 +++++- .../phases/clarify/clarify-global.md | 2 +- .../references/phases/clarify/clarify.md | 21 +++++++++++++++++-- 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/migrate/plugins/migration-to-aws/skills/gcp-to-aws/SKILL.md b/migrate/plugins/migration-to-aws/skills/gcp-to-aws/SKILL.md index 204ab66b..28488e4f 100644 --- a/migrate/plugins/migration-to-aws/skills/gcp-to-aws/SKILL.md +++ b/migrate/plugins/migration-to-aws/skills/gcp-to-aws/SKILL.md @@ -129,7 +129,11 @@ Generate phase additionally loads `references/shared/validate-artifacts.md` befo When reading `$MIGRATION_DIR/.phase-status.json`, validate before proceeding: 1. **Multiple sessions**: If multiple directories exist under `.migration/`, list them with their phase status and ask: [A] Resume latest, [B] Start fresh, [C] Cancel. -2. **Invalid JSON**: If `.phase-status.json` fails to parse, STOP. Output: "State file corrupted (invalid JSON). Delete the file and restart the current phase." +2. **Invalid JSON**: If `.phase-status.json` fails to parse, do NOT delete it and do NOT restart from Discover — the phase artifacts on disk are the durable record of progress. Reconstruct instead: + 1. Enumerate `$MIGRATION_DIR` and infer completed phases from artifacts: any of `gcp-resource-inventory.json` / `billing-profile.json` / `ai-workload-profile.json` → discover completed; `preferences.json` → clarify completed; `aws-design.json` / `aws-design-ai.json` / `aws-design-billing.json` → design completed; `estimation-*.json` → estimate completed; `generation-*.json` or `MIGRATION_GUIDE.md` → generate completed. + 2. Present the inferred status to the user: "Your state file was corrupted, but I can see [phases] completed from the artifacts on disk. Resume at [next phase]? (Y/N)" + 3. On Y: rewrite `.phase-status.json` with the inferred phases marked `"completed"`, the next phase `"pending"`, `current_phase` set to it, and a fresh `last_updated`. Continue normally. On N: ask which phase to resume from and write that instead. + This is reconstruction of ground truth from artifacts, not artifact-patching to pass a gate — the handoff-gate prohibition does not apply to `.phase-status.json` recovery. 3. **Unrecognized phase**: If `phases` object contains a phase not in {discover, clarify, design, estimate, workshop, generate, feedback}, STOP. Output: "Unrecognized phase: [value]. Valid phases: discover, clarify, design, estimate, workshop, generate, feedback." 4. **Unrecognized status**: If any `phases.*` value is not in {pending, in_progress, completed}, STOP. Output: "Unrecognized status: [value]. Valid values: pending, in_progress, completed." 5. **Invalid `current_phase`** (if present): If `current_phase` is not in {discover, clarify, design, estimate, generate, complete}, STOP. Output: "Unrecognized current_phase: [value]. Valid values: discover, clarify, design, estimate, generate, complete." (`workshop` and `feedback` are sidebars — never `current_phase`.) diff --git a/migrate/plugins/migration-to-aws/skills/gcp-to-aws/references/phases/clarify/clarify-global.md b/migrate/plugins/migration-to-aws/skills/gcp-to-aws/references/phases/clarify/clarify-global.md index 4ef2f72d..20e0c804 100644 --- a/migrate/plugins/migration-to-aws/skills/gcp-to-aws/references/phases/clarify/clarify-global.md +++ b/migrate/plugins/migration-to-aws/skills/gcp-to-aws/references/phases/clarify/clarify-global.md @@ -269,7 +269,7 @@ Default: B — `availability: "multi-az"`. **Database migration tooling notes:** -- Read `preferences.json` → `design_constraints.db_size.value` (set by Q13b in `clarify-database.md`) to select the right tool. If absent, fall back to the size thresholds below. +- Use the **in-flight resolved Q13b value** (`db_size` from Step 2 extraction, the confirmed Assumption Sheet, or `preferences-draft.json` — Q13b is defined in `clarify-database.md`) to select the right tool. Do NOT read `preferences.json` here: mid-Clarify it does not exist yet (it is written at Step 5), and on a re-run any file present is a prior run's stale answers. If Q13b is not yet resolved, fall back to the size thresholds below. - For PostgreSQL databases `db_size: "<10GB"` or unknown-small: **pg_dump/pg_restore** is sufficient. - For PostgreSQL databases `db_size: "10-100GB"` or `"100-500GB"`: **pgcopydb** offers parallel table copying and index rebuilding, significantly reducing migration time within the same maintenance window. - For PostgreSQL databases `db_size: ">500GB"`: **AWS DMS strongly recommended** regardless of maintenance window — single-pass export/import at this scale is high-risk. diff --git a/migrate/plugins/migration-to-aws/skills/gcp-to-aws/references/phases/clarify/clarify.md b/migrate/plugins/migration-to-aws/skills/gcp-to-aws/references/phases/clarify/clarify.md index adf17484..f8da280b 100644 --- a/migrate/plugins/migration-to-aws/skills/gcp-to-aws/references/phases/clarify/clarify.md +++ b/migrate/plugins/migration-to-aws/skills/gcp-to-aws/references/phases/clarify/clarify.md @@ -26,13 +26,30 @@ Check `$MIGRATION_DIR/` for existing state: **Case 1 — Completed preferences exist** (`preferences.json` present): +**Compatibility check (run BEFORE offering reuse):** The existing file may predate the current flow, and the Completion Handoff Gate forbids patching artifacts to pass — so an incompatible file offered for reuse dead-ends at `GATE_FAIL`. Check: + +1. **Schema currency** — `metadata.clarify_mode` is present; every constraint has `value`, `chosen_by`, `prompt`, and `design_consequence`; every constraint with `chosen_by: "extracted"` or `"default"` has a `source` field; `design_constraints.cpu_architecture` is present when compute resources exist in the current inventory. +2. **Discovery match** — the file's `metadata.discovery_artifacts` is consistent with what exists in `$MIGRATION_DIR` now: if `ai-workload-profile.json` exists but the file has no `ai_constraints` (or the reverse), or the inventory has database/compute resources whose required constraints (`availability`, `db_size`) are absent, the file is stale relative to current discovery. + +**If both pass**, offer: + > "I found existing migration preferences from a previous run. Would you like to:" > > A) Re-use these preferences and skip questions > B) Start fresh and re-answer all questions - If A: Run Step 2 item 6 only (BigQuery detection) on current discovery artifacts. If `bigquery_present` is **true**, output the Step 4 **BigQuery / deferred analytics** advisory block once (even though questions are skipped), then skip to Validation Checklist with the existing `preferences.json`. -- If B: delete `preferences.json`, continue to Step 1. +- If B: rename `preferences.json` to `preferences-superseded.json` (do not delete — prior answers are unrecoverable otherwise), continue to Step 1. + +**If either check fails**, do NOT offer plain reuse — it would fail the gate. Instead: + +> "I found preferences from a previous run, but they predate the current flow (missing: [list]). Would you like to:" +> +> A) Keep your previous answers where they're still valid — I'll confirm them on the assumption sheet and only ask what's new or missing +> B) Start fresh and re-answer all questions + +- If A: rename the old file to `preferences-superseded.json`, seed the wizard from it — carry each still-valid constraint value forward with its original `chosen_by` (backfilling `prompt`/`design_consequence`/`source` from the current catalog), treat missing constraints as unresolved — and continue to Step 1 (the wizard fills the gaps; carried-forward values appear on the Assumption Sheet for confirmation). +- If B: rename to `preferences-superseded.json`, continue to Step 1. **Case 2 — Draft preferences exist** (`preferences-draft.json` present, no `preferences.json`): @@ -747,7 +764,7 @@ Full schema and constraint catalog: `references/shared/schema-preferences.md`. 15. `ai_constraints.ai_framework` is an array (Q14 is select-all-that-apply). If auto-detected, `chosen_by` is `"extracted"` with `source`. 16. `metadata.clarify_mode` is one of `"wizard"`, `"full"`, `"fast_path"`, `"simple_hybrid"`. -After writing `preferences.json`, delete `$MIGRATION_DIR/preferences-draft.json` if it exists. +After writing `preferences.json`, delete `$MIGRATION_DIR/preferences-draft.json` and `$MIGRATION_DIR/preferences-superseded.json` if they exist (the superseded backup has served its purpose once a new complete file exists). --- From 1f447f66528293c179d134bf22929d0b7736a3a5 Mon Sep 17 00:00:00 2001 From: Logan Kleier Date: Thu, 13 Aug 2026 07:16:41 -0700 Subject: [PATCH 2/2] fix(gcp-to-aws): tighten corrupt-state estimate inference for partial AI writes When reconstructing .phase-status.json, do not mark estimate completed if AI artifacts are expected (ai_constraints / ai profile / aws-design-ai) but estimation-ai.json is missing. Note that Y/N confirmation remains the safety net for other partial-write ambiguity. Co-authored-by: Cursor --- migrate/plugins/migration-to-aws/skills/gcp-to-aws/SKILL.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/migrate/plugins/migration-to-aws/skills/gcp-to-aws/SKILL.md b/migrate/plugins/migration-to-aws/skills/gcp-to-aws/SKILL.md index 28488e4f..def53454 100644 --- a/migrate/plugins/migration-to-aws/skills/gcp-to-aws/SKILL.md +++ b/migrate/plugins/migration-to-aws/skills/gcp-to-aws/SKILL.md @@ -130,8 +130,8 @@ When reading `$MIGRATION_DIR/.phase-status.json`, validate before proceeding: 1. **Multiple sessions**: If multiple directories exist under `.migration/`, list them with their phase status and ask: [A] Resume latest, [B] Start fresh, [C] Cancel. 2. **Invalid JSON**: If `.phase-status.json` fails to parse, do NOT delete it and do NOT restart from Discover — the phase artifacts on disk are the durable record of progress. Reconstruct instead: - 1. Enumerate `$MIGRATION_DIR` and infer completed phases from artifacts: any of `gcp-resource-inventory.json` / `billing-profile.json` / `ai-workload-profile.json` → discover completed; `preferences.json` → clarify completed; `aws-design.json` / `aws-design-ai.json` / `aws-design-billing.json` → design completed; `estimation-*.json` → estimate completed; `generation-*.json` or `MIGRATION_GUIDE.md` → generate completed. - 2. Present the inferred status to the user: "Your state file was corrupted, but I can see [phases] completed from the artifacts on disk. Resume at [next phase]? (Y/N)" + 1. Enumerate `$MIGRATION_DIR` and infer completed phases from artifacts: any of `gcp-resource-inventory.json` / `billing-profile.json` / `ai-workload-profile.json` → discover completed; `preferences.json` → clarify completed; `aws-design.json` / `aws-design-ai.json` / `aws-design-billing.json` → design completed; `estimation-*.json` → estimate completed (**partial-write check:** if `preferences.json` has an `ai_constraints` section — or `ai-workload-profile.json` / `aws-design-ai.json` is present — but `estimation-ai.json` is missing while another `estimation-*.json` exists, treat estimate as **incomplete**, not completed; propose resume at estimate); `generation-*.json` or `MIGRATION_GUIDE.md` → generate completed. + 2. Present the inferred status to the user: "Your state file was corrupted, but I can see [phases] completed from the artifacts on disk. Resume at [next phase]? (Y/N)". **Confirmation is the safety net for residual ambiguity** (e.g. other partial writes the heuristic misses) — on N, the user picks the phase to resume. 3. On Y: rewrite `.phase-status.json` with the inferred phases marked `"completed"`, the next phase `"pending"`, `current_phase` set to it, and a fresh `last_updated`. Continue normally. On N: ask which phase to resume from and write that instead. This is reconstruction of ground truth from artifacts, not artifact-patching to pass a gate — the handoff-gate prohibition does not apply to `.phase-status.json` recovery. 3. **Unrecognized phase**: If `phases` object contains a phase not in {discover, clarify, design, estimate, workshop, generate, feedback}, STOP. Output: "Unrecognized phase: [value]. Valid phases: discover, clarify, design, estimate, workshop, generate, feedback."