Repository navigation
feat: extract Bedrock migration assessment skill - #483
herosjourney wants to merge 58 commits into
Conversation
…n-assessment Merge main, which contains PR aws#369 (preserve Astra model and API across Bedrock migration), into the PR 483 branch using a semantic union. - The five conflicted gcp-to-aws phase files (clarify-ai-only, design-ai, estimate-ai, generate-ai, and the agent-advisor migration-plan overlap) keep the 483 delegation-only shims. - PR aws#369's neutral behavior is ported into the bedrock-migration-assessment files instead: design-ai, estimate-ai, clarify-ai-only, generate-ai, generate-artifacts-ai, discover-preview and shared/openai-on-bedrock. 483's source-neutral wording is kept in the textual conflict hunks. - Vendored AI guides are resynced from shared/ai. - closure.json and the bootstrap manifests are regenerated with the repo tools. The closure stays at 65 entries. The documented bootstrap hash in gcp-to-aws SKILL.md and discover.md is updated to 5863fe96...bba7. - Regression tests for the moved aws#369 behavior are added. Validation: plugin pytest 697 passed, llm-to-bedrock 407 passed, agent-advisor 562 passed; mise ci, validate, build and security pass; fixture validator 85 artifacts, 0 errors; six-scenario remote smoke 6/6.
shrugninreddy-hash
left a comment
There was a problem hiding this comment.
Requesting changes for the inline comment on line endings. I also agree with vagmur-aws's comment on the Graviton step (discover-app-code.md:124).
One more gap: the new description and the bedrock-migration-assessment keyword are in the Claude and Cursor manifests, but not in .codex-plugin/plugin.json (description, keywords, interface.longDescription), the plugin-root plugin.json, or the .devin-plugin/plugin.json that #482 added to main today. Could you merge main and update all three?
AI-assisted review.
Addresses PR aws#483 review 5620455181 by vagmur-aws, comment 4353203474 (skills/shared/migration/bma-input-patterns.json:3 and closure.json): 4a51ac3 was a merge commit on the aws#449 branch, not an ancestor of main, and predated aws#369. - selected_base 4a51ac3 -> 9ab5063 (upstream/main) git merge-base --is-ancestor 9ab5063 upstream/main -> exit 0 - Regenerated closure.json and both bootstrap manifests with the PR's own tooling (sync-runtime-copies.py, build-bma-closure.py). - Verified every aws#369 hunk in the 7 adapted sources (clarify-ai-only, design-ai, discover-preview, estimate-ai, generate-ai, generate-artifacts-ai, openai-on-bedrock) is present in the BMA copies; no content drift to port. Vendored files pass lint:vendored-parity. - New test test_selected_base_pins_agree_and_are_consistent asserts one selected_base across closure.json, both bootstrap manifests, all three bma-input-patterns.json copies, runtime-copy-manifest.json, both fixtures, and the BASE constant in the classifier copies and tools. Hashes: closure.json file 7a58d70792bc363ab3d9e86156236dd3429905cc12ba9414c951bfa62717a783 closure.json self 457c32fc8ca1b0e6c74975500a6f921e2464aba1eb4cba0dbd279a0e261fa5da bootstrap manifest file 267fe013d216f85dd8c272126099d3f3eb2b909901324d14ab1a47ee06751b02 bootstrap manifest self 2447652f905ab40b2db3220883abb41c470106d118402f23b68fc6906624faab
…resence Addresses PR aws#483 review 5620455181 by vagmur-aws, comment 4353203462 (skills/shared/migration/bma-route-classifier.py:354): any .py/.js/.ts or package.json made the run AI_CANDIDATE, so a GCP repo with no AI code required the bedrock-migration-assessment sibling and regressed to BEDROCK_MIGRATION_ASSESSMENT_SIBLING_MISSING when only gcp-to-aws was installed. - bma-input-patterns.json gains `ai_signals` (imports, dependencies, endpoints, env_vars, model_prefixes) taken from the pattern families BMA's discover-app-code.md Step 3 / 3B and provider discover files already recognize. - Classifier reads source and manifest files it already inventories (audited; secret_excludes still never read) and reports AI_SIGNAL_CANDIDATE + ai_signal_files. Imports need import/from/require context; dependencies are matched in manifests only. AI_CANDIDATE = ai_signal or provider intent or Vertex-strong or durable. SOURCE_CONTAINING stays informational and no longer drives candidacy. - Reviewer repro (infra/main.tf + scripts/cleanup.py with print): before AI_CANDIDATE true / PURE_INFRASTRUCTURE false; after AI_CANDIDATE false / PURE_INFRASTRUCTURE true, no BMA path read. Same layout + scripts/ask.py `import openai`: AI_CANDIDATE true. Both are tests in tests/test_bma_bootstrap.py, plus per-family positives, negatives for prose/identifier substrings, secret-exclusion, and ai_signals schema negatives. - Route-rule prose updated in gcp-to-aws SKILL.md and discover.md. Hashes: closure.json file aaff5f522b57fb53604f5174a9db5d744466299ef93f32b5022815f0c419fd06 bootstrap manifest file ba18b9ac9dbb150fed6619d2c90bf132eced2a4bda63e1bdc538bfd8b6015d62
Addresses PR aws#483 review 5620455181 by vagmur-aws, comment 4353203451 (skills/bedrock-migration-assessment/references/phases/discover/ discover-app-code.md:124): the extraction replaced Step 2.7 for every mode, so delegated GCP runs stopped emitting `graviton_profile` entries with `source: "app_code"` while discover-iac.md:118 and clarify-compute.md:256 still consume them. Per the reviewer's preferred option, Graviton/compute profiling moves back to gcp-to-aws ownership and stays out of the neutral BMA engine: - New GCP-owned references/phases/discover/discover-app-graviton.md carries the pre-PR Step 2.7 text (loads shared/schema-graviton.md and shared/graviton.md, emits `graviton_profile` with `source: "app_code"`). - discover.md Step 1b loads it for every source-containing run, before and independent of the BMA shim; the shim is now loaded only when preflight returned `AI_CANDIDATE: true` (after the finding-2 gate a source-containing non-candidate never preflights BMA yet still needs app-code Graviton profiles). Sub-discovery list and completion gate updated accordingly. - gcp-to-aws shim notes that Graviton is not delegated. - BMA discover-app-code.md Step 2.7 stays "not applicable" in every mode and tells delegated runs not to touch the GCP profile (closure entry 11 changed, hashes rebuilt). - New tests/test_gcp_graviton_app_code_ownership.py: controller order and AI_CANDIDATE gating, GCP file emits app_code profiles with the four rules, consumers still reference app_code, direct BMA has no infrastructure/Graviton logic anywhere in its closure. - gcp-to-aws SKILL.md keeps the exact "pure source-free infrastructure performs zero BMA operations" phrase pinned by test_outer_controllers_preserve_gcp_ownership (the finding-2 reword had dropped it). Hashes: closure.json file 2b7bc5142b92066213c1f55f6ac263f6b90bfa43c8b35af7eb4f69da1b303af7 bootstrap manifest file 2fb2a229f9eace99a49ef0344c2506c4f0e1088c7ecac59c98b8c27dc6770cb0
…AI imports Follow-up to a02d030 for PR aws#483 review 5620455181 by vagmur-aws, comment 4353203462 (skills/shared/migration/bma-route-classifier.py:354). The AI-evidence gate's import template only matched dotted tokens spelled in full (`from google.cloud.aiplatform import x`), so the canonical Python spelling `from google.cloud import aiplatform` (and vision, speech, documentai, translate, dialogflow) produced AI_CANDIDATE false and the GCP controller never loaded the BMA shim for such a project. - signal_patterns(): for dotted import tokens without a path separator, add `from <package> import [...]<leaf>` templates covering the plain, aliased, comma-separated and parenthesised multi-line forms. `from google.cloud import storage` and `from google import cloud` still do not match. - tests/test_bma_bootstrap.py: +4 positive cases in test_each_ai_signal_family_is_candidate, +1 negative case in test_non_ai_source_content_is_not_a_signal. - Runtime copies, closure.json and both bootstrap manifests regenerated with sync-runtime-copies.py / build-bma-closure.py; manifest pin updated in gcp-to-aws SKILL.md and discover.md. Hashes: closure.json file e011534f2cf84e5ae0e1314202d101215f819774f56f31dd9335ef543678260b bootstrap manifest file bd185386b30141710327440148b58c57fb16dfe13b8818d82b76f8112fac751a
…-assessment' into feat/issue-389-bedrock-migration-assessment
…ude manifest Main (aws#482) added .devin-plugin/plugin.json with the pre-PR plugin description and a validator that requires it to match .claude-plugin/plugin.json. This PR updates the Claude description for the bedrock-migration-assessment skill, so carry the same text into the Devin manifest. `mise run validate` passes again.
|
@shrugninreddy-hash thanks for the manifest review. All five manifests now list The Graviton item was already addressed in 39671c0 (restores GCP-owned Graviton app-code profiling). |
|
@shrugninreddy-hash Thanks for the manifest check. All five manifests (plugin.json, .claude-plugin, .cursor-plugin, .codex-plugin, .devin-plugin) now carry the bedrock-migration-assessment keyword and the same description. Commit 563225e added the keyword and the BMA capability, and 92a1304 keeps main's existing "move your model calls to Amazon Bedrock" wording with the BMA clause added beside it. The Graviton item was already addressed in 39671c0. Head is f4d509e. |
|
@shrugninreddy-hash the manifest finding is valid and fixed. The keyword and description now carry bedrock-migration-assessment in five manifests: plugin.json, .claude-plugin, .cursor-plugin, .codex-plugin, and .devin-plugin. The fix is in commit 563225e, with the description wording kept on main's model-call text in 92a1304. The Graviton item was already addressed in 39671c0. |
leon1418
left a comment
There was a problem hiding this comment.
[🤖 AI review 🤖]
Reviewed f4d509ed25dad5b9565456e9f5adb504693b9127 against 9ab50636d12510dc351ff02fd7966efa4dba4341. Four functional issues remain: final document rendering, delegated AI-only preferences ownership, authorized phase re-entry, and versioned Google AI detection. The inline comments give the required corrections and acceptance checks.
After the corrections, regenerate the BMA closure and shared/GCP bootstrap manifests from the final source, refresh the pinned hash in GCP SKILL.md and Discover, and run the closure/copy/documented-pin checks.
I verified the source changes addressing the earlier Graviton, non-AI bootstrap, selected-base and five-manifest feedback, plus LF behavior using a core.autocrlf=true checkout simulation.
Validation: targeted reproductions on original source; raw closure, parity, artifact, reference, consent, model/pricing, Markdown, root validation and both Node suites passed; advisor/LLM suites passed 562/407 tests. Current-head Ubuntu CI passed 749 tests with 2 skips. The local macOS plugin run had 643 passes, 106 failures caused by denied nested sandbox-exec, and 2 skips. Independent projected-source tests retained 2 projection-induced closure failures (326 passed, 1 skipped); these were not classified as PR defects.
|
Following up on my review: the issues I raised are fixed.
Waiting for the issues raised by leon1418 to be fixed before approval. AI-assisted comment. |
…egated route Addresses review item B from leon1418 on PR aws#483 (thread PRRT_kwDOSKiaLs6vsyPA). Delegated runs now require delegated_route (ai_only or combined). The AI-only route assigns preferences writes to bedrock-migration-assessment; combined keeps gcp-to-aws. Closure and bootstrap pins regenerated.
…port documents Addresses review item A from leon1418 on PR aws#483 (thread PRRT_kwDOSKiaLs6vsyO9). Report assemblies now require a controller-supplied complete document with section anchors. Each contribution carries a required section key, and HTML targets require report_mode. The runtime preflights the document, escapes contribution text into paragraphs, and remains the only final writer. Breaking change: assemblies without document fail with document_required, and contributions without section are rejected. Callers must send the full document and anchors (see the report assembly ABI in the BMA SKILL.md).
…th prior hash Addresses review item C from leon1418 on PR aws#483 (thread PRRT_kwDOSKiaLs6vsyPJ). Final documents owned by a phase (preferences, design, estimate, generate, and decision outputs) can be replaced on a same-route rerun. The caller must supply the exact prior SHA-256 and the owning phase. The runtime also requires stale downstream state or no completed later phase. Stale hashes and unauthorized replacements are rejected, and publish failures roll back.
Addresses review item D from leon1418 on PR aws#483 (thread PRRT_kwDOSKiaLs6vsyPO). Google Cloud import tokens now accept a version suffix (for example speech_v1 or documentai_v1) in the classifier signal patterns. Unversioned and other tokens are unchanged, so storage and storage_v1 stay non-candidates. Closure, runtime copies, and bootstrap pins are regenerated.
leon1418
left a comment
There was a problem hiding this comment.
[🤖 AI review 🤖]
Follow-up at c6ce88b7c2d78a9cf64b30c8a2ce2835f4eaad54 against previously reviewed f4d509ed25dad5b9565456e9f5adb504693b9127. The original plain-text report defect, delegated AI-only preference ownership, and versioned Google import detection are repaired.
Three functional issues remain: final-document assemblies still cannot replace existing outputs using a prior hash; the new report preflight rejects validator-valid attribute ordering; and state decisions do not prevent unrequested Generate writes. I missed the last issue in the first review; it exists at both heads. The report/re-entry details belong in the original threads, with the state-decision issue inline below.
Raw local validation: 672 plugin tests passed, 106 failed because nested macOS sandbox-exec is denied, and 2 were skipped. Advisor/LLM suites passed 562/407 tests. Raw closure, copy/parity, artifact, reference, consent, model/pricing, Markdown, root checks and both Node suites passed. Current-head CI was queued at capture; no prior-head CI result is claimed as current. The independent projected-source test failures remain explicitly separated from source defects.
After corrections, regenerate the raw closure/bootstrap copies and refresh documented pins; keep owner, prior-hash, duplicate-write and rollback checks. Approval remains with the user.
Address PR aws#483 review thread PRRT_kwDOSKiaLs6vwO-j from reviewer leon1418. - Generate-owned outputs (phase generate, replaceable outputs mapped to generate, ai-migration/ prefix) are refused unless generate was explicitly requested. Estimate outputs still write. - A confirm_reentry decision blocks replacement of an existing design file before any write is staged or published. Regression test: test_generate_writes_refused_without_generate_opt_in (plus estimate, stale-downstream re-entry, and rerun coverage in test_bma_phase_reentry.py).
…-assessment' into feat/issue-389-bedrock-migration-assessment
|
@leon1418 @vagmur-aws @shrugninreddy-hash — the branch is at
A before/after run on a real Gemini + image-generation app surfaced five behavior defects (image calls routed to a text model, a gate that didn't stop the run, the public profile taking the wrong shape, missing sidecar context, false retirement PASS). All five are fixed with regression tests. One note for @leon1418: the report-assembly change you asked for (complete document + section anchors, single final writer) is in and is a breaking change to that contract — bare contributions now fail with Previously-open threads have replies in place. I have not resolved any thread. Gates: plugin CI 883 passed, root validate/lint/security clean, gitleaks clean on the full range. The Authorities table and the 66-entry closure list in the description are current for this head. |
… instead of replacing it Review PR aws#483, thread PRRT_kwDOSKiaLs6wWifC (comment 4379736196) by vagmur-aws: `convert` overwrote what BMA discovery had already written to .bma-input/ai-workload-profile.json and replaced the sidecar observed_costs wholesale. Reproduced on 4b04374 with the exact scenario (BMA profile with gpt-4o from code, usage-API sidecar with observed_costs $555 = Google $450 + OpenAI $105, Vertex seed with gemini-2.5-pro). Before: bma-input models [('google', ['gemini-2.5-pro'])] and observed_costs {monthly_ai_spend: 450, source: billing_data}. After: both providers, gpt-4o and gemini-2.5-pro with their original evidence, observed_costs 555 mixed with both breakdown rows. Merge rule (deterministic, idempotent): - merge_415_profiles: ai_sources union keyed by (provider, source_service); models, model_observations (by normalized_model), evidence and model_families union in order of first appearance; gateways union keyed by (product, type) with upstreams by (provider, source_service) and families by name; model_evidence/upstream_evidence recomputed. The merged document is validated against the vendored aws#415 schema plus the runtime invariants. An existing non-aws#415 .bma-input profile fails closed (EXISTING_415_INVALID). - merge_observed_costs: per-provider rows (schema-discover-ai.md Usage-API merge); different providers summed under source "mixed" with breakdown[]; same provider replaced with the displaced row kept in conflicting_sources[]; totals recomputed, None never coerced to 0. - Sidecar: BMA-owned workloads, agentic_profile, tool_manifest untouched; GCP-owned integration_context, infrastructure, model_context, profile_origin replaced. Tests: the wrong test test_sidecar_keeps_existing_app_code_workloads_and_replaces_only_gcp_keys is rewritten as test_sidecar_keeps_existing_app_code_workloads_and_merges_observed_costs (asserts the merge); added test_convert_merges_into_bma_discovered_profile_and_sidecar_vagmur_repro, test_merge_observed_costs_same_provider_conflict_is_recorded_not_dropped, test_merge_415_profiles_unions_sources_models_observations_and_gateways, test_existing_bma_input_that_is_not_415_fails_closed. All five fail on 4b04374 and pass after this change. Verification: uv run --no-project --with pytest --with jsonschema==4.25.1 python -m pytest tests/test_gcp_ai_profile_adapter.py -q -> 36 passed.
…e and sidecar Review PR aws#483, thread PRRT_kwDOSKiaLs6wWifL (comment 4379736209) by vagmur-aws: the delegated writer table assigned .bma-input/ai-workload-profile.json and .bma-input/ai-workload-sidecar.json to gcp-to-aws, so the BMA writes the docs describe were rejected with writer_owner_invalid. Reproduced on 4b04374: execute_contract (mode delegated, route combined, phase discover) writing either .bma-input/ path with logical_owner bedrock-migration-assessment -> ValueError: writer_owner_invalid. Who writes what in delegated mode, per the docs: - discover-app-code.md Step 8 items 1-2: BMA writes $AI_PROFILE (.bma-input/ai-workload-profile.json) and $AI_SIDECAR; its "Pre-existing IaC profile" rule rewrites the profile. - discover-openai-api.md / discover-anthropic-api.md / discover-openrouter-api.md Step 4: BMA merges observed_costs and usage-only models into both files (rewrites with expected_sha256). - gcp-to-aws discover.md "AI profile boundary": the GCP adapter writes both files by direct file I/O outside bma-runtime.py execute (now a merge, see the previous commit). The public ai-workload-profile.json stays GCP's. Therefore the runtime's writer() only ever sees BMA for the two .bma-input/ paths: both are now BMA_OWNER. No either-owner rule is needed. The public ai-workload-profile.json stays GCP_OWNER (decision 3 / P3), guarded by the new negative test. .bma-input/ai-workload-profile.json is added to MUTABLE_OUTPUTS so the Step 4 / Step 8 rewrites with expected_sha256 are not rejected as duplicate_final_write. Tests: rewrote test_delegated_bma_input_is_gcp_adapter_owned_and_public_profile_unchanged as test_delegated_bma_input_is_bma_discover_owned_and_public_profile_gcp_owned; added test_delegated_bma_discover_write_of_bma_input_profile_and_sidecar_passes, test_delegated_bma_write_to_public_profile_fails_writer_owner_invalid, and the end-to-end test_delegated_flow_end_to_end_keeps_every_provider_model_and_dollar (adapter convert -> BMA Step 8 adds gpt-4o -> usage-API merges OpenAI $105 -> adapter convert again: all providers, all models, $555, idempotent). The three new/rewritten tests fail on 4b04374 and pass after this change. Closure and bootstrap pins regenerated with tools/build-bma-closure.py and tools/sync-runtime-copies.py; the two documented pins in skills/gcp-to-aws/SKILL.md and references/phases/discover/discover.md are hand-set per decision 11. Verification: uv run --no-project --with pytest --with jsonschema==4.25.1 python -m pytest tests/test_bma_*.py tests/test_gcp_ai_profile_adapter.py -q -> 345 passed, 2 skipped; build-bma-closure.py --check and sync-runtime-copies.py --check PASS.
Render option 1 decision: Render has no legacy profile and will never produce a sidecar, so the direct-mode input shape is the aws#415 profile alone (no legacy profile, no sidecar file). Before this change `validate-profile --sidecar <absent path>` raised an uncaught FileNotFoundError (exit 1), so every AI phase gate stopped on a Render-shaped input. - validate-profile accepts an absent --sidecar path: exit 0 with "sidecar": "absent"; a present sidecar is still validated ("sidecar": "validated") and an invalid one still fails with ai_sidecar_invalid. Without --sidecar the output is unchanged. - sidecar_availability() reports each sidecar-only field (workloads, agentic_profile, tool_manifest, observed_costs, integration_context, infrastructure, model_context, profile_origin) as available or not_available from presence only; it is emitted as "sidecar_fields" in the gate output. Nothing is inferred or synthesized for an absent field. - Routing (ai_sources[].provider / source_service) and target pricing (lifecycle registry, MODEL_TARGETS) come from the profile alone; semantic_trace already yields source_monthly / monthly_delta / source_monthly_basis None with observed cost not available while pricing the registered targets (pricing_source bedrock_cache). - Docs: schema-discover-ai.md states a direct run may have no sidecar and how the gate and phases treat it; design-ai.md Step 0 treats every sidecar field as not available when the file is absent; discover-app-code.md fixes the "$AI_SIDECAR is $AI_SIDECAR in direct mode" typo ($MIGRATION_DIR/ai-workload-sidecar.json). Tests: new tests/test_bma_direct_no_sidecar.py runs discover -> clarify -> design -> estimate on a aws#415-only input with no sidecar file (test_direct_415_only_input_without_sidecar_runs_discover_to_estimate), checks present-sidecar reporting and that validation is not weakened (test_validate_profile_cli_reports_present_sidecar_fields), and checks the per-field availability rule. The new file fails on the previous runtime (10 failed) and passes after this change. Recorded as decisions.md entry 15 (outside the repo). Closure and bootstrap pins regenerated with tools/build-bma-closure.py and tools/sync-runtime-copies.py; the two documented pins in skills/gcp-to-aws/SKILL.md and references/phases/discover/discover.md are hand-set per decision 11. Verification: uv run --no-project --with pytest --with jsonschema==4.25.1 python -m pytest tests/test_bma_*.py tests/test_gcp_ai_profile_adapter.py -q -> 355 passed, 2 skipped; build-bma-closure.py --check and sync-runtime-copies.py --check PASS.
…ock-migration-assessment # Conflicts: # plugins/aws-startup-advisor/mise.toml
|
@vagmur-aws @shrugninreddy-hash ready for another look at head Since your last review:
PR description's Authorities table and "Changes since first review" section are refreshed for this head. I have not resolved any threads; please close them if the fixes look right. |
vagmur-aws
left a comment
There was a problem hiding this comment.
My two earlier comments are fixed at fb1ba76. These seven are regressions against main or out-of-scope behavior changes; details and repros inline.
| if isinstance(payload.get("graviton_profile"), list): | ||
| return 0, f"GATE_PASS | {PHASE_GATE} | field=graviton_profile | file={name}" | ||
|
|
||
| return 1, f"ROUTE_GATE_FAIL | {PHASE_GATE} | field=graviton_profile | reason=missing" |
There was a problem hiding this comment.
Blocking (regresses GCP runs with no AI): This gate now stops any run that has source code but no top-level graviton_profile in gcp-resource-inventory.json or ai-workload-profile.json. Two common runs can't pass:
billing export + source code → ROUTE_GATE_FAIL exit=1 (billing writes no inventory)
inventory with metadata.graviton_profile → ROUTE_GATE_FAIL exit=1 (discover-app-graviton.md says "in the discovery metadata")
On main, a missing profile just meant Clarify asks Q11b. Please don't stop the run on a missing profile. If you keep the gate, make the doc and the script agree on exactly where the list goes, and add a test for billing-only plus source code.
There was a problem hiding this comment.
Confirmed and fixed in 024a44f. Both runs you named reproduced (ROUTE_GATE_FAIL … reason=missing, exit 1). The gate now treats a missing graviton_profile as "not yet known": it prints GATE_PASS … reason=not_yet_known | note=clarify_q11b_asks_architecture and exits 0, so billing-export + source code continues and Clarify Q11b asks for the architecture exactly as on main. ROUTE_GATE_FAIL is kept only for genuinely malformed input (a file that is not a JSON object, or a graviton_profile that is not an array), and GATE_NA for the AI-only route is unchanged. On the location: the fixtures, scripts/artifact-contracts.json (graviton_profile[]), the validator test and the workshop sheet all read the array at the top level, so top-level stays the one canonical write location; discover-app-graviton.md now says that explicitly (the old "into the GCP discovery metadata" prose was ambiguous), and the gate additionally accepts metadata.graviton_profile so a run that nested it still passes. Tests added for billing-only + source code, inventory with metadata.graviton_profile, missing profile → pass with reason, and the two malformed cases; discover.md Step 2 and schema-graviton.md updated to match.
| "secret_excludes": ["**/.env*", "**/credentials.json", "**/service-account.json", "**/*-service-account.json", "**/*.pem", "**/*.key", "**/*.p12", "**/*.pfx", "**/secrets.yaml", "**/secrets.yml"], | ||
| "vertex_strong_tokens": ["google_vertex_ai_", "google_vertex_ai"], | ||
| "ai_signals": { | ||
| "imports": ["google.cloud.aiplatform", "@google-cloud/aiplatform", "cloud.google.com/go/aiplatform", "com.google.cloud.aiplatform", "google.generativeai", "@google/generative-ai", "vertexai", "openai", "@anthropic-ai/sdk", "anthropic", "cohere", "mistralai", "google.cloud.documentai", "google.cloud.vision", "google.cloud.speech", "google.cloud.translate", "google.cloud.dialogflow", "langchain", "llama_index", "litellm", "langgraph", "crewai", "autogen", "strands", "pydantic_ai", "agno"], |
There was a problem hiding this comment.
Blocking (silent regression for GCP Gemini apps): The current Google GenAI SDK isn't in imports or dependencies. from google import genai, import { GoogleGenAI } from "@google/genai", and a google-genai dependency all return AI_CANDIDATE: false. On main, any source code ran app-code AI discovery, so these apps now lose the AI track with no error. Please add google.genai, the from google import genai form, @google/genai and google-genai, plus a test for each.
There was a problem hiding this comment.
Confirmed and fixed in 0854843. All forms reproduced as AI_CANDIDATE: false (from google import genai, import google.genai, import { GoogleGenAI } from "@google/genai", google-genai in requirements, @google/genai in package.json). The canonical skills/shared/migration/bma-input-patterns.json now has import tokens google.genai and @google/genai and dependency tokens google-genai and @google/genai; each form now reports AI_SIGNAL_CANDIDATE: true with the file listed in ai_signal_files, and from google import auth stays non-AI. The two runtime copies, closure.json, the bootstrap manifest and the two doc pins were regenerated with tools/sync-runtime-copies.py / tools/build-bma-closure.py rather than hand-edited, and lint:runtime-copy-parity / lint:bma-closure pass. One test per form plus the negative case were added to tests/test_bma_bootstrap.py.
| "openai": ("openai", "openai_api"), | ||
| "google": ("google", "vertex_ai"), | ||
| } | ||
| FAMILY_PREFIXES = (("claude", "claude"), ("gemini", "gemini"), ("gpt", "gpt"), ("o1", "gpt"), ("o3", "gpt"), ("text-embedding", "embedding")) |
There was a problem hiding this comment.
Blocking: imagen-3.0-generate-001 and o4-mini still fail with LEGACY_MODEL_FAMILY_UNKNOWN, and discover.md then stops the AI route. These worked on main, and Imagen is in this PR's own Gemini+Imagen fixture. Please add imagen and the o-series families (or degrade an unknown family to a per-model warning), with a test each.
There was a problem hiding this comment.
Confirmed and fixed in 0b9d0e5. imagen-3.0-generate-001, imagen-4.0-fast-generate-001 and o4-mini reproduced with LEGACY_MODEL_FAMILY_UNKNOWN. The adapter's FAMILY_PREFIXES now mirrors SOURCE_MODEL_FAMILY in bma-runtime.py: imagen* → family imagen (image output, which the BMA capability map and design-target already route to Stability), and o4* joins o1*/o3* on the gpt track per ai-openai-to-bedrock.md. We deliberately did not add a generic unknown-family downgrade — unrecognized model IDs are still rejected by name (e.g. mistral-large), which is a standing decision on this PR. Tests cover each new family (six IDs), an end-to-end conversion of the Gemini+Imagen fixture with imagen-3.0-generate-001 that validates against the #415 schema and validate-profile, and the still-rejected unknown case. The mapping row in gcp-ai-profile-415-mapping.md was updated.
|
|
||
| ## Part 2: Build Model Comparison Table | ||
|
|
||
| Calculate the monthly Bedrock cost for **every viable model** at the user's token volume. Source models with no Bedrock target mapping in `scripts/bma-runtime.py` (for example `gemini-1.5-pro`) get no target price, are labelled `lifecycle unverified`, and are excluded from generation. A target that is not listed as Active in the lifecycle registry is also unpriced, with retirement status unverified. |
There was a problem hiding this comment.
Blocking (GCP AI estimates come out unpriced): The registry this rule checks has 6 rows. 57 of the model IDs in the pricing cache aren't in it, so they get no price. That includes Nova Lite and Micro, Sonnet 5, Opus 5.5, titan-embed-text-v2 and stable-image-core (the new embedding and image defaults), and even the default's own global. and us.anthropic.claude-sonnet-5-5 IDs. Source models outside the 3-entry MODEL_TARGETS table also get no target. GCP AI estimates now run through this file, so they lose prices that they have on main. Please price from bedrock-pricing-cache.md as before, or make the registry cover every priced row before gating on it.
There was a problem hiding this comment.
Agreed on the defect: registered_active_models() does an exact-string lookup, so our own targets miss via the us./global. cross-region prefixes, and amazon.titan-embed-text-v2:0 / stability.stable-image-core-v1:0 were never in the 6-row table at all. We are not fixing it in this head because the shape of the fix changed with the scope split below: this PR's shared/ai edits (including that 6-row "Verified Active Models" table) are being reverted, and the lifecycle facts are moving to PR #500, whose registry already carries the full Active/Legacy/EOL table plus a new capability-constraints table. Once #500 lands and is merged into this branch, design-target will read lifecycle status (with CRIS-prefix normalization) from that registry rather than a BMA-private list, and a test will assert every emitted target resolves to an Active base model and is priced. The pricing rule itself (price iff target Active) is unchanged. For the record, 55 pricing-cache IDs are absent from the current 6-row table. Leaving this thread open until that lands.
There was a problem hiding this comment.
Update: this landed in this PR after all, in d7840f90. registered_active_models() / pricing_registry() now read Status, Tier and rates from the vendored bedrock-pricing-cache.md (with ai-model-lifecycle.md Legacy/EOL/Removed as exclusions) and normalize inference-profile prefixes (us., eu., au., apac., global., us-gov., jp.), so the CRIS-prefixed IDs and the embedding/image targets you listed are matched and priced. The 6-row BMA-private table is gone with the shared/ai revert. tests/test_bma_target_registry.py asserts every target design-target can emit resolves to an active, priced row. Pricing rule unchanged (price iff Active).
| } | ||
| CONTRIBUTION_FIELDS = {"id", "bucket", "source_order", "target", "kind", "content", "section"} | ||
| SECTION_ID = re.compile(r"^[a-z][a-z0-9-]*$") | ||
| ASSEMBLY_FIELDS = {"phase", "target", "contributions", "document", "report_mode"} |
There was a problem hiding this comment.
Blocking (GCP report reruns fail): GCP's combined migration-report.html and DECISION.md now have to be written through this assembly path, which can't replace an existing file. Delegated combined repro: the first assembly is OK, and the second fails with duplicate_final_write. Adding the prior hash fails with assembly_request_invalid because expected_sha256 isn't accepted here. On main, GCP can regenerate these reports. This is the same item leon1418 raised. Please accept expected_sha256 on assemblies and pass it to prepare.
There was a problem hiding this comment.
Confirmed and fixed in 90a96f3 — same root cause as leon1418's thread. Reproduced exactly: first assembly OK, rerun without hash duplicate_final_write, rerun with the prior hash assembly_request_invalid because expected_sha256 was not an accepted assembly field. Assembly requests now accept optional expected_sha256 and pass it to the same prepare path writes[] use, so a rerun with the file's current SHA-256 replaces migration-report.html / DECISION.md (and the other replaceable report targets); without the hash it still fails duplicate_final_write, a stale hash fails expected_prior_hash_mismatch, and the owner, owning-phase, downstream-authorization, same-request-duplicate and rollback protections are unchanged. The assembler ABI docs and the GCP report/decision phase docs (report-decision-core.md, generate-artifacts-report.md, generate-artifacts-docs.md, estimate.md decision-pack re-entry) now show passing the hash. Tests cover rerun with the correct hash (file replaced), without hash, wrong hash, hash on a missing target, and the delegated-mode DECISION.md rerun including the owning-phase guard.
|
|
||
| If the bootstrap check returns `ok: false`, stop before any state, telemetry, or artifact write. Report the exact `reason` value returned by the classifier, and do not fall back to a different route. The likely cause is line-ending normalization (for example, Git `core.autocrlf=true` on Windows) or a stale checkout. Fix it with a fresh checkout that uses LF line endings, or by reinstalling the plugin. | ||
|
|
||
| A noncandidate continues GCP-only and must not stat or resolve BMA. Only `AI_CANDIDATE: true` may resolve the exact sibling `<GCP_BASE>/../bedrock-migration-assessment` and rerun the same classifier with `--bma-base` before the first write. A missing or invalid sibling stops with `BEDROCK_MIGRATION_ASSESSMENT_SIBLING_MISSING` or `BMA_STANDALONE_CLOSURE_INVALID` and leaves project, run, telemetry, GCP, and BMA trees unchanged. `AI_CANDIDATE` requires AI evidence: an `ai_signals` match in source or manifest files (provider SDK import or dependency, AI endpoint host, provider env var name, or model identifier), explicit provider intent, Vertex-strong IaC, or a durable AI route. Candidate input preflights and scans through BMA once even if confidence later remains below 70%. `SOURCE_CONTAINING` is informational only: source files without AI evidence stay GCP-only with zero BMA operations, and pure source-free infrastructure performs zero BMA operations. Delegated BMA receives the existing `$MIGRATION_DIR`; GCP remains the only outer state, telemetry, combined Clarify, and combined report owner. |
There was a problem hiding this comment.
Blocking unless intended: With only gcp-to-aws installed, any GCP repo with AI evidence now stops with BEDROCK_MIGRATION_ASSESSMENT_SIBLING_MISSING, and llm-to-bedrock now needs three siblings. That works on main today. It is the per-skill install decision that #389 asks a maintainer to make, and that decision hasn't been made yet. Please get it recorded on #389 before merge, or keep a fallback for that install.
There was a problem hiding this comment.
Implemented option 2 in 972a8640. When bedrock-migration-assessment is not installed beside gcp-to-aws, a new stdlib resolver skills/gcp-to-aws/scripts/resolve-ai-track.py runs on the first classifier pass and decides:
- No AI evidence →
not_applicable; the sibling is never even stat'ed (pure infrastructure keeps doing zero BMA operations). - Sibling present →
active; the existing second classifier pass with--bma-baseruns exactly as before. A present-but-tampered sibling still fails closed withBMA_STANDALONE_CLOSURE_INVALID— that is not a deferral case andbma-route-classifier.pyis unchanged. - Sibling missing + infrastructure input (Terraform/billing in the repo, or a resumed run with
gcp-resource-inventory.json/billing-profile.json/live-capture/manifest.json) →deferred. The infrastructure migration proceeds; the AI track is deferred with an explicitdeferred_shared_ai_enginewarning, never silently dropped and never represented as generated. The decision is recorded once in$MIGRATION_DIR/ai-track.json(contract inreferences/shared/schema-ai-track.md, registered inartifact-contracts.json) and surfaces in the Discover preview, the Clarify assumption sheet, the decision report (exec-assumptionscallout), MIGRATION_GUIDE/README ("Deferred: AI workloads") and the migration report as a required<section id="deferred-surfaces">naming the missing skill and the install command. - Sibling missing + AI-only repo →
AI_TRACK_FAIL | code=bedrock_migration_assessment_missing_ai_only | missing_skill=bedrock-migration-assessment | detail=…, exit 1, since there is nothing else to migrate.llm-to-bedrockkeeps its stop for the same reason but now names the skill and the install command.
The report validator enforces it (--migration-dir): AI_DEFERRED_STATE_MISSING when the deferred section/callout is absent, AI_DEFERRED_BUT_AI_SECTIONS_PRESENT if appendix-ai/exec-tco appear anyway, AI_DEFERRED_IN_AI_ONLY_MODE, and AI_DEFERRED_WARNING_UNEXPECTED when the warning text appears without a deferred track. Behavioral coverage in tests/test_gcp_ai_track_fallback.py runs the resolver as a subprocess against a temp copy of skills/gcp-to-aws with the sibling genuinely absent (defer / AI-only fail / present-unchanged / tampered-still-fails / never-stats). This mirrors the resolve-ai-track.py + deferred-surfaces pattern already used by render-to-aws.
| @@ -32,7 +32,7 @@ Global is not available in GovCloud. Mantle uses the bare ID only in `us-east-1` | |||
| profile; a generic model name alone is insufficient. Other cache rows retain the | |||
| full-cache date at the top of this file. | |||
|
|
|||
| **Anthropic Claude (Standard on-demand)** figures below match **US East (N. Virginia)** on [Amazon Bedrock pricing](https://aws.amazon.com/bedrock/pricing/) as of cache refresh. **Recommend defaults (new migrations):** Claude Sonnet 5 (flagship), Claude Opus 5.5 (demanding reasoning), Claude Haiku 4.5 (cost/speed). Do not default to any Claude Fable / Mythos frontier model (Fable 5, Fable 5.1, and successors). **Claude Fable 5** and **Claude Fable 5.1** (GA Sep 1, 2026) are the most expensive Anthropic models (Mythos-class). Fable 5 is $10/$50 per 1M tokens, Global/base. Fable 5.1 is served via CRIS only (no in-region/bare-id form), with two supported profiles: **Global** (`global.anthropic.claude-fable-5-1`) at $10/$50 — supported from commercial `us-east-1` and a real option when there is no residency constraint — and **Geo US** (`us.anthropic.claude-fable-5-1`) at $11/$55 (~10% above Global), for workloads with US-only residency requirements. Quote whichever profile matches the actual deployment target; do not default to Geo pricing for a Global deployment. Fable 5.1's cache read is $0.25 (Global; 0.025x of Global input) or $0.275 (Geo); Fable 5's cache read is $1.00 (Global). Bedrock lists no batch rate for either. Both are Anthropic **Covered Models**: using them requires opting the account into the `aws_review` data-retention mode. In-region (non-CRIS) access for Fable 5.1 exists only in AWS GovCloud (US). Claude Mythos 5.1 is a gated Preview for vetted cyber/bio research organizations and is not a migration target. **Claude Opus 4.8** keeps the same $5/$25 rate as Opus 4.6/4.7. **Claude Sonnet 5** launched June 30 at $2/$10; that launch rate became the standard price on Sep 1, 2026 (the scheduled increase to $3/$15 was cancelled), so Sonnet 5 is now both newer and cheaper than Sonnet 4.6 ($3/$15). **Claude Opus 4.7** lists the same headline on-demand input/output as **Opus 4.6** on that page; confirm **batch** availability per model (Opus 4.7 batch was **not** listed on the global cross-region table when this row was added). **Claude Opus 4.1** entered **Legacy** on Jul 8, 2026 (EOL Jan 8, 2027). **Batch**, **prompt cache** (5m / 1h write + cache read), and **geo / in-region cross-region** rows on that page can differ; e.g. **US East (Ohio)** cross-region inference for Claude Sonnet 4.6 is listed at **$3.30 / $16.50** per 1M input/output (≈10% above N. Virginia). Long-context SKUs **do not** all use the same multiplier: **Sonnet 4.6** and **Opus 4.6** long-context modes share the same on-demand rates as the non–long-context rows on the standard table; **Sonnet 4.5** and **Sonnet 4** long-context rows are priced higher on that same table. | |||
| **Anthropic Claude (Standard on-demand)** figures below match **US East (N. Virginia)** on [Amazon Bedrock pricing](https://aws.amazon.com/bedrock/pricing/) as of cache refresh. **Recommend defaults (new migrations):** Claude Sonnet 5.5 (flagship; Sonnet 5 remains an explicit alternative), Claude Opus 5.5 (demanding reasoning), Claude Haiku 4.5 (cost/speed). Do not default to any Claude Fable / Mythos frontier model (Fable 5, Fable 5.1, and successors). **Claude Fable 5** and **Claude Fable 5.1** (GA Sep 1, 2026) are the most expensive Anthropic models (Mythos-class). Fable 5 is $10/$50 per 1M tokens, Global/base. Fable 5.1 is served via CRIS only (no in-region/bare-id form), with two supported profiles: **Global** (`global.anthropic.claude-fable-5-1`) at $10/$50 — supported from commercial `us-east-1` and a real option when there is no residency constraint — and **Geo US** (`us.anthropic.claude-fable-5-1`) at $11/$55 (~10% above Global), for workloads with US-only residency requirements. Quote whichever profile matches the actual deployment target; do not default to Geo pricing for a Global deployment. Fable 5.1's cache read is $0.25 (Global; 0.025x of Global input) or $0.275 (Geo); Fable 5's cache read is $1.00 (Global). Bedrock lists no batch rate for either. Both are Anthropic **Covered Models**: using them requires opting the account into the `aws_review` data-retention mode. In-region (non-CRIS) access for Fable 5.1 exists only in AWS GovCloud (US). Claude Mythos 5.1 is a gated Preview for vetted cyber/bio research organizations and is not a migration target. **Claude Opus 4.8** keeps the same $5/$25 rate as Opus 4.6/4.7. **Claude Sonnet 5** launched June 30 at $2/$10; that launch rate became the standard price on Sep 1, 2026 (the scheduled increase to $3/$15 was cancelled), so Sonnet 5 is now both newer and cheaper than Sonnet 4.6 ($3/$15). **Claude Opus 4.7** lists the same headline on-demand input/output as **Opus 4.6** on that page; confirm **batch** availability per model (Opus 4.7 batch was **not** listed on the global cross-region table when this row was added). **Claude Opus 4.1** entered **Legacy** on Jul 8, 2026 (EOL Jan 8, 2027). **Batch**, **prompt cache** (5m / 1h write + cache read), and **geo / in-region cross-region** rows on that page can differ; e.g. **US East (Ohio)** cross-region inference for Claude Sonnet 4.6 is listed at **$3.30 / $16.50** per 1M input/output (≈10% above N. Virginia). Long-context SKUs **do not** all use the same multiplier: **Sonnet 4.6** and **Opus 4.6** long-context modes share the same on-demand rates as the non–long-context rows on the standard table; **Sonnet 4.5** and **Sonnet 4** long-context rows are priced higher on that same table. | |||
There was a problem hiding this comment.
Production behavior change, out of scope: Editing the shared defaults (Sonnet 5.5 as the default here, and GPT-4o → GPT-6 Luna in ai-openai-to-bedrock.md) changes the recommendations from azure-to-aws, agent-advisor and gcp-to-aws through the vendored copies, 13 files outside BMA. That contradicts #389 ("no model mapping or pricing changes" in the extraction) and this PR's own "no Azure changes" note. Sonnet 5.5 also rejects forced tool_choice, so apps that rely on it would break after following the recommendation. Please move the defaults and pricing changes to a separate PR.
There was a problem hiding this comment.
Agreed, and splitting. The verified model facts from these edits (rates, IDs, lifecycle rows, and a new capability-constraints table that records, among other things, that Sonnet 5.5 accepts tool_choice auto/none only, which confirms your point) have moved to PR #500 at 0820cda5. The next push on this PR reverts every change under skills/shared/ai/ and the vendored twins back to main, and reverts the Q16/Q21/Q22 answer-table edits in the Clarify docs, so this PR carries no model-mapping or pricing changes per #389. Default/mapping-target changes ("Recommend defaults", "Best Bedrock Match", GPT-4o → GPT-6 Luna as a target) go to a separate mapping-guide PR after #500 merges. This PR will depend on #500 landing first.
…e as not yet known A missing graviton_profile no longer fails the Graviton route gate: billing-only Discover writes no inventory and the scan may not have emitted yet, so the gate reports GATE_PASS reason=not_yet_known and Clarify Q11b asks for the architecture (the main behavior). ROUTE_GATE_FAIL is kept for malformed input only (unreadable JSON, non-array graviton_profile). Top-level graviton_profile stays canonical; metadata.graviton_profile is accepted too. Review 5661016215, comment 4384076083.
Add import tokens google.genai and @google/genai and dependency tokens
google-genai and @google/genai to the canonical bma-input-patterns.json so
Gemini apps on the current Google GenAI SDK (from google import genai,
import { GoogleGenAI } from "@google/genai") are AI_CANDIDATE again, as on
main. Runtime copies, closure.json, bootstrap manifest and the two hand-set
doc pins are regenerated with tools/sync-runtime-copies.py and
tools/build-bma-closure.py. Review 5661016215, comment 4384076088.
…s in the GCP AI profile adapter imagen-* now resolves to the imagen family and the OpenAI o-series (o1/o3/o4 with -mini/-pro/-preview suffixes) to the gpt family, mirroring SOURCE_MODEL_FAMILY in bma-runtime.py. These ids worked on main and Imagen is in this PR's own Gemini+Imagen fixture; previously they failed with LEGACY_MODEL_FAMILY_UNKNOWN and discover.md stopped the AI route. No generic unknown-family downgrade: other ids are still rejected by name. Review 5661016215, comment 4384076090.
…eplace a final report Assembly requests may now carry an optional expected_sha256 that is passed to WriteAudit.prepare, so re-entering Estimate or Generate can regenerate migration-report.html, DECISION.md and the other replaceable report targets through the assembly path (as GCP does on main). Without the hash a rerun still fails duplicate_final_write; a stale hash fails expected_prior_hash_mismatch; owner, owning-phase, same-request-duplicate and rollback protections are unchanged. Assembler ABI docs and the GCP report/decision phase docs show the rerun-with-hash form. closure.json, bootstrap manifest and the doc pins are regenerated. Review 5661016215, comment 4384076096.
…Sonnet 5.5 Geo facts in pricing cache Facts harvested from PR aws#483 and re-verified 2026-10-26: - Stability AI heading scoped to US East (N. Virginia); Stable Image Core $0.04/image source note (AWS Stability price table, verified 2026-10-25; model card Active 2026-10-26) with the Gemini 3.1 Flash Image $30/1M image-token comparison price (Gemini API pricing). - Sonnet 5.5 Geo $2.20/$11.00 added to the Geo-multiplier note (listed directly on the pricing table, not derived). - GPT-6 Luna quick-ref Status cites the model card for the rates and the 272K short/long-context boundary. - Titan Text Embeddings v2 Status cites the model card (Active) and its absence from the pre-2026-09-07 lifecycle page; Tier cell untouched. Twins regenerated with tools/sync-vendored.py.
…ing cache
bma-runtime.py no longer reads the branch-only "Verified Active Models"
table or carries rate literals. pricing_registry() parses every
Status-bearing table of references/vendored/ai/bedrock-pricing-cache.md
(Model ID / Tier / Status / rates), normalizes inference-profile prefixes
(us-gov., global., apac., us., eu., au., jp.) onto the base model ID, and
applies the lifecycle Legacy / EOL table and Removed list as a fail-closed
exclusion. registered_active_models() keeps its name and frozenset return;
target_rates() supplies the (input, output) $/1M pair; design_target()
resolves embedding / image_generation by table + Tier (default; fast /
premium) with an unchanged output shape.
MODEL_TARGETS is now {source: (target, migration_path)} with three rows:
claude-3-haiku-20240307 -> anthropic.claude-haiku-4-5-20251001-v1:0,
gpt-4o -> openai.gpt-5.6-terra (restored from the Luna remap; matches the
vendored ai-openai-to-bedrock.md Option-A table), gemini-2.5-pro ->
amazon.nova-pro-v1:0. Haiku 4.5 is priced at the target's cache rate
(1.00 / 5.00) instead of the Claude 3 Haiku literal (0.25 / 1.25).
Tests: new tests/test_bma_target_registry.py (every emittable design
target and every MODEL_TARGETS target is active and priced; prefix
normalization; registry reads cache Status, not a hand list; CLI shape;
fail-closed when the cache is missing). test_bma_retired_models.py and
test_bma_direct_no_sidecar.py now derive rates from target_rates();
test_bma_artifact_equivalence.py compares against the regenerated
baseline. selected-base-semantic-projections.json regenerated by running
the runtime (gpt-4o 1M/1M -> 15.4, Haiku -> 6.0). Closure, bootstrap
manifests and the two doc pins regenerated.
…cing to main for aws#483 PR aws#483 is the bedrock-migration-assessment extraction. The model-default, mapping and pricing refreshes it carried belong to the pricing-refresh PR (aws#500) and are restored to upstream/main here; the BMA runtime commit before this one no longer depends on any of them. Reverted to main (skills/shared/ai, propagated to the four vendored twins with tools/sync-vendored.py): ai-anthropic-to-bedrock.md, ai-gemini-to-bedrock.md, ai-model-lifecycle.md (Last updated 2026-09-21, "Verified Active Models" table removed), ai-openai-to-bedrock.md (GPT-4o -> GPT-5.6 Terra), bedrock-pricing-cache.md, schema-design-aws-ai.md. Kept: skills/shared/ai/sdk-capability-map.json (+image_output_indicators, +image_output_model_patterns). bma-runtime.py::classify_ai_call reads both keys; they are detection patterns, not model facts, prices or defaults. Reverted to main wholesale: gcp-to-aws design-refs/ai-gemini-to-bedrock.md, discover-preview.md, shared/pricing-cache.md, shared/retarget-gotchas.md; azure-to-aws clarify-ai-only.md, estimate-ai.md, shared/pricing-cache.md; fixtures aws-design-ai/* and estimation-ai/* (4 files). Hand-reverted named-model lines only: gcp-to-aws clarify-assemble.md (7 rows) and generate-artifacts-report.md (rule 8), keeping the typed BMA contribution boundary, mantle-spelling and expected_sha256 hunks. BMA hand-adapted copies mirrored by hand (Sonnet 5.5 -> Sonnet 5, GPT-4o row -> GPT-5.6 Terra, Nano Banana / Sonnet 5.5 cache rows removed): clarify-ai.md, clarify-ai-only.md, design-ai.md, estimate-ai.md, discover-preview.md, design-refs/ai-gemini-to-bedrock.md (main GCP file + its one ai_sources[] header line), shared/pricing-cache.md and shared/retarget-gotchas.md (byte-equal to main's GCP files). All ai_sources[] / sidecar / direct-mode / input-gate adaptations kept. Deleted tests/test_bedrock_pricing_sonnet55.py (pinned the reverted facts). tests/test_bma_target_registry.py asserts Sonnet 5.5 is absent from the registry. Closure, bootstrap manifests and both doc pins regenerated. Facts move to PR aws#500.
…test The test asserted the runtime source no longer names the branch-only lifecycle table by its full heading, which made the plugin-wide grep for that heading (the acceptance check) match the test itself. Assert on the shorter substring instead; behaviour under test is unchanged.
…assessment is not installed Option 2 of PR aws#483 thread 4384076100 (vagmur-aws). When gcp-to-aws runs without its bedrock-migration-assessment sibling, a repository with AI evidence AND infrastructure input now proceeds with the infrastructure migration and defers the AI track explicitly, instead of stopping. Resolver contract (skills/gcp-to-aws/scripts/resolve-ai-track.py, stdlib, read-only unless --write-run-dir): consumes the first-pass classifier JSON and prints one canonical JSON line. not_applicable (no AI evidence; sibling never stat'ed), active (sibling present; second classifier pass with --bma-base runs exactly as before), deferred (sibling missing, terraform / billing / resume_artifacts evidence; reason bedrock_migration_assessment_missing, warning_code deferred_shared_ai_engine, install_hint). AI-only repository with the sibling missing: stderr `AI_TRACK_FAIL | code=bedrock_migration_assessment_missing_ai_only | missing_skill=bedrock-migration-assessment | detail=...`, exit 1. Record: $MIGRATION_DIR/ai-track.json written in discover.md Step 0 (item 7) with a contract in scripts/artifact-contracts.json (references/shared/schema-ai-track.md), so validate-artifacts.py reports no NO_CONTRACT and every later phase reads one file. Report: generate-artifacts-report.md gains the `deferred-surfaces` section spec (REQUIRED when deferred, forbidden otherwise), a TOC link and self-check item 21; report-decision-core.md requires one deferred_shared_ai_engine callout inside exec-assumptions in decision mode. scripts/validate-migration-report.py (and its byte-identical BMA copy) enforces it from --migration-dir: AI_DEFERRED_STATE_MISSING, AI_DEFERRED_BUT_AI_SECTIONS_PRESENT (appendix-ai / exec-tco), AI_DEFERRED_IN_AI_ONLY_MODE, AI_DEFERRED_WARNING_UNEXPECTED. `deferred-surfaces` joins OPTIONAL_SECTION_IDS; check 27 documented in references/shared/validate-migration-report.md. Phase docs: SKILL.md (route-sensitive section, Prerequisites bullet, file tree), discover.md (preflight resolver step, Step 0 record, Step 1b shim only when active, AI profile boundary skipped, Step 2 no AI artifact, Step 3 preview warning, handoff gate check 4, Step 4 message, output files), clarify.md / clarify-assemble.md (no AI fragment or BMA_AI_CLARIFY_RESULT, Assumption Sheet row, preferences.json without ai_constraints), design.md, estimate.md, generate.md, generate-artifacts-docs.md ("Deferred: AI workloads" subsection). Consumers: llm-to-bedrock keeps its stop (AI-only flow, nothing to proceed with) but names bedrock-migration-assessment and the install command; agent-advisor migration-plan Step -0.5 delegates the missing-BMA decision to the GCP resolver; README notes the deferral. Tampered sibling still fails closed: bma-route-classifier.py is unchanged and a present-but-invalid sibling still stops with BMA_STANDALONE_CLOSURE_INVALID (never deferred). Tests (tests/test_gcp_ai_track_fallback.py, resolver and classifier run as subprocesses against a temp skills tree with the sibling genuinely absent): test_sibling_missing_infra_repo_defers_ai_track_and_writes_record, test_sibling_missing_ai_only_repo_fails_naming_the_skill, test_sibling_present_resolves_active_and_second_pass_is_unchanged, test_no_ai_evidence_is_not_applicable_and_never_stats_sibling, test_tampered_sibling_is_not_deferred, test_report_validator_requires_deferred_surfaces_when_track_deferred, test_phase_docs_branch_on_ai_track, test_llm_to_bedrock_names_missing_bma_skill_and_keeps_stop, test_resolver_is_referenced_from_discover_and_skill. Regen chain: closure.json, both bma-bootstrap-manifest.json copies, and the manifest pin in SKILL.md / discover.md.
|
@vagmur-aws @leon1418 @shrugninreddy-hash ready for re-review at head All seven items from the 2026-10-27 review are addressed in-thread. In short: the route gate no longer fails on a missing Graviton profile; the google-genai SDK is detected; imagen and o-series families are recognized; report assemblies accept Merge order: #500 first, then this PR. The description's "Changes since the third review" section and Authorities hash table are refreshed. Threads left open for you to close. |
… 2026 (aws#500) * docs(aws-startup-advisor): refresh Bedrock model lifecycle for Oct 26 2026 Recompute exclusion-zone statuses against the AWS legacy lifecycle page, move past-EOL Claude Sonnet 4 to Removed, and mark newly Legacy models the plugin still references (Llama 4, Llama 3.3, DeepSeek, Sonnet 4.5) so agents stop treating them as Active defaults. Co-authored-by: Cursor <cursoragent@cursor.com> * docs(aws-startup-advisor): add Sonnet/Haiku 5.5 and DeepSeek V3.2 to pricing cache Price Claude Sonnet 5.5 and Haiku 5.5 (Global/Geo) from the Bedrock Anthropic tables without changing Haiku defaults, and surface DeepSeek V3.2 in the quick-reference Status table so US migrations stop reading only Legacy V3.1. Co-authored-by: Cursor <cursoragent@cursor.com> * docs(aws-startup-advisor): fix Haiku 5.5 100K tiers and Marengo 3.0 region scope Address PR 500 review: publish Haiku 5.5 ≤100K/>100K rates (incl. cache) for Global and US Geo so long prompts are not underpriced, and restore Marengo Embed 3.0 as the Active v2.7 replacement outside Seoul. Co-authored-by: Cursor <cursoragent@cursor.com> * docs(aws-startup-advisor): add Bedrock capability constraints table to model lifecycle registry Add a "Capability Constraints" fact table (lifecycle, context window, max output, forced tool_choice, image/audio input, image output, structured outputs) for Claude Sonnet 5.5 / Sonnet 5 / Haiku 4.5 / Haiku 5.5 / Opus 5.5, Nova Pro / Lite / Micro, and GPT-6 Luna, each cell read from the Bedrock model card on 2026-10-26 and marked _unverified_ where the card is silent. Add a neutral Rule 0 to Selection Rules: check capability constraints before tier/priority selection (no model named). Regenerate the gcp-to-aws and azure-to-aws vendored twins with tools/sync-vendored.py. * docs(aws-startup-advisor): cite verified Stability, Titan, Luna, and Sonnet 5.5 Geo facts in pricing cache Facts harvested from PR aws#483 and re-verified 2026-10-26: - Stability AI heading scoped to US East (N. Virginia); Stable Image Core $0.04/image source note (AWS Stability price table, verified 2026-10-25; model card Active 2026-10-26) with the Gemini 3.1 Flash Image $30/1M image-token comparison price (Gemini API pricing). - Sonnet 5.5 Geo $2.20/$11.00 added to the Geo-multiplier note (listed directly on the pricing table, not derived). - GPT-6 Luna quick-ref Status cites the model card for the rates and the 272K short/long-context boundary. - Titan Text Embeddings v2 Status cites the model card (Active) and its absence from the pre-2026-09-07 lifecycle page; Tier cell untouched. Twins regenerated with tools/sync-vendored.py. * docs(aws-startup-advisor): record verified model facts in Anthropic, OpenAI, and Gemini mapping guides Facts only; mapping targets and "Best Bedrock Match" cells are unchanged. - Anthropic guide: Sonnet 5 rate cells and the dagger footnote now state the current $2/$10 Global and $2.20/$11 Geo price (launch rate became standard Sep 1, 2026; $3/$15 increase cancelled) instead of the stale intro-pricing note; new fact sentence for Claude Sonnet 5.5 (IDs and us./eu./au./global. profiles, Active with launch/EOL-no-sooner-than dates, 1M/128K, rates, tool_choice auto/none only) citing the model card, verified 2026-10-26. - OpenAI guide: GPT-4o row notes OpenAI's 2026-10-14 deprecation, 2027-01-14 shutdown, and named successor gpt-6-luna (OpenAI deprecations page) plus Luna's Active Bedrock ID; cross-family target cell left as-is. - Gemini guide: new gemini-3.1-flash-image (Nano Banana 2) price row ($30/1M image tokens; $0.0336/1K image standard, $0.0168 batch) next to the existing imagen-* row, mirroring its Stable Image Core target cell; token-to-image equivalence marked _unverified_. Twins regenerated with tools/sync-vendored.py. * docs(aws-startup-advisor): drop Gemini 3.1 Flash Image row from the shared Gemini guide tests/test_gemini_guide_body_parity.py requires the shared Gemini guide body to be byte-identical to skills/gcp-to-aws/references/design-refs/ai-gemini-to-bedrock.md, which is outside this PR's edit scope. The Gemini 3.1 Flash Image price fact ($30/1M image tokens) stays recorded in bedrock-pricing-cache.md § Stability AI; the Gemini-guide row moves to the mapping-guide follow-up. Twins regenerated with tools/sync-vendored.py. --------- Co-authored-by: Logan Kleier <lkleier@amazon.com> Co-authored-by: Cursor <cursoragent@cursor.com>
|
This is a monstrously large PR. First pass agent adversarial review is reporting a few dozen contradictions. Ill comment on the High findings, but with a list that large I strongly urge you to run your own review against HEAD. After almost 60 additional commits, it appears that the expected behavior and functionality have drifted |
| if not evidence: | ||
| raise UsageError("bedrock_migration_assessment_missing_ai_only") | ||
| signal_files = classification.get("ai_signal_files") | ||
| return { |
There was a problem hiding this comment.
This isnt behaving how the PR description claims it should. Desc states "missing or tampered sibling fails closed with BEDROCK_MIGRATION_ASSESSMENT_SIBLING_MISSING or BMA_STANDALONE_CLOSURE_INVALID rather than silently degrading"
Your code fails silently.
| item["model_family"] not in source["model_families"] for item in source["model_observations"] | ||
| ): | ||
| raise ValueError("ai_profile_observation_mismatch") | ||
| # The mapping never derives "confirmed". The schema still lists it, so reject it here. |
There was a problem hiding this comment.
Schema still lists it, schema-discover-ai.md still allows it.
Description says user confirmation is removed. Seems like there is still a expected path that will set users in this now failing state.
Decide if confirmed is to remain or be removed, and reconcile the rest of your change to be consistent on that decision.
| | `"medium"` | 60M | 40M | 60/40 | | ||
| | `"high"` | 600M | 400M | 60/40 | | ||
| | `"very_high"` | 6B | 4B | 60/40 | | ||
|
|
There was a problem hiding this comment.
estimate phase is setting these tiers 10x what the clarify phase claims.
Low here is 6M in and 4M out. Low in clarify is < 1M
Have we tested these changes? I would expect that discrepancy to damage the quality of the outputs
|
Thank you for the detailed reviews. They exposed cross-contract inconsistencies after extensive scope drift: runtime behavior no longer consistently matches the schemas, phase documents, estimates, or this PR's description. At this size and history, adding more repair commits would make the change harder—not easier—to review with confidence. We are superseding #483 with a sequence of smaller, independently testable PRs tracked in #389: standalone BMA contract/core; design and estimate engine; GCP adapter/delegation; report assembly; then the consumer integrations. The useful tests and decisions from this branch will become requirements for those PRs, but implementations will be rebuilt from current Reviewers do not need to continue reviewing the current head. I am leaving the PR open momentarily for traceability; it will not be merged in its current form. |
|
Closing as superseded by the smaller replacement sequence documented in #389 (3a.1–3a.4). The branch and review history remain available as implementation evidence, but this PR will not be merged or used as a source of mechanically cherry-picked commits. Thank you to everyone who reviewed it and surfaced the cross-contract inconsistencies. |
Problem
Teams that only want to assess an AI workload for a move to Amazon Bedrock currently have no public skill for that. The assessment, design, cost-estimate, and generation-planning logic for OpenAI, Anthropic, Gemini/Vertex AI, OpenRouter, and agentic workloads lives inside
gcp-to-aws, so it is only reachable as part of a GCP migration. The existingllm-to-bedrockskill is the wrong fit for that need because it rewrites application code and evaluates output; it does not produce a standalone assessment. This also leaves the neutral AI logic without a single owner, which blocks later stages of issue #389.Fix
This PR adds a new public skill,
bedrock-migration-assessment, that runs the provider-neutral Discover, Clarify, Design, Estimate, and optional Generate-support-artifacts workflow on its own. It identifies AI call sites and provider/gateway/model provenance, captures permitted usage data, recommends Bedrock targets and regions, estimates cost, records decisions, and can generate migration-support artifacts. It does not rewrite application source;llm-to-bedrockremains the execution skill for SDK/code rewrites, output evaluation, and ready-to-merge delivery.gcp-to-awsnow delegates its AI track to the new skill through a route-sensitive bootstrap:bedrock-migration-assessment; they do not stat, resolve, or load it.SOURCE_CONTAININGis informational. A missing or tampered sibling fails closed withBEDROCK_MIGRATION_ASSESSMENT_SIBLING_MISSINGorBMA_STANDALONE_CLOSURE_INVALIDrather than silently degrading.gcp-to-awskeeps GCP infrastructure, live, and billing discovery, Vertex-specific adaptation, BigQuery handling, telemetry, outer run state, combined preferences, and combined report assembly.Input contract. BMA's only AI input is the #415
ai-workload-profile.jsoncontract (scripts/contracts/ai-workload-profile.schema.json, vendored byte-identically into the closure). Legacy GCP-shaped input is rejected by name (BmaLegacyProfileRejected). In delegated GCP runs, a deterministic adapter (gcp-ai-profile-adapter.py) converts GCP's legacy profile at the GCP boundary into a #415 document plus a temporary sidecar, written to a hidden.bma-input/location; GCP's publicai-workload-profile.jsonkeeps its legacy shape and name. The sidecar carries the fields #415 has no slot for (workloads, agentic profile, tool manifest, observed cost, integration context, per-model usage, Terraform AI resources) and is explicitly temporary pending a #415 schema-version follow-up that folds them in. Artifact names, routes, state transitions, and ownership boundaries are unchanged for every existing GCP route; AI design and estimate content for GCP runs does change where noted under "Changes since first review" below. The PR 449 target-onlyestimation-ai/generation-aicontracts keep theirsharedplusfixture_only:trueactivation. New safety behavior that reviewers should know about:gcp-to-awsand bound to the generated manifest by a test, so the two cannot drift silently.This advances issue #389 (stage 3a). It does not close that issue.
Changes since the third review (head
972a8640)Reverted — this PR carries no model-mapping or pricing changes (
96b263c5).skills/shared/ai/(ai-anthropic-to-bedrock.md,ai-gemini-to-bedrock.md,ai-model-lifecycle.md,ai-openai-to-bedrock.md,bedrock-pricing-cache.md,schema-design-aws-ai.md) and all four vendored twins are back tomain; so are the GCP/Azurepricing-cache.md,retarget-gotchas.md,discover-preview.md,design-refs/ai-gemini-to-bedrock.md, Azureclarify-ai-only.md/estimate-ai.md, the fouraws-design-ai/estimation-aifixtures, the Sonnet 5.5 rows inclarify-assemble.md/generate-artifacts-report.md, and the BMA hand-adapted clarify/design/estimate/discover-preview/pricing-cache/retarget-gotchas copies.tests/test_bedrock_pricing_sonnet55.pyis deleted. The onlyshared/aidiff left issdk-capability-map.json(+11 lines of image-output detection patterns the extraction needs; no model facts).BMA runtime reads the vendored pricing cache (
d7840f90,ddcf6bb0).registered_active_models()/pricing_registry()parse Status, Tier and rates frombedrock-pricing-cache.md(withai-model-lifecycle.mdLegacy/EOL + Removed as exclusions) and normalize inference-profile prefixes (us.,eu.,au.,apac.,global.,us-gov.,jp.).design_targetresolves embedding/image targets by table + Tier instead of ID literals (same three IDs).MODEL_TARGETSkeeps three source→target pairs with no rate literals;gpt-4o → openai.gpt-5.6-terra(matches main's OpenAI guide), Haiku 4.5 priced at the cache rate ($1.00/$5.00). Resolves review Item 4 (CRIS-prefixed IDs / default targets now matched and priced).Missing-sibling fallback, option 2 of the thread (
972a8640).skills/gcp-to-aws/scripts/resolve-ai-track.py+$MIGRATION_DIR/ai-track.json: with Terraform/billing input the infrastructure migration proceeds and the AI track is deferred with a validator-enforceddeferred_shared_ai_enginewarning (deferred-surfacesreport section,exec-assumptionscallout, guide subsection); an AI-only repo stops namingbedrock-migration-assessment; a tampered sibling still fails closed.llm-to-bedrockkeeps its stop but names the skill.Tests. Added
tests/test_bma_target_registry.py(6) andtests/test_gcp_ai_track_fallback.py(9); updatedtest_bma_retired_models.py,test_bma_direct_no_sidecar.py, regeneratedfixtures/bedrock-migration-assessment/selected-base-semantic-projections.jsonfrom the runtime; removedtest_bedrock_pricing_sonnet55.py. Plugin CI: 927 passed, 2 skipped; telemetry 280 passed.Hand-off to #500 (facts intentionally not in this PR):
bedrock-pricing-cache.md,ai-model-lifecycle.md) and the Sonnet 5 → 5.5 default/mapping rows across the guides and clarify/design/estimate docs.ai-openai-to-bedrock.md, clarify tables); after it lands,MODEL_TARGETS["gpt-4o"]follows.## Verified Active Models/ registry table inai-model-lifecycle.md(now superseded by reading the pricing cache; decide whether docs(aws-startup-advisor): refresh Bedrock model lifecycle for Oct 26 2026 #500 still wants it) and theLast updatedbump (lint:model-stalenessgoes stale 2026-11-05).gemini-3.1-flash-image (Nano Banana 2)→ Stable Image Core mapping row.MODEL_TARGETSliterals inbma-runtime.pywith the docs(aws-startup-advisor): refresh Bedrock model lifecycle for Oct 26 2026 #500 capability table.Merge order. This PR now depends on PR #500 (model lifecycle/pricing facts, incl. the capability-constraints table) merging first; the default/mapping-guide changes ("Recommend defaults", "Best Bedrock Match", Sonnet 5 → 5.5, GPT-4o → GPT-6 Luna) follow in a separate PR after both.
Changes since first review (head
fb1ba769)For reviewers who saw an earlier head. Every item below was approved explicitly during review and is recorded in the branch's decisions log; commits name the decision they implement.
Second-review follow-ups (head
fb1ba769).bma-input/document and sidecar instead of overwriting them (@vagmur-aws thread). Writer ownership table: public GCP profile →gcp-to-aws; both.bma-input/*files →bedrock-migration-assessment(@vagmur-aws thread).upstream/mainmerged (brings fix(aws-startup-advisor): isolate telemetry tests and skill attribution #499 telemetry isolation and fix(startup-advisor): align Lambda Event and Web Function guidance #442).bedrock-migration-assessmentis intentionally absent from the telemetrySKILL_IDSallowlist untilPluginSkillIdmodels it; the telemetry test records this inNOT_YET_MODELLEDso the directory check stays exact.Contract
Defaults and pricing (all rates verified against AWS Bedrock model cards / pricing page, cited in
skills/shared/ai/bedrock-pricing-cache.md)openai.gpt-6-luna(OpenAI's own recommended replacement in its 2026-10-14 deprecation notice; GPT-4o shuts down 2027-01-14). US Geo $0.11/$0.55, Global $0.10/$0.50. Replaces the earlier Terra mapping; guides and Clarify tables updated to match.anthropic.claude-haiku-4-5-20251001-v1:0.Lifecycle / retirement
ai-model-lifecycle.md, Verified Active table) is read at run time. A Bedrock target is priced only when it is listed Active there; an unregistered target getsretirement_status: unverifiedand no price.lifecycle unverified/observed, not priced from registry, and are excluded frommonthly_deltaso an unverified baseline is never presented as a verified comparison.Behavior fixes found by a before/after run on a real app
gemini-3.1-flash-image) now classify asimage_generationand route to Stability, never to a text model. Deterministic viabma-runtime.py design-target.gcp-route-gate.py):GATE_NAfor AI-only runs,ROUTE_GATE_FAILstops infrastructure runs.amazon.titan-embed-text-v2:0.confirm_reentryare enforced before any staged write; the"confirmed"evidence-confidence label is removed.section; HTML targets requirereport_mode. Bare contributions fail withdocument_required. This is a breaking change to the assembly contract.Known / deferred
gcp-to-aws/SKILL.md,discover.md) are hand-set to the generated bootstrap hash because no tool writes them; a test enforces equality. Generator is a follow-up.azure-to-aws's standaloneschema-design-aws-ai.md; out of this PR's scope (no Azure changes).Scope
Skills:
bedrock-migration-assessment(new, public),gcp-to-aws(delegation shims, bootstrap, pinned manifest hash), withllm-to-bedrockandagent-advisoronly preflighting the new sibling on GCP-selected migration routes. The plugin now exposes 13 public skills.Files: see
git diff --stat upstream/main...HEAD; the first-review count (141 paths) predates the changes listed above. The new skill's 66-file runtime closure,bma-runtime.py,bma-route-classifier.py, the content-contribution schema, bootstrap manifests inskills/shared/migration/and the GCP runtime copy, plugin and marketplace registration (plugin.json,marketplace.json), the pluginREADME.md,tests/test_bma_*.py, remote-smoke fixtures, and tooling (build-bma-closure.py,sync-runtime-copies.py,check-skill-refs.py).Base:
main. PR 449 merged on 2026-10-21 and this PR consumes those contracts without duplicating them. PR 369 also merged on 2026-10-21, and this branch has merged main to include it, so the PR 369 Bedrock model and API behavior is still present, now in the new skill. Open PR 459 overlaps this area; its note is in the reviewer block below.Validation
test_bma_bootstrap.pyand the seven-module contribution/runtime selection.llm-to-bedrocksuite 407 passed;agent-advisorsuite 562 passed.mise -C plugins/aws-startup-advisor run ciafter the merge, plus rootmise run validate,mise run build, andmise run security, all passed.sync-vendoredcovered 75 files.check-skill-refschecked 1570 references with 0 missing.96172042cd1a7a4f50d63e6e7594d882757026ef0f027b0acb802c11a3a3f5a8.Limitations
The equivalence harness carries its own copy of model-mapping, pricing, generated-file, and report-section rules. The Markdown phase files the agent executes do not read those tables. The harness therefore proves the extracted runtime matches the selected base as of this change, but will NOT detect a future edit to the Markdown that changes mappings, prices, or report composition. Reviewers must check such edits by hand until the tables are moved into shared data files consumed by both (tracked as a follow-up to issue #389).
Remote smoke could not independently observe tool or subagent absence (
tool_iterationsandsubagent_callswere null), and packet-level transport was not inspected. All 11 GitHub checks on the current head passed when last verified.Known issue:
scripts/check-bedrock-pricing-parity.pyexits non-zero on this branch withBedrock section changed during extraction. It is not part of CI, and it also failed on this branch's head before main was merged.For reviewers
File-level move and shim map
The neutral implementations move from GCP ownership into the new skill. These
gcp-to-awsfiles become delegation-only compatibility shims (binding and delegation logic only; no duplicate mapping, pricing, schema, writer, or fallback logic):discover-app-code.md(loaded only when preflight returnsAI_CANDIDATE: true),discover-openai-api.md,discover-anthropic-api.md,discover-openrouter-api.md.discover-app-graviton.mdis new and GCP-owned: Gravitongraviton_profileentries withsource: "app_code"are not delegated and are emitted for every source-containing GCP run.clarify-ai-only.mdand the neutral computation inclarify-ai.mddesign-ai.mdestimate-ai.mdgenerate-ai.md,generate-artifacts-ai.mdNo file was deleted and Git detects no rename; the move is additions plus modifications because the old paths must survive until later issue #389 stages repoint consumers. GCP phase controllers keep outer orchestration and load the BMA contribution once. Combined-only files (
clarify-assemble.md,generate-artifacts-docs.md,generate-artifacts-report.md,report-decision-core.md) stay GCP-owned. Classifier inputs and bootstrap metadata are synchronized across the canonical shared location, the GCP bootstrap copy, and the standalone BMA package.Ownership and one-writer behavior
plan.jsonhas one selected emitter.$MIGRATION_DIR; it cannot create another run, mint another ID, advance GCP outer state, emit GCP telemetry, or write combined wrappers.telemetry_owner: nullrather than misattributing activity.Overlap notes for open PRs
fix(startup-advisor): preserve Astra model and API across Bedrock migration) merged on 2026-10-21 (commit 7cf4fab). This branch merged main as merge commit 5b41eb6 (parents 74b479b and 7cf4fab), keeping the union of both sides. PR 369's neutral model/API behavior was ported intobedrock-migration-assessment(design, estimate, clarify, generate, discover-preview, andopenai-on-bedrock), and thegcp-to-awsfiles stay delegation-only shims. Where this PR's mechanism was the better design it was kept, and no PR 369 capability was dropped.feat(aws-startup-advisor): add credits and Azure plans) is open; GitHub currently reports no merge conflicts against main, but it still overlaps this area. Reconciliation must keep GCP Discover initialization and one-time notice ordering at the GCP owner, sync shared/vendored notices through canonical tooling, and refresh the byte-identical BMA copy of canonical plan-emitter changes.Authorities
closure.json96172042cd1a7a4f50d63e6e7594d882757026ef0f027b0acb802c11a3a3f5a8; self-hash08bada8b83a5b9f150838fb7597a44b86c31524fd2a7c2de5496982c59a00d95127d190a7c80c6bd39189064c6d4226a2f872d7b6dc66adef71b398c62065361; self-hashd30376bc2f88c420f810811cc0d65e243aa1112591e8bb8678625457bce52eaacontent-contribution.schema.json97e9dd312ec55695fd4c30a560a45e0672c843484702c85afe38be6513ee980abma-runtime.py87e7a9e98144df80ab45e4db62ee35d4345b7faf0250d136ab696626a348a50cComplete 66-entry runtime closure
Authoritative manifest:
plugins/aws-startup-advisor/skills/bedrock-migration-assessment/references/runtime/closure.json(schema 1, selected base9ab50636d12510dc351ff02fd7966efa4dba4341, a commit onmain:git merge-base --is-ancestor 9ab50636 upstream/mainexits 0). Source paths are relative toplugins/aws-startup-advisor/; destinations are relative to the new skill directory.skills/gcp-to-aws/SKILL.md→SKILL.md(adapted)references/runtime/bma-input-patterns.json(native)scripts/bma-route-classifier.py(native)scripts/bma-runtime.py(native)skills/gcp-to-aws/references/design-refs/ai-gemini-to-bedrock.md→references/design-refs/ai-gemini-to-bedrock.md(adapted)skills/gcp-to-aws/references/design-refs/ai.md→references/design-refs/ai.md(adapted)skills/gcp-to-aws/references/phases/clarify/clarify-ai-only.md→references/phases/clarify/clarify-ai-only.md(adapted)skills/gcp-to-aws/references/phases/clarify/clarify-ai.md→references/phases/clarify/clarify-ai.md(adapted)skills/gcp-to-aws/references/phases/design/design-ai.md→references/phases/design/design-ai.md(adapted)skills/gcp-to-aws/references/phases/discover/discover-anthropic-api.md→references/phases/discover/discover-anthropic-api.md(adapted)skills/gcp-to-aws/references/phases/discover/discover-app-code.md→references/phases/discover/discover-app-code.md(adapted)skills/gcp-to-aws/references/phases/discover/discover-openai-api.md→references/phases/discover/discover-openai-api.md(adapted)skills/gcp-to-aws/references/phases/discover/discover-openrouter-api.md→references/phases/discover/discover-openrouter-api.md(adapted)skills/gcp-to-aws/references/phases/discover/discover-preview.md→references/phases/discover/discover-preview.md(adapted)skills/gcp-to-aws/references/phases/estimate/estimate-ai.md→references/phases/estimate/estimate-ai.md(adapted)skills/gcp-to-aws/references/phases/generate/generate-ai.md→references/phases/generate/generate-ai.md(adapted)skills/gcp-to-aws/references/phases/generate/generate-artifacts-ai.md→references/phases/generate/generate-artifacts-ai.md(adapted)skills/gcp-to-aws/references/shared/handoff-gates.md→references/shared/handoff-gates.md(adapted)skills/gcp-to-aws/references/shared/migration-complexity.md→references/shared/migration-complexity.md(adapted)skills/gcp-to-aws/references/shared/openai-on-bedrock.md→references/shared/openai-on-bedrock.md(adapted)skills/gcp-to-aws/references/shared/pricing-cache.md→references/shared/pricing-cache.md(adapted)skills/gcp-to-aws/references/shared/pricing-fallback.md→references/shared/pricing-fallback.md(adapted)skills/gcp-to-aws/references/shared/retarget-gotchas.md→references/shared/retarget-gotchas.md(adapted)skills/gcp-to-aws/references/shared/schema-design-aws-ai.md→references/shared/schema-design-aws-ai.md(adapted)skills/gcp-to-aws/references/shared/schema-discover-ai.md→references/shared/schema-discover-ai.md(adapted)skills/gcp-to-aws/references/shared/schema-phase-status.md→references/shared/schema-phase-status.md(adapted)skills/gcp-to-aws/references/shared/schema-preferences.md→references/shared/schema-preferences.md(adapted)skills/gcp-to-aws/references/shared/validate-artifacts.md→references/shared/validate-artifacts.md(adapted)skills/gcp-to-aws/references/shared/validate-migration-report.md→references/shared/validate-migration-report.md(adapted)skills/shared/ai/ai-anthropic-to-bedrock.md→references/vendored/ai/ai-anthropic-to-bedrock.md(byte-identical)skills/shared/ai/ai-gemini-to-bedrock.md→references/vendored/ai/ai-gemini-to-bedrock.md(byte-identical)skills/shared/ai/ai-migration-guardrails.md→references/vendored/ai/ai-migration-guardrails.md(byte-identical)skills/shared/ai/ai-model-lifecycle.md→references/vendored/ai/ai-model-lifecycle.md(byte-identical)skills/shared/ai/ai-openai-to-bedrock.md→references/vendored/ai/ai-openai-to-bedrock.md(byte-identical)skills/shared/ai/ai-openrouter-to-bedrock.md→references/vendored/ai/ai-openrouter-to-bedrock.md(byte-identical)skills/shared/ai/bedrock-pricing-cache.md→references/vendored/ai/bedrock-pricing-cache.md(byte-identical)skills/shared/ai/bedrock-quotas.md→references/vendored/ai/bedrock-quotas.md(byte-identical)skills/shared/ai/design-ref-agentic-to-agentcore.md→references/vendored/ai/design-ref-agentic-to-agentcore.md(byte-identical)skills/shared/ai/design-ref-harness.md→references/vendored/ai/design-ref-harness.md(byte-identical)skills/shared/ai/sdk-capability-map.json→references/vendored/ai/sdk-capability-map.json(byte-identical)skills/shared/clarify/clarify-availability.md→references/vendored/clarify/clarify-availability.md(byte-identical)skills/shared/clarify/clarify-compliance.md→references/vendored/clarify/clarify-compliance.md(byte-identical)skills/shared/clarify/clarify-cost-appetite.md→references/vendored/clarify/clarify-cost-appetite.md(byte-identical)skills/shared/clarify/clarify-multicloud.md→references/vendored/clarify/clarify-multicloud.md(byte-identical)skills/shared/clarify/clarify-region.md→references/vendored/clarify/clarify-region.md(byte-identical)scripts/emit-plan-json.py→scripts/emit-plan-json.py(byte-identical)scripts/validate-migration-report.py→scripts/validate-migration-report.py(byte-identical)scripts/validate-startup-program-artifacts.py→scripts/validate-startup-program-artifacts.py(byte-identical)references/assemblers/decision-report.md(native)references/assemblers/migration-docs.md(native)references/assemblers/migration-report.md(native)references/phases/clarify/clarify.md(native)references/phases/design/design.md(native)references/phases/discover/discover.md(native)references/phases/estimate/estimate.md(native)references/phases/generate/generate.md(native)references/report-sections/ai-decision-report.md(native)references/report-sections/ai-guide.md(native)references/report-sections/ai-migration-report.md(native)references/report-sections/ai-readme.md(native)references/runtime/bedrock-region-map.json(native)references/runtime/bma-ai-clarify-result.schema.json(native)references/runtime/content-contribution.schema.json(native)references/runtime/plugin.json(native)references/shared/bma-ai-clarify-result.md(native)scripts/contracts/ai-workload-profile.schema.json→references/contracts/ai-workload-profile.schema.json(byte-identical; the test(aws-startup-advisor): define neutral AI workload profile #415 input contract)Type of Change
Select at least one.
Startup Advisor review checklist
By submitting this PR, I confirm that:
mise -C plugins/aws-startup-advisor run ciand all checks pass.The first confirmation is left for the author to check after personally reading the 141-path diff; the other three are backed by the Validation and Limitations sections above.
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.