feat(gcp-to-aws): post-Estimate Decision gate — Generate becomes opt-in - #185
feat(gcp-to-aws): post-Estimate Decision gate — Generate becomes opt-in#185herosjourney wants to merge 13 commits into
Conversation
… product, Generate is opt-in - estimate.md: workshop offer becomes a 3-option Decision gate (done for now / what-ifs / generate). Verdict, cost (with baseline-quality label), timeline band, and deferred items presented from existing estimate artifacts. Option A ends the run decision-complete; C opts into Generate. - SKILL.md: 'Generate is opt-in' hard rule (gate C, resume acceptance, or explicit Terraform request — never auto-chain); generate state-machine row now requires consent; new decide-complete row with resume offer; ordered evaluation respects consent; feedback checkpoint re-anchored to fire after gate resolution (decision-check lands right after the actual decision). - workshop: exits return to the Decision gate, not Generate (workshop-assemble, workshop.md branch + decline, sheet action label); canonical workshop-invariants exit rule generalized (skill may define a post-Estimate gate; heroku/vercel behavior unchanged) + vendored resync. - schema-phase-status.md: optional run_mode field (decide | decide_and_execute); decide-complete documented as terminal-unless-asked (generate stays pending — no 'skipped' status).
1. State-machine workshop row: 'workshop offer' -> Decision gate (stale wording would regress agents to the old Enter/Proceed prompt) 2. Estimate scope boundary: carve out the gate's one-line timeline band; full schedules stay Generate-only 3. Every Execute path (gate C, resume Yes, explicit ask) sets run_mode: decide_and_execute BEFORE loading generate.md, so a death mid-Generate resumes as an Execute run 4. Consent guard at the top of generate.md — refuses and re-presents the gate when loaded cold without consent 5. Canonical invariants exit rule tightened: skills with a gate NEVER auto-advance to Generate (vendored resynced) 6. handoff-gates.md: decide-complete documented as a valid terminal state, not a failure to repair 7. Soft: after gate A, feedback folds into the closing line as a one-line Yes/No instead of a separate phase-like prompt
|
Review fixes landed in 28f46ef — all six improvements plus the soft suggestion:
Re-verified after the changes: dprint, markdownlint (0 errors), frontmatter validator, vendored-shared check, and fixtures:assert (6 asserters incl. both workshop goldens) all pass. On the chat-only decision pack UX hole: agreed and holding the line — PR 2 (shared decision core + durable decision-report.html) is queued, nothing report-shaped added here. |
leon1418
left a comment
There was a problem hiding this comment.
[🤖 AI review 🤖]
Reviewed all 11 changed files end-to-end against mainline and sibling PRs #180–#186.
Design: Sound — the core insight ("the decision is the product; Terraform is a second product") is well-executed as a single-pipeline two-exit-ramp model. run_mode as durable cross-session consent, decide-complete as a terminal-unless-asked state, and the consent guard at the top of generate.md form a defence-in-depth against auto-chaining. State machine, schema, invariants, and handoff-gates all mutually consistent.
Functionality: Workshop → gate return, gate choice handling, resume offers, feedback re-anchoring, and ordered evaluation logic all trace correctly. Vendored trees are byte-identical (verified). The AI-only/billing-only path correctly omits option B.
No blocking findings. Two nits below — both are about documentation clarity rather than correctness. The existing mickylindsay comment (line 141, heading parenthetical noise) is a fair point worth addressing but is not a code-health regression.
Recommend merge once the open reviewer thread is resolved.
…ing, legacy resume - Drop changelog parenthetical from the Decision gate heading - Align generate-row + HARD RULE wording on explicit produce-request intent - Add legacy-generate back-compat for current_phase=generate with no run_mode (present resume offer instead of hanging with no matching row) - Phase Status Update Protocol: current_phase may become complete after Estimate when gate A sets run_mode=decide Co-authored-by: Cursor <cursoragent@cursor.com>
Validity check + fixesAssessed each open thread before changing code:
No disagreements — all four were correctness/clarity issues worth landing before merge. |
Merge-readiness checkVerified bc46ccd against all five open review threads:
All five threads look resolvable as-is. One remaining blocker — the failing #186 contains these commits and inherits the same sync requirement — this PR should land first. |
…isor's vendored copies Mechanical port of this branch's 11 changed files to their advisor twins (re-copy + the prefix/path/$id rewrites cross-plugin-drift.ts normalizes), so the advisor plugin ships the same post-Estimate Decision gate instead of the old auto-advance. Verified locally: cross-plugin-drift.ts OK (250 identical, 25 allowlisted), sync-vendored-shared.ts OK on both plugins. Unblocks the drift:check failure on awslabs#185; changes are herosjourney's, this commit only mirrors them.
|
Pushed a307579 to unblock |
…th SKILL.md copies The legacy-generate row widened the table; dprint wants the columns re-padded. Formatting-only — cross-plugin drift and both vendored-shared checks re-verified green after formatting.
…dvisor's vendored copies This branch predates awslabs#206's consolidation, so drift:check fails: 16 skill files (report-decision-core.md missing outright, 15 drifted — SKILL.md, design, discover-preview, estimate, feedback, five generate phase files, migration-complexity, schema-estimate-infra, validate-migration-report) carried the decision-report changes on the migrate side only. Synced via re-copy + the prefix/path/$id rewrites the tool normalizes. Also synced what drift:check cannot see — the advisor plugin's OWN copies outside skills/: scripts/validate-migration-report.py (decision mode: executive sections + CTA, appendices forbidden), tests/test_validate_migration_report.py, tools/run-asserters.py (the gcp-decision-gate asserter mapping), the updated reference fixtures, and the new fixtures/gcp-decision-gate/ tree. Without these the advisor plugin would validate decision reports with the pre-decision rules. The branch also merges feat/decision-gate (awslabs#185's current head — this PR stacks on it and CI needs its 11-file advisor sync) and main. Both suites 51/51, both asserter sets PASS, drift 252 identical, vendored-shared and dprint green.
Summary
The problem, in plain English: Most startups come to this plugin with one question — "should we migrate, and roughly what would it cost?" — but the pipeline treats that as a waypoint on the road to Terraform. The verdict already exists at the end of Estimate (
recommendation.outcome, since #173), yet the flow's default motion is onward: workshop offer, feedback prompt, then Generate writes 20 Terraform files and a fill-in TODO list for a user who never said yes to executing. The decision is the product for the startup ICP; execution artifacts are a second product that today isn't opt-in.What this PR does: makes the post-Estimate fork the product. One pipeline, two exit ramps — no mode picker at the door, no new phase status, no second report engine.
Changes:
estimate.md): the workshop offer becomes a three-option gate presented after outer-EstimateHANDOFF_OK: [A] Done for now (decision-complete), [B] Explore what-ifs (existing workshop, benefit-first wording and the data-justified scenario hint preserved), [C] Generate Terraform and migration scripts. The gate leads with the decision pack — verdict (outcome_label), Balanced-tier AWS estimate beside the GCP baseline with its baseline-quality label and the feat(gcp-to-aws): Design summary card + cost baseline-quality labels #175 not-comparable rule, a timeline band frommigration-complexity.md, and deferred-specialist items. A/B/C never auto-resolves.SKILL.mdhard rule + state machine):generate.mdloads only on gate choice C, an accepted resume offer, or an explicit ask for Terraform/scripts. Thegeneratestate-machine row now requires that consent; a new decide-complete row (current_phase: "complete"+run_mode: "decide"+generate: "pending") defines resume behavior — offer Execute, never re-run Estimate, never auto-run Generate. Ordered (no-current_phase) evaluation respects the same consent.workshop-assemble.md,workshop.md,workshop-sheet.md): exiting the workshop re-presents the gate (A/C, verdict lines refreshed from the active scenario) instead of advancing to Generate. The canonicalworkshop-invariants.mdexit rule is generalized — "advances per the skill's post-Estimate flow;generateby default, or the skill's decision gate when one is defined" — so heroku/vercel behavior is unchanged; vendored trees resynced viashared:sync.SKILL.mdstep 8): the post-Estimate feedback checkpoint now fires after the gate resolves, and the gate owns the post-Estimate sequence (no prompt stacking). Side benefit: feat(gcp-to-aws): benefit-first workshop offer, outcome flips in compare, feedback decision check #176's "could you make your migrate/stay decision?" questions now land immediately after the user actually made one.run_mode(schema-phase-status.md): optional field,"decide"|"decide_and_execute", set only by the gate (or resume acceptance) — durable cross-session evidence of Generate consent. Deliberately no"skipped"status:generatestays"pending", and decide-complete is documented as terminal-unless-asked, not failure. Flow state, not a design constraint — never written topreferences.json.What this deliberately does NOT do (v1 scope, agreed in design review)
generate: "skipped"enum — a new status touches never-goes-backward, resume, gates, and heroku parity mid-feat(heroku-to-aws): clarify extraction + assumption sheet, decision outcomes, breadcrumbs (gcp parity) #180.pending+run_modecarries the meaning; revisit only if the ambiguity bites.--mode decisionvalidator subset; replace-never-patch on upgrade). Until then, option A's decision pack lives in chat plus the existing estimate/design JSON.Test plan
dprint check— cleanmise run lint:md— 0 errorsmise run lint:frontmatter— OK (both skills)shared:sync+ vendored check — OK (3 vendored trees; canonical edit synced, no hand-edited vendored files)fixtures:assert— PASS (6 asserters incl. both workshop goldens)HANDOFF_OK, no status writes — diff-verified)run_mode: decide_and_executeFollow-ups (tracked)
report-decision-core.md(Sections 0–8) loaded by Estimate's Decide path and Generate's report;decision-report.html+DECISION.md; validator--mode decision. Extraction keeps one source of truth for feat(gcp-to-aws): Design summary card + cost baseline-quality labels #175 rules/verdict typography (the vendored-drift lesson).run_mode+ gate semantics rather than a status enum — flagged so the enums don't fork.Type of Change
Team Folder
migrate/