llm-to-bedrock
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseMigrate to Bedrock (Assess + Execute)
迁移到Bedrock(评估+执行)
Single-command AI migration: OpenAI / Gemini / Anthropic → Amazon Bedrock.
The skill base directory is given in the "Base directory for this skill: X" line the harness
emits at load time. Call it . Derived paths:
<SKILL_BASE>- =
$SCRIPTS<SKILL_BASE>/scripts - =
$HELPERS(the former helper skills, now references)<SKILL_BASE>/references/helpers
一键式AI迁移:OpenAI / Gemini / Anthropic → Amazon Bedrock。
技能基础目录由加载时工具输出的「Base directory for this skill: X」行给出,记为。派生路径:
<SKILL_BASE>- =
$SCRIPTS<SKILL_BASE>/scripts - =
$HELPERS(原辅助技能,现为参考文件)<SKILL_BASE>/references/helpers
Step 0 — Check prerequisites
步骤0 — 检查先决条件
0a. Check that uv
is available
uv0a. 检查uv
是否可用
uvbash
uv --version 2>/dev/null || echo "MISSING"If missing: "Install uv first — see the official install guide: https://docs.astral.sh/uv/getting-started/installation/ (e.g. or )". Stop.
brew install uvpipx install uvbash
uv --version 2>/dev/null || echo "MISSING"如果缺失:请先安装uv——参考官方安装指南:https://docs.astral.sh/uv/getting-started/installation/(例如`brew install uvpipx install uv`)。停止操作。
或Step 1 — Collect source code path
步骤1 — 收集源代码路径
If contains a path, use it as . Otherwise use AskUserQuestion:
"Where is your source code? Enter a local path or GitHub URL."
$ARGUMENTS$REPOIf a GitHub URL, it to a temp dir; use that path as .
git clone$REPOChecks on $REPO:
-
Git-root check (compare resolved paths — on macOSresolves to
/tmp, so a raw string comparison false-positives):/private/tmpbash[ "$(git -C <REPO> rev-parse --show-toplevel 2>/dev/null)" = "$(cd <REPO> && pwd -P)" ] && echo GIT_ROOT_OK || echo GIT_ROOT_MISMATCH- → proceed.
GIT_ROOT_OK - and the command errored (not a git repo at all) → tell the user the path must be a git repository (the deliverable is a git branch); re-ask.
GIT_ROOT_MISMATCH - but inside a repo (user pointed at a subdirectory) → AskUserQuestion: "Use the repo root instead" (recommended) / "Continue with this subdirectory" / "Abort".
GIT_ROOT_MISMATCH
-
Dirty-tree check:bash
git -C <REPO> status --porcelainIf uncommitted changes exist, show them and AskUserQuestion: "Continue anyway" or "Let me clean up first".
Record for all subsequent steps.
$REPO如果包含路径,则将其用作。否则使用AskUserQuestion询问:
"你的源代码在哪里?请输入本地路径或GitHub URL。"
$ARGUMENTS$REPO如果是GitHub URL,使用将其克隆到临时目录;将该路径用作。
git clone$REPO对$REPO的检查:
-
Git根目录检查(比较解析后的路径——在macOS上会解析为
/tmp,因此原始字符串比较会出现误判):/private/tmpbash[ "$(git -C <REPO> rev-parse --show-toplevel 2>/dev/null)" = "$(cd <REPO> && pwd -P)" ] && echo GIT_ROOT_OK || echo GIT_ROOT_MISMATCH- → 继续。
GIT_ROOT_OK - 且命令报错(根本不是git仓库)→ 告知用户路径必须是git仓库(交付物是git分支);重新询问。
GIT_ROOT_MISMATCH - 但位于仓库内(用户指向子目录)→ 使用AskUserQuestion询问: "改用仓库根目录"(推荐)/ "继续使用此子目录" / "中止"。
GIT_ROOT_MISMATCH
-
脏树检查:bash
git -C <REPO> status --porcelain如果存在未提交的更改,显示这些更改并使用AskUserQuestion询问:"继续操作"或"我先清理一下"。
记录供后续所有步骤使用。
$REPOPhase A — Assess (MANDATORY: delegate to the gcp-to-aws skill)
阶段A — 评估(必填:委托给gcp-to-aws技能)
CRITICAL: You MUST use the Skill tool to invoke (a sibling skill
in this same plugin). Do NOT perform the Assess phase yourself. Do NOT read source code, detect
AI SDKs, or ask Clarify questions manually. The entire Assess phase is handled by the gcp-to-aws
skill — you only invoke it and wait for completion.
migration-to-aws:gcp-to-aws关键:必须使用Skill工具调用(此插件中的同级技能)。请勿自行执行评估阶段。请勿手动读取源代码、检测AI SDK或提出澄清问题。整个评估阶段由gcp-to-aws技能处理——你只需调用它并等待完成。
migration-to-aws:gcp-to-awsA1 — Invoke the Assess skill
A1 — 调用评估技能
Call the Skill tool with skill name .
migration-to-aws:gcp-to-awsBefore invoking, tell the user:
"I'm now invoking the gcp-to-aws Assess skill to discover your AI workloads and design the Bedrock migration. It will ask you some questions — please answer them. (Don't be confused by the skill'sname — it also covers pure AI/LLM migrations with no GCP or infrastructure component, which is how it's being used here.)"gcp-to-aws
After invoking the Skill tool, the skill instructions will load into context.
Follow those instructions exactly — they will drive the Discover, Clarify, Design, Estimate,
and Generate phases. The source code to scan is at .
gcp-to-aws$REPOImportant context for the gcp-to-aws skill execution:
- Source code is at — when the skill asks for GCP sources or scans for files, point it there
$REPO - This is an AI/LLM workload migration — the AI path is the goal
- Unless Terraform/IaC files are actually present in , skip IaC discovery
$REPO - Unless the user offers billing data, skip billing discovery. If the source provider is
OpenAI, the skill may instead offer its OpenAI Admin API usage discovery
(— read-only, consent-gated, needs an Admin key with Usage set to Read); accepting it gives Estimate real spend and token volumes without manual CSV exports
discover-openai-api.md
使用技能名称调用Skill工具。
migration-to-aws:gcp-to-aws调用前告知用户:
"我现在将调用gcp-to-aws评估技能来发现你的AI工作负载并设计Bedrock迁移方案。它会向你提出一些问题——请回答。(不要被技能的名称混淆——它也适用于没有GCP或基础设施组件的纯AI/LLM迁移,本次就是这样使用的。)"gcp-to-aws
调用Skill工具后,技能的指令将加载到上下文中。严格遵循这些指令——它们将驱动发现、澄清、设计、估算和生成阶段。要扫描的源代码位于。
gcp-to-aws$REPOgcp-to-aws技能执行的重要上下文:
- 源代码位于——当技能请求GCP源或扫描文件时,指向该路径
$REPO - 这是AI/LLM工作负载迁移——AI路径是目标
- 除非中实际存在Terraform/IaC文件,否则跳过IaC发现
$REPO - 除非用户提供计费数据,否则跳过计费发现。如果源提供商是OpenAI,技能可能会提供其OpenAI Admin API使用情况发现(——只读,需要同意,需要将Usage设置为Read的Admin密钥);接受它无需手动导出CSV即可获得估算的实际支出和令牌量
discover-openai-api.md
A2 — Wait for Assess completion
A2 — 等待评估完成
The skill is a state machine. After each phase completes, it may stop and wait
for the next invocation. Check progress against the LATEST run directory only (older
runs may contain a stale "completed" status):
gcp-to-aws.migration/bash
MIGRATION_DIR=$(ls -td "$REPO/.migration"/*/ 2>/dev/null | head -1)gcp-to-aws.migration/bash
MIGRATION_DIR=$(ls -td "$REPO/.migration"/*/ 2>/dev/null | head -1)Stdlib-only JSON read — no boto3, so bare python3 is fine here (no pinned env needed).
仅使用标准库读取JSON——无需boto3,因此纯python3即可(无需固定环境)。
python3 -c "import json,sys; print(json.load(open('$MIGRATION_DIR/.phase-status.json'))['phases'].get('generate','missing'))" 2>/dev/null || echo "no-status-file"
- `completed` → proceed to A3.
- Anything else (including `no-status-file`) → the skill needs to run again. Re-invoke
`migration-to-aws:gcp-to-aws` via the Skill tool — it picks up where it left off.
**Cap: at most 6 re-invocations.** If `generate` is still not `completed` after 6, stop and
show the user the last status output — the Assess skill is stuck and needs manual attention;
looping further just burns context.python3 -c "import json,sys; print(json.load(open('$MIGRATION_DIR/.phase-status.json'))['phases'].get('generate','missing'))" 2>/dev/null || echo "no-status-file"
- `completed` → 进入A3。
- 其他任何情况(包括`no-status-file`)→ 需要重新运行技能。通过Skill工具重新调用`migration-to-aws:gcp-to-aws`——它会从上次中断的地方继续。
**上限:最多重新调用6次。**如果6次后`generate`仍未变为`completed`,则停止并向用户显示最后一次状态输出——评估技能已卡住,需要手动干预;继续循环只会消耗上下文资源。A3 — Locate Assess output
A3 — 定位评估输出
Find (the directory that was created):
$MIGRATION_DIR.migration/<MMDD-HHMM>/bash
ls -td "$REPO/.migration"/*/ 2>/dev/null | head -1Verify these files exist in :
$MIGRATION_DIR- (model mapping + architecture)
aws-design-ai.json - (detected workloads)
ai-workload-profile.json - (user preferences from Clarify)
preferences.json
If is missing, Assess did not complete the AI path correctly. Show the
error and stop.
aws-design-ai.json找到(即创建的目录):
$MIGRATION_DIR.migration/<MMDD-HHMM>/bash
ls -td "$REPO/.migration"/*/ 2>/dev/null | head -1验证中存在以下文件:
$MIGRATION_DIR- (模型映射+架构)
aws-design-ai.json - (检测到的工作负载)
ai-workload-profile.json - (来自澄清阶段的用户偏好)
preferences.json
如果缺失,则评估未正确完成AI路径。显示错误并停止。
aws-design-ai.jsonPhase B — Execute Prep
阶段B — 执行准备
B1 — Read Assess outputs
B1 — 读取评估输出
Read and extract:
$MIGRATION_DIR/aws-design-ai.json- → array of
ai_architecture.bedrock_models[]{source_model, aws_model_id, use_case} - Collect all values into
aws_model_id(array). Keep the$TARGET_MODELSof each: the preflight script probes each model by the right API automatically (Converse for chat, InvokeModel for embeddings), but the evaluator's quality scoring only applies to chat models — embedding targets get format/dimension validation only.use_case
Read and extract:
$MIGRATION_DIR/ai-workload-profile.json- → source provider
summary.ai_source
Read and extract:
$MIGRATION_DIR/preferences.json- →
design_constraints.target_region(default$REGIONif absent)us-east-1
Validation: If has no array, or the
array is empty, STOP: "Assess output incomplete — model mapping missing."
aws-design-ai.jsonai_architecture.bedrock_models[]读取并提取:
$MIGRATION_DIR/aws-design-ai.json- →
ai_architecture.bedrock_models[]数组{source_model, aws_model_id, use_case} - 将所有值收集到
aws_model_id(数组)中。保留每个模型的$TARGET_MODELS:预飞脚本会自动通过正确的API探测每个模型(聊天使用Converse,嵌入使用InvokeModel),但评估器的质量评分仅适用于聊天模型——嵌入目标仅进行格式/维度验证。use_case
读取并提取:
$MIGRATION_DIR/ai-workload-profile.json- → 源提供商
summary.ai_source
读取并提取:
$MIGRATION_DIR/preferences.json- →
design_constraints.target_region(如果缺失,默认$REGION)us-east-1
**验证:**如果没有数组,或数组为空,停止操作:"评估输出不完整——模型映射缺失。"
aws-design-ai.jsonai_architecture.bedrock_models[]B2 — AWS identity confirmation
B2 — AWS身份确认
bash
aws sts get-caller-identity 2>&1If the command fails (no credentials, expired SSO token): show the error and tell the user
to run or (suggest typing to run it in this
session), then re-run B2. Do not proceed without a confirmed identity.
aws configureaws sso login! aws sso loginOn success, show Account, Arn, UserId via AskUserQuestion:
"This AWS identity will be used for Bedrock calls. Is this correct?"
Options:
- Yes, use this identity → proceed
- Use a different AWS profile → ask which profile, record it as , re-run B2 as
$AWS_PROFILE_CHOICE, and re-confirm. Do NOT rely on exportingaws sts get-caller-identity --profile $AWS_PROFILE_CHOICE— env vars do not persist across Bash tool calls or into workflow subagents (see B3). Instead pass the choice explicitly everywhere:AWS_PROFILEon every aws CLI call, and prepend--profileinline on the B4 preflight command and inside the workflow args (AWS_PROFILE=$AWS_PROFILE_CHOICEfield) so subagents can do the same.awsProfile
Also confirm region: "Bedrock region will be . OK or override?"
$REGIONbash
aws sts get-caller-identity 2>&1如果命令失败(无凭据、SSO令牌过期):显示错误并告知用户运行或(建议输入在此会话中运行),然后重新运行B2。未确认身份前请勿继续。
aws configureaws sso login! aws sso login成功后,通过AskUserQuestion显示账户、Arn、UserId:
"此AWS身份将用于Bedrock调用。是否正确?"
选项:
- 是,使用此身份 → 继续
- 使用其他AWS配置文件 → 询问配置文件名称,将其记录为,使用
$AWS_PROFILE_CHOICE重新运行B2,并重新确认。 请勿依赖导出aws sts get-caller-identity --profile $AWS_PROFILE_CHOICE——环境变量不会在Bash工具调用之间或工作流子Agent中持久化(见B3)。而是在所有地方显式传递选择:在每个aws CLI调用上添加AWS_PROFILE,并在B4预飞命令和工作流参数(--profile字段)中内联添加awsProfile,以便子Agent也能这样做。AWS_PROFILE=$AWS_PROFILE_CHOICE
同时确认区域:"Bedrock区域将设置为。确认还是修改?"
$REGIONB3 — Source API key (optional)
B3 — 源API密钥(可选)
First, create the artifact directory and make it self-ignoring IMMEDIATELY — before any key
exists, so the secret is never sitting in an unignored working tree (even if the user aborts
before the rewriter runs):
bash
mkdir -p "$REPO/.saws-migrate" && printf '*\n' > "$REPO/.saws-migrate/.gitignore"Determine from B1's source provider (this is the env-var name the baseline
skill's parser expects — a bare key without the prefix will NOT be parsed):
$KEY_ENV_VARNAME=- →
openaiOPENAI_API_KEY - →
anthropicANTHROPIC_API_KEY - /
google→geminiGEMINI_API_KEY
The key must never enter this conversation (HARD RULE). Do not ask the user to paste the
key in chat, and never echo, cat, or interpolate its VALUE into any command, question, or
output — the agent only ever handles the file path. If the user pastes a key into the chat
unprompted, do not use it: tell them it is now part of the transcript, recommend rotating it,
and continue with one of the paths below.
First check whether the key is already present in the shell environment (each Bash call
initializes from the user's profile, so a profile-exported key is visible to every call).
POSIX-safe — works in bash and zsh alike ( indirection is bash-only and
zsh errors on it). This prints presence only, never the value:
printenv${!VAR}bash
[ -n "$(printenv "$KEY_ENV_VAR")" ] && echo ENV_KEY_PRESENT || echo ENV_KEY_ABSENTAskUserQuestion: "Do you have an API key for the source model (e.g. OpenAI key for GPT-4o)?
Providing it enables side-by-side quality comparison. Without it, evaluation uses absolute scoring only."
Options (offer the first only on ):
ENV_KEY_PRESENT-
Use thealready in my environment → materialize env var to file in one command — the value never appears in the transcript:
$KEY_ENV_VARbashprintf '%s=%s\n' "$KEY_ENV_VAR" "$(printenv "$KEY_ENV_VAR")" > "$REPO/.saws-migrate/.source-provider-env" && chmod 600 "$REPO/.saws-migrate/.source-provider-env"Then run the format check below and set,sourceBaselineAvailable = true.sourceKeyRef = "$REPO/.saws-migrate/.source-provider-env" -
I'll write it to a file myself → give the user this command to run in THEIR OWN terminal (not through the agent; in Claude Code anprefix runs it in-session) —
!collects the key without echoing it:read -rsbashread -rs k && printf '%s=%s\n' "<KEY_ENV_VAR>" "$k" > "<REPO>/.saws-migrate/.source-provider-env" && chmod 600 "<REPO>/.saws-migrate/.source-provider-env" && unset kSubstitute the literal env-var name and repo path when presenting it (those are not secrets). Then run the format check below and set the same flags as above. -
Skip →,
sourceBaselineAvailable = false.sourceKeyRef = ""
Whichever path wrote the file, verify the format (never prints the key; catches a value
written without the prefix, which the baseline parser would silently miss):
NAME=bash
grep -qE '^(OPENAI|ANTHROPIC|GEMINI)_API_KEY=.+' "$REPO/.saws-migrate/.source-provider-env" && echo KEY_FORMAT_OK || echo KEY_FORMAT_BADOn , have the same path that wrote the file rewrite it (do not echo its
contents).
KEY_FORMAT_BAD( is already self-ignoring from the first command above; the rewriter
re-asserts this before any commit as a second layer.)
.saws-migrate/IMPORTANT: The file is the handoff mechanism — do NOT rely on to carry the key
into later steps. Shell state set in one Bash call does not persist into other calls or into
workflow subagents; only a profile-exported variable (the path above) is
reliably visible, and even that must be materialized to the file for the baseline runner.
exportENV_KEY_PRESENT首先,立即创建工件目录并设置自忽略——在任何密钥存在之前,确保密钥永远不会存放在未被忽略的工作树中(即使用户在重写器运行前中止):
bash
mkdir -p "$REPO/.saws-migrate" && printf '*\n' > "$REPO/.saws-migrate/.gitignore"根据B1中的源提供商确定(这是基线技能解析器期望的环境变量名称——不带前缀的裸密钥将不会被解析):
$KEY_ENV_VARNAME=- →
openaiOPENAI_API_KEY - →
anthropicANTHROPIC_API_KEY - /
google→geminiGEMINI_API_KEY
**密钥绝不能进入此对话(硬性规则)。**请勿要求用户在聊天中粘贴密钥,永远不要在任何命令、问题或输出中回显、打印或插入其值——Agent仅处理文件路径。如果用户未经提示将密钥粘贴到聊天中,请勿使用:告知用户它已成为对话记录的一部分,建议轮换密钥,然后继续以下路径之一。
首先检查密钥是否已存在于shell环境中(每次Bash调用都会从用户配置文件初始化,因此配置文件中导出的密钥对每个调用都可见)。符合POSIX标准——在bash和zsh中都有效(间接引用仅适用于bash,zsh会报错)。此命令仅打印存在性,绝不打印值:
printenv${!VAR}bash
[ -n "$(printenv "$KEY_ENV_VAR")" ] && echo ENV_KEY_PRESENT || echo ENV_KEY_ABSENTAskUserQuestion询问: "你有源模型的API密钥吗(例如GPT-4o的OpenAI密钥)?提供密钥可实现并排质量比较。没有密钥的话,评估仅使用绝对评分。"
选项(仅当时提供第一个选项):
ENV_KEY_PRESENT-
使用我环境中已有的→ 通过一个命令将环境变量写入文件——值永远不会出现在对话记录中:
$KEY_ENV_VARbashprintf '%s=%s\n' "$KEY_ENV_VAR" "$(printenv "$KEY_ENV_VAR")" > "$REPO/.saws-migrate/.source-provider-env" && chmod 600 "$REPO/.saws-migrate/.source-provider-env"然后运行下面的格式检查,并设置,sourceBaselineAvailable = true。sourceKeyRef = "$REPO/.saws-migrate/.source-provider-env" -
我会自己写入文件 → 给用户此命令让他们在自己的终端中运行(不是通过Agent;在Claude Code中前缀会在会话中运行)——
!会收集密钥而不回显:read -rsbashread -rs k && printf '%s=%s\n' "<KEY_ENV_VAR>" "$k" > "<REPO>/.saws-migrate/.source-provider-env" && chmod 600 "<REPO>/.saws-migrate/.source-provider-env" && unset k呈现时替换实际的环境变量名称和仓库路径(这些不是机密)。然后运行下面的格式检查,并设置与上述相同的标志。 -
跳过 →,
sourceBaselineAvailable = false。sourceKeyRef = ""
无论通过哪种路径写入文件,都要验证格式(绝不打印密钥;捕获未添加前缀的写入值,这会被基线解析器忽略):
NAME=bash
grep -qE '^(OPENAI|ANTHROPIC|GEMINI)_API_KEY=.+' "$REPO/.saws-migrate/.source-provider-env" && echo KEY_FORMAT_OK || echo KEY_FORMAT_BAD如果是,让写入文件的同一路径重新写入(不要回显其内容)。
KEY_FORMAT_BAD(已通过上面的第一个命令设置为自忽略;重写器在任何提交前会再次确认这一点,作为第二层保障。)
.saws-migrate/**重要:**文件是传递机制——请勿依赖将密钥带入后续步骤。在一个Bash调用中设置的shell状态不会持久化到其他调用或工作流子Agent中;只有配置文件中导出的变量(上述路径)是可靠可见的,即使如此也必须将其写入文件供基线运行器使用。
exportENV_KEY_PRESENTB4 — Bedrock preflight
B4 — Bedrock预飞检查
bash
uv run --project $SCRIPTS python $SCRIPTS/preflight_bedrock.py --region $REGION --models <comma-separated $TARGET_MODELS> --dataset-size 200( matches the golden-dataset cap, so the quota warning reflects the worst case. Prefix with if B2 chose a non-default profile.)
--dataset-size 200AWS_PROFILE=$AWS_PROFILE_CHOICEParse the JSON output. On failure the TOP LEVEL carries / (lifted from the
first failing model) plus (all failing ids); per-model verdicts are in :
reasondetailfailing_modelsmodels[]- +
ok == false→ show the detail (configure/refresh credentials), stop; user re-runs after fixing.reason: credentials - +
ok == false→ model access not enabled in the Bedrock console (NOT an IAM problem): point the user at the console Model access page for the failing models, stop; re-run B4 after they enable it.reason: model_access - +
ok == false→ IAM deniesreason: authz: tell user the IAM action to grant; stop.bedrock:InvokeModel - +
ok == false→ Read thereason: model_unavailablereference atresolve-bedrock-model-idand follow its procedure with each ID from$HELPERS/resolve-bedrock-model-id/resolve-bedrock-model-id.md+ region. AskUserQuestion with the candidates: "Usefailing_models(cross-region inference profile)" / "Paste a different model ID" / "Abort". On a choice, replace the ID in<candidate>and re-run B4.$TARGET_MODELS - + any other
ok == false→ showreasonand stop.detail - → proceed. Surface any
ok == true, and any model whosequota_warningisreason(embedding family the preflight can't probe — remind the user to confirm model access in the console).embedding_unprobed
bash
uv run --project $SCRIPTS python $SCRIPTS/preflight_bedrock.py --region $REGION --models <comma-separated $TARGET_MODELS> --dataset-size 200(与黄金数据集上限匹配,因此配额警告反映最坏情况。如果B2选择了非默认配置文件,前缀添加。)
--dataset-size 200AWS_PROFILE=$AWS_PROFILE_CHOICE解析JSON输出。失败时,顶层包含/(来自第一个失败模型)以及(所有失败的ID);每个模型的结果在中:
reasondetailfailing_modelsmodels[]- +
ok == false→ 显示详细信息(配置/刷新凭据),停止;用户修复后重新运行。reason: credentials - +
ok == false→ 未在Bedrock控制台启用模型访问(不是IAM问题):将用户指向失败模型的控制台模型访问页面,停止;启用后重新运行B4。reason: model_access - +
ok == false→ IAM拒绝reason: authz:告知用户需要授予的IAM操作;停止。bedrock:InvokeModel - +
ok == false→ 阅读reason: model_unavailable中的$HELPERS/resolve-bedrock-model-id/resolve-bedrock-model-id.md参考,并对resolve-bedrock-model-id中的每个ID和区域执行其流程。使用AskUserQuestion提供候选选项:"使用failing_models(跨区域推理配置文件)" / "粘贴其他模型ID" / "中止"。选择后,替换<candidate>中的ID并重新运行B4。$TARGET_MODELS - + 其他
ok == false→ 显示reason并停止。detail - → 继续。显示任何
ok == true,以及任何quota_warning为reason的模型(预飞检查无法探测的嵌入系列——提醒用户在控制台确认模型访问)。embedding_unprobed
Phase C — Execute
阶段C — 执行
Phase C dispatches the five plugin agents sequentially via the Agent tool (subagent types
, , ,
, ). Each agent writes its result to
a file under ; you validate every file with
the bundled validator before moving on. There is no workflow runtime — the files ARE the state.
migration-to-aws:llm2bedrock-code-analyzermigration-to-aws:llm2bedrock-log-ingestormigration-to-aws:llm2bedrock-prompt-evaluatormigration-to-aws:llm2bedrock-code-rewritermigration-to-aws:llm2bedrock-report-generator$PHASE_DIR = $REPO/.saws-migrate/phase-results/阶段C通过Agent工具依次调度五个插件Agent(子Agent类型为、、、、)。每个Agent将结果写入下的文件;在进入下一步之前,你需要使用捆绑的验证器验证每个文件。没有工作流运行时——文件就是状态。
migration-to-aws:llm2bedrock-code-analyzermigration-to-aws:llm2bedrock-log-ingestormigration-to-aws:llm2bedrock-prompt-evaluatormigration-to-aws:llm2bedrock-code-rewritermigration-to-aws:llm2bedrock-report-generator$PHASE_DIR = $REPO/.saws-migrate/phase-results/The validator (used at every step)
验证器(每个步骤都使用)
bash
uv run --project $SCRIPTS python $SCRIPTS/validate_result.py --schema <analysis|ingestion|eval|rewrite|delta-decisions> <file>- Exit 0 + → phase completed; proceed.
RESULT=valid CONTROL=ok - Exit 0 + → blocked flow (below).
CONTROL=blocked REASON=<r> - Exit 0 + → partial flow (eval only).
CONTROL=partial COMPLETED=<n> TOTAL=<m> - Exit 1 (+ error lines) or exit 2 (file missing) → stateless fixer retry: dispatch a FRESH agent of the same type whose prompt is the original context block + the file path + the validator's verbatim error output + the instruction "fix ONLY the output file at
RESULT=invalidso it validates; do not redo the phase's work unless a required field is genuinely missing from it". Cap 2 retries per phase; then stop and show the errors.<path>
bash
uv run --project $SCRIPTS python $SCRIPTS/validate_result.py --schema <analysis|ingestion|eval|rewrite|delta-decisions> <file>- 退出码0 + → 阶段完成;继续。
RESULT=valid CONTROL=ok - 退出码0 + → 流程阻塞(如下)。
CONTROL=blocked REASON=<r> - 退出码0 + → 流程部分完成(仅评估阶段)。
CONTROL=partial COMPLETED=<n> TOTAL=<m> - 退出码1(+ 错误行)或退出码2(文件缺失)→ 无状态修复重试:调度一个相同类型的新Agent,其提示包含原始上下文块+文件路径+验证器的原始错误输出+指令"仅修复
RESULT=invalid处的输出文件使其通过验证;除非确实缺少必填字段,否则不要重新执行阶段工作"。每个阶段最多重试2次;然后停止并显示错误。<path>
The context block (instantiated at every dispatch)
上下文块(每次调度时实例化)
Build this exact line format (agents parse the labels). Omit lines marked optional when empty:
Repository: <$REPO>
AWS region: <$REGION>
AWS profile (pass as --profile / AWS_PROFILE= inline on every aws/boto3 invocation): <$AWS_PROFILE_CHOICE — omit line if default>
Target Bedrock model(s): <comma-joined $TARGET_MODELS, with any resolved overrides already applied>
Migration plan dir: <$MIGRATION_DIR>
Resolved target model id: <override for the primary chat model — omit if none>
Scripts directory (pinned uv toolchain): <$SCRIPTS>
Report date suffix: <saved suffix from run-context — C5/C6 dispatches only>
Source baseline available: <true|false>
Source provider env file: <path — omit if none>
User-supplied log files: <comma-joined — omit if none>
Golden dataset cap (max cases the ingestor may emit): 200
Phase results directory: <$PHASE_DIR>
Prior phase results (Read these files): <paths of already-validated phase JSONs>
Confirmed behavior-delta decisions file (Read it): <$PHASE_DIR/delta-decisions.json — C5 only>
<helper-reference lines — inject ONLY the ones this agent needs, per the table below>Prior-phase results are passed as FILE PATHS — never inline their JSON into the prompt.
Helper references (the former helper skills, now under ). Agents no longer
load skills by name; instead the agent Reads a helper reference at an absolute path you
inject. For each dispatch, add ONLY the helper lines that agent uses (per its section):
$HELPERS# 4| Agent (dispatch) | Helper-reference lines to add |
|---|---|
| C1 llm2bedrock-code-analyzer | |
| C5 llm2bedrock-code-rewriter | |
| C3 llm2bedrock-prompt-evaluator | |
| C2 llm2bedrock-log-ingestor, C6 llm2bedrock-report-generator | (none — these agents load no helpers) |
Expand to its absolute path (you have ) so the subagent — where
is empty — receives a resolvable absolute path.
$HELPERS<SKILL_BASE>${CLAUDE_PLUGIN_ROOT}构建此精确的行格式(Agent会解析标签)。空值时省略标记为可选的行:
Repository: <$REPO>
AWS region: <$REGION>
AWS profile (pass as --profile / AWS_PROFILE= inline on every aws/boto3 invocation): <$AWS_PROFILE_CHOICE — 默认时省略此行>
Target Bedrock model(s): <逗号分隔的$TARGET_MODELS,已应用所有已解析的覆盖>
Migration plan dir: <$MIGRATION_DIR>
Resolved target model id: <主聊天模型的覆盖——无则省略>
Scripts directory (pinned uv toolchain): <$SCRIPTS>
Report date suffix: <运行上下文中保存的后缀——仅C5/C6调度使用>
Source baseline available: <true|false>
Source provider env file: <路径——无则省略>
User-supplied log files: <逗号分隔——无则省略>
Golden dataset cap (max cases the ingestor may emit): 200
Phase results directory: <$PHASE_DIR>
Prior phase results (Read these files): <已验证的阶段JSON文件路径>
Confirmed behavior-delta decisions file (Read it): <$PHASE_DIR/delta-decisions.json — 仅C5使用>
<helper-reference lines — 仅注入此Agent需要的行,如下表>前期阶段结果以文件路径传递——绝不将其JSON内联到提示中。
**辅助参考(原辅助技能,现位于下)。**Agent不再按名称加载技能;而是Agent读取你注入的绝对路径下的辅助参考。每次调度时,仅添加该Agent使用的辅助行(根据其部分):
$HELPERS# 4| Agent(调度) | 要添加的辅助参考行 |
|---|---|
| C1 llm2bedrock-code-analyzer | |
| C5 llm2bedrock-code-rewriter | |
| C3 llm2bedrock-prompt-evaluator | |
| C2 llm2bedrock-log-ingestor, C6 llm2bedrock-report-generator | (无——这些Agent不加载任何辅助参考) |
将展开为绝对路径(你已有),以便子Agent(其中为空)收到可解析的绝对路径。
$HELPERS<SKILL_BASE>${CLAUDE_PLUGIN_ROOT}C0 — Run-context gate (resume safety)
C0 — 运行上下文门(恢复安全性)
The Eval phase makes one paid Bedrock call per golden case (and, with a source key, one paid
source-provider call per case). Before any dispatch, tell the user evaluation will invoke
Bedrock at their expense, capped at 200 cases.
- . Build
mkdir -p $PHASE_DIRwith exactly these fields (hashes via$PHASE_DIR/current-context.json; key hash is a fingerprint — never store the key value):shasum -a 256
json
{
"repo_root": "<cd $REPO && pwd -P>",
"migration_dir": "<$MIGRATION_DIR>",
"region": "<$REGION>",
"aws_profile": "<$AWS_PROFILE_CHOICE or \"\">",
"aws_account": "<Account from B2>",
"repo_head_sha": "<git -C $REPO rev-parse HEAD>",
"repo_branch": "<git -C $REPO rev-parse --abbrev-ref HEAD>",
"repo_dirty_sha256": "<sha256 of: git status --porcelain + git diff + git diff --cached, EACH with pathspecs -- . ':(exclude).saws-migrate' ':(exclude).migration' ':(exclude)MIGRATION_REPORT_*.md'; \"\" when all three are empty>",
"target_models": [{"source_model": "...", "aws_model_id": "...", "use_case": "..."}],
"resolved_model_overrides": {},
"source_provider": "<from B1>",
"source_baseline_available": <true|false from B3>,
"source_key_sha256": "<sha256 of .source-provider-env contents, \"\" when absent>",
"log_files": [{"path": "...", "sha256": "..."}],
"max_golden_cases": 200,
"assess_design_sha256": "<sha256 of $MIGRATION_DIR/aws-design-ai.json>",
"report_date_suffix": "<date +%Y-%m-%d>",
"schema_version": 1,
"plugin_version": "<version from <plugin>/.claude-plugin/plugin.json>"
}-
Stage 0 (post-C5 normalization). Ifexists and validates as a payload (
$PHASE_DIR/rewrite.json), do NOT use liveCONTROL=okvalues. Run three integrity checks: (1)repo_*equals the SAVEDrewrite.baseline_parent_sha; (2)repo_head_shaequalsgit rev-parse <rewrite.branch_name>; (3)rewrite.branch_tip_sha(with the artifact exclusions) is empty. All pass → copy the savedgit status --porcelainvalues into current-context verbatim, continue to step 3. Check 2 fails (tip moved) → STOP and AskUserQuestion: "Keep your commits (regenerate report only, with a mixed-authorship note)" / "Reset the branch to the rewriter's tip and regenerate from C6" / "Abort". Check 3 fails (dirty tree) → STOP and ask: commit/stash (then re-check) or discard the edits. Check 1 fails → treat as a fullrepo_*mismatch in step 3.repo_* -
Ifexists, compare:
$PHASE_DIR/run-context.json
bash
uv run --project $SCRIPTS python $SCRIPTS/validate_result.py --check-run-context $PHASE_DIR/run-context.json --current $PHASE_DIR/current-context.json- → resume: walk C1→C2→C3→(C4: delta-decisions.json)→C5→(C6: report file) in order; a phase counts completed iff its file validates with
RUN_CONTEXT=match(C6: iffCONTROL=okexists while rewrite.json is payload-valid). STOP the walk at the first missing/invalid/control-state file — blocked/partial files route to their flows below, NEVER count as completed. Offer the user "skip completed phases X..Y, resume at Z". Files after an unexplained gap: archive them with the gap.MIGRATION_REPORT_<saved suffix>.md - → scoped invalidation. Map each MISMATCH line through this table, archive the named units to
RUN_CONTEXT=mismatch(a SIBLING of phase-results/ — never nest it inside), then immediately overwrite run-context.json with current-context.json (carrying forward the saved$REPO/.saws-migrate/phase-results-archive/<saved suffix>-$(date +%H%M%S)/unless REPORT itself is being invalidated), then re-run the invalidated phases in order. Tell the user which fields differed and what re-runs.report_date_suffix
| Mismatched field(s) | Archive (units) | Keep |
|---|---|---|
| repo_root, migration_dir, region, aws_profile, aws_account, source_provider, assess_design_sha256, schema_version, plugin_version | everything | — |
| repo_head_sha / repo_branch / repo_dirty_sha256 | everything | — |
| target_models / resolved_model_overrides | ANALYSIS, EVAL, REWRITE, REPORT | INGESTION |
| log_files / max_golden_cases | everything | — |
| source_key_sha256 / source_baseline_available | ANALYSIS, EVAL, REWRITE, REPORT | INGESTION |
Units: ANALYSIS = analysis.json · INGESTION = ingestion.json +
· EVAL = eval.json + (minus cost_compare.py) · REWRITE =
rewrite.json + delta-decisions.json · REPORT = .
.saws-migrate/golden-dataset/.saws-migrate/eval-results/MIGRATION_REPORT_<saved suffix>.mdPost-C5 reruns of C1–C3 need the pre-migration tree. If rewrite.json was payload-valid
and the table invalidates ANALYSIS/INGESTION/EVAL: confirm with the user that the old
migration branch will be discarded (keep-or-reset flow first if the tip moved), then
, delete the old branch and the
tag, and re-run from C1. If the user declines, stop — re-analyzing a tree that contains
the rewrite produces garbage.
git checkout <saved repo_branch>saws-migrate-baseline- No saved run-context → fresh run: write current-context.json as run-context.json, dispatch C1.
评估阶段会为每个黄金案例调用一次付费的Bedrock(如果有源密钥,还会为每个案例调用一次付费的源提供商)。在任何调度之前,告知用户评估将以他们的费用调用Bedrock,上限为200个案例。
- 。构建
mkdir -p $PHASE_DIR,包含以下精确字段(通过$PHASE_DIR/current-context.json生成哈希;密钥哈希是指纹——绝不存储密钥值):shasum -a 256
json
{
"repo_root": "<cd $REPO && pwd -P>",
"migration_dir": "<$MIGRATION_DIR>",
"region": "<$REGION>",
"aws_profile": "<$AWS_PROFILE_CHOICE or \"\">",
"aws_account": "<B2中的Account>",
"repo_head_sha": "<git -C $REPO rev-parse HEAD>",
"repo_branch": "<git -C $REPO rev-parse --abbrev-ref HEAD>",
"repo_dirty_sha256": "<以下内容的sha256:git status --porcelain + git diff + git diff --cached,每个都带有路径规范 -- . ':(exclude).saws-migrate' ':(exclude).migration' ':(exclude)MIGRATION_REPORT_*.md';当三者都为空时为\"\">",
"target_models": [{"source_model": "...", "aws_model_id": "...", "use_case": "..."}],
"resolved_model_overrides": {},
"source_provider": "<来自B1>",
"source_baseline_available": <来自B3的true|false>,
"source_key_sha256": "<.source-provider-env内容的sha256,不存在时为\"\">",
"log_files": [{"path": "...", "sha256": "..."}],
"max_golden_cases": 200,
"assess_design_sha256": "<$MIGRATION_DIR/aws-design-ai.json的sha256>",
"report_date_suffix": "<date +%Y-%m-%d>",
"schema_version": 1,
"plugin_version": "<来自<plugin>/.claude-plugin/plugin.json的版本>"
}-
阶段0(C5后规范化)。如果存在并验证为有效负载(
$PHASE_DIR/rewrite.json),请勿使用实时CONTROL=ok值。运行三个完整性检查:(1)repo_*等于保存的rewrite.baseline_parent_sha;(2)repo_head_sha等于git rev-parse <rewrite.branch_name>;(3)rewrite.branch_tip_sha(排除工件)为空。全部通过→将保存的git status --porcelain值逐字复制到current-context,继续步骤3。检查2失败(分支尖端已移动)→停止并使用AskUserQuestion询问:"保留你的提交(仅重新生成报告,添加混合作者注释)" / "将分支重置为重写器的尖端并从C6重新生成" / "中止"。检查3失败(脏树)→停止并询问:提交/暂存(然后重新检查)或丢弃编辑。检查1失败→在步骤3中视为完全的repo_*不匹配。repo_* -
如果存在,进行比较:
$PHASE_DIR/run-context.json
bash
uv run --project $SCRIPTS python $SCRIPTS/validate_result.py --check-run-context $PHASE_DIR/run-context.json --current $PHASE_DIR/current-context.json- → 恢复:按顺序执行C1→C2→C3→(C4: delta-decisions.json)→C5→(C6: 报告文件);阶段完成的条件是其文件验证为
RUN_CONTEXT=match(C6:当rewrite.json为有效负载时,CONTROL=ok存在)。在第一个缺失/无效/控制状态文件处停止遍历——阻塞/部分完成的文件会进入相应流程,绝不视为已完成。向用户提供"跳过已完成阶段X..Y,从Z恢复"。未解释的间隙后的文件:将它们与间隙一起归档。MIGRATION_REPORT_<saved suffix>.md - → 范围失效。将每个不匹配的行映射到下表,将指定单元归档到
RUN_CONTEXT=mismatch(phase-results/的同级目录——绝不要嵌套在其中),然后立即将run-context.json覆盖为current-context.json(除非REPORT本身失效,否则保留保存的$REPO/.saws-migrate/phase-results-archive/<saved suffix>-$(date +%H%M%S)/),然后按顺序重新运行失效的阶段。告知用户哪些字段不同以及需要重新运行哪些阶段。report_date_suffix
| 不匹配的字段 | 归档(单元) | 保留 |
|---|---|---|
| repo_root, migration_dir, region, aws_profile, aws_account, source_provider, assess_design_sha256, schema_version, plugin_version | 所有内容 | — |
| repo_head_sha / repo_branch / repo_dirty_sha256 | 所有内容 | — |
| target_models / resolved_model_overrides | ANALYSIS, EVAL, REWRITE, REPORT | INGESTION |
| log_files / max_golden_cases | 所有内容 | — |
| source_key_sha256 / source_baseline_available | ANALYSIS, EVAL, REWRITE, REPORT | INGESTION |
单元:ANALYSIS = analysis.json · INGESTION = ingestion.json +
· EVAL = eval.json + (减去cost_compare.py)· REWRITE =
rewrite.json + delta-decisions.json · REPORT = 。
.saws-migrate/golden-dataset/.saws-migrate/eval-results/MIGRATION_REPORT_<saved suffix>.md**C1–C3在C5后的重新运行需要迁移前的代码树。**如果rewrite.json是有效负载且表格失效ANALYSIS/INGESTION/EVAL:与用户确认旧的迁移分支将被丢弃(如果尖端已移动,先执行保留或重置流程),然后,删除旧分支和标签,然后从C1重新运行。如果用户拒绝,停止——分析包含重写的代码树会产生无效结果。
git checkout <saved repo_branch>saws-migrate-baseline- 无保存的运行上下文→全新运行:将current-context.json写入run-context.json,调度C1。
C1 — Analyzer · C2 — Ingestor · C3 — Evaluator
C1 — 分析器 · C2 — 摄取器 · C3 — 评估器
For each phase in order, dispatch the agent with the context block (listing all
prior-phase file paths), then validate its output file:
| Step | agentType | Output file | Schema |
|---|---|---|---|
| C1 | | | analysis |
| C2 | | | ingestion |
| C3 | | | eval |
Blocked flow (): resolve with the user per REASON —
CONTROL=blocked- → user enables the model in the Bedrock console (nothing fingerprinted changes; re-dispatch the blocked phase only)
model_access - → user picks/pastes an ID → record it in
model_unresolvable, fold it into the Target lineresolved_model_overrides - → user supplies a new key (re-run B3) or sets baseline unavailable
source_key_auth - → re-run Phase A, then restart Phase C at C0
assess_output_missing
After ANY resolution, re-run the C0 recipe (rebuild current-context, apply the invalidation
table, overwrite run-context) and re-dispatch from the earliest invalidated phase — the
table, not the block location, decides where execution resumes.
Partial flow (eval only, ): AskUserQuestion —
CONTROL=partial- Continue remaining cases → re-dispatch the evaluator with the extra context line:
Resume: raw_results.jsonl already contains completed cases — evaluate only prompts whose ids are not present in it, then re-score and overwrite eval.json - Proceed with partial pass rate → re-dispatch the evaluator with: . Then C4 runs normally.
Finalize partial: do NOT call Bedrock again — score the cases already in raw_results.jsonl and emit the FULL eval payload over only those cases, with total_cases = the number scored and a notes prefix line 'partial_coverage: <completed>/<total> cases (throttled)' - Abort → stop; the files stay on disk for a later C0 resume.
按顺序对每个阶段,使用上下文块(列出所有前期阶段文件路径)调度Agent,然后验证其输出文件:
| 步骤 | agentType | 输出文件 | Schema |
|---|---|---|---|
| C1 | | | analysis |
| C2 | | | ingestion |
| C3 | | | eval |
阻塞流程():根据REASON与用户解决——
CONTROL=blocked- → 用户在Bedrock控制台启用模型(指纹未更改;仅重新调度阻塞的阶段)
model_access - → 用户选择/粘贴ID → 将其记录到
model_unresolvable,合并到Target行resolved_model_overrides - → 用户提供新密钥(重新运行B3)或设置基线不可用
source_key_auth - → 重新运行阶段A,然后从C0重新开始阶段C
assess_output_missing
任何解决后,重新运行C0流程(重建current-context,应用失效表格,覆盖run-context)并从最早的失效阶段重新调度——表格而非阻塞位置决定执行恢复点。
部分完成流程(仅评估阶段,):使用AskUserQuestion询问——
CONTROL=partial- 继续剩余案例 → 重新调度评估器,添加额外上下文行:
Resume: raw_results.jsonl已包含完成的案例——仅评估未出现在其中的prompt ID,然后重新评分并覆盖eval.json - 以部分通过率继续 → 重新调度评估器,添加:。然后C4正常运行。
Finalize partial: 不再调用Bedrock——对raw_results.jsonl中已有的案例评分,并仅针对这些案例生成完整的eval有效负载,total_cases = 已评分的数量,notes前缀行'partial_coverage: <completed>/<total> cases (throttled)' - 中止 → 停止;文件保留在磁盘上供以后通过C0恢复。
C4 — Sidebar (two gates) + persist decisions
C4 — 侧边栏(两个门)+ 持久化决策
Gate (a) — Quality go/no-go. Read . The threshold is
pass rate >= 0.9 AND (with
in the notes there is no quality signal — always ask). At or above → proceed silently.
Below, AskUserQuestion:
$PHASE_DIR/eval.jsonsource_baseline_quality != 'poor'no_golden_cases: true- Proceed anyway → gate (b)
- Change target model → record in , re-run C0 (the table invalidates ANALYSIS/EVAL and execution resumes at C1). Cap: 2 retries.
resolved_model_overrides - Abort → stop, no code touched.
Gate (a.5) — Rewrite strategy (from migration plan). Read from
→ .
If the value is , set . Otherwise (value is
, , or the field is absent), set .
No user question needed — the decision was already made during the Assess/Design phase.
migration_path$MIGRATION_DIR/aws-design-ai.jsonai_architecture.code_migration.migration_path"mantle"rewrite_strategy = "mantle""converse""gpt-oss"rewrite_strategy = "converse"Gate (b) — Behavior-delta resolution. For each with
, AskUserQuestion with the options from the
reference (Read , and the
sub-reference under its dir).
analysis.behavior_deltas[]user_visible == truebehavior-delta-detection$HELPERS/behavior-delta-detection/behavior-delta-detection.mdsource_providerreferences/Persist: write the decisions array (entries ; when there were no user-visible deltas) to
and validate it (). The file must exist before C5 — it is what
makes a C5 retry or a post-crash resume self-sufficient.
{delta_type, location, resolution_chosen, source}[]$PHASE_DIR/delta-decisions.json--schema delta-decisions门(a) — 质量通过/不通过。读取。阈值为通过率 >= 0.9 且 (如果notes中,则无质量信号——始终询问)。达到或超过阈值→静默继续。低于阈值,使用AskUserQuestion询问:
$PHASE_DIR/eval.jsonsource_baseline_quality != 'poor'no_golden_cases: true- 仍继续 → 门(b)
- 更改目标模型 → 将其记录到,重新运行C0(表格失效ANALYSIS/EVAL,执行从C1恢复)。上限:2次重试。
resolved_model_overrides - 中止 → 停止,不修改任何代码。
**门(a.5) — 重写策略(来自迁移计划)。**读取中的 → 。如果值为,设置。否则(值为、或字段缺失),设置。无需询问用户——决策已在评估/设计阶段确定。
$MIGRATION_DIR/aws-design-ai.jsonmigration_pathai_architecture.code_migration.migration_path"mantle"rewrite_strategy = "mantle""converse""gpt-oss"rewrite_strategy = "converse"**门(b) — 行为差异解决。**对于每个中的条目,使用参考中的选项询问用户(读取及其目录下的子参考)。
analysis.behavior_deltas[]user_visible == truebehavior-delta-detection$HELPERS/behavior-delta-detection/behavior-delta-detection.mdreferences/source_provider**持久化:**将决策数组(条目;当没有用户可见差异时为)写入并验证()。C5之前必须存在此文件——它使C5重试或崩溃后恢复能够自给自足。
{delta_type, location, resolution_chosen, source}[]$PHASE_DIR/delta-decisions.json--schema delta-decisionsC5 — Rewriter · C6 — Report
C5 — 重写器 · C6 — 报告
| Step | agentType | Output | Schema |
|---|---|---|---|
| C5 | | | rewrite |
| C6 | | | (none — file existence is the completion check) |
C5's context block includes the line and the
line (from run-context, NOT today's date on a resume). C6's context
block lists all four phase-result file paths.
Confirmed behavior-delta decisions fileReport date suffixWhen , C5's context block ALSO includes:
rewrite_strategy == "mantle"- (omit this line entirely for Converse — its absence is the signal for the default Converse path)
Rewrite strategy: mantle - — sourced from the plan's
Mantle model map: <source-model> -> <bedrock-model-id>entries (eachai_architecture.bedrock_models[]→source_modelpair).aws_model_id
| 步骤 | agentType | 输出 | Schema |
|---|---|---|---|
| C5 | | | rewrite |
| C6 | | 仓库根目录中的 | (无——文件存在即为完成检查) |
C5的上下文块包含行和行(来自运行上下文,不是恢复时的当天日期)。C6的上下文块列出所有四个阶段结果文件路径。
Confirmed behavior-delta decisions fileReport date suffix当时,C5的上下文块还包括:
rewrite_strategy == "mantle"- (Converse策略完全省略此行——其缺失是默认Converse路径的信号)
Rewrite strategy: mantle - — 来自计划的
Mantle model map: <source-model> -> <bedrock-model-id>条目(每个ai_architecture.bedrock_models[]→source_model对)。aws_model_id
C7 — Render summary
C7 — 渲染摘要
bash
uv run --project $SCRIPTS python $SCRIPTS/render_report.py --phase-results $PHASE_DIR --repo $REPO --date-suffix <saved suffix>Print the summary. Point the user at (usually , but
a collision-suffixed variant like when they already had that branch)
and the report file. Tell them how to undo — substitute the ACTUAL branch name from
, never a hardcoded one (on a collision run, is the
user's own pre-existing branch and deleting it would destroy their work):
rewrite.branch_namebedrock-migrationbedrock-migration-2rewrite.branch_namebedrock-migrationTo discard:,git checkout <your original branch>,git branch -D <rewrite.branch_name>, andgit tag -d saws-migrate-baselineremoves all migration artifacts (including the API key file).rm -rf .saws-migrate .migration
bash
uv run --project $SCRIPTS python $SCRIPTS/render_report.py --phase-results $PHASE_DIR --repo $REPO --date-suffix <saved suffix>打印摘要。将用户指向(通常为,但如果用户已有该分支,则为碰撞后缀变体如)和报告文件。告知用户如何撤销——替换中的实际分支名称,绝不要硬编码(碰撞运行时,是用户自己预先存在的分支,删除它会破坏他们的工作):
rewrite.branch_namebedrock-migrationbedrock-migration-2rewrite.branch_namebedrock-migration要撤销:,git checkout <你的原始分支>,git branch -D <rewrite.branch_name>,然后git tag -d saws-migrate-baseline删除所有迁移工件(包括API密钥文件)。rm -rf .saws-migrate .migration
Inline mode (platforms without an Agent/subagent dispatch tool)
内联模式(无Agent/子Agent调度工具的平台)
If this platform has no subagent dispatch tool, run phases inline ONE AT A TIME, with a
mandatory stop between phases:
- exactly ONE agent definition (
Read) — never load more than one phase's definition into context at once.<plugin>/agents/<name>.md - Follow it start-to-finish; write and validate the same phase-result file.
- STOP. Report the phase outcome (validator CONTROL line + one-line summary) and ask the user to confirm before loading the next phase's definition. This sidebar is mandatory: it is the context-pressure release valve, and the phase-result file means nothing is lost if the user continues in a fresh session instead.
Warn the user up front that inline mode is slower and context-heavier than subagent dispatch,
and that the rewriter phase performs git operations (branch, commits, worktree) directly in
this session.
如果此平台没有子Agent调度工具,一次运行一个阶段,阶段之间必须停止:
- Read恰好一个Agent定义()——永远不要同时加载多个阶段的定义到上下文中。
<plugin>/agents/<name>.md - 从头到尾遵循它;写入并验证相同的阶段结果文件。
- 停止。报告阶段结果(验证器CONTROL行+一行摘要)并询问用户确认后再加载下一个阶段的定义。此侧边栏是强制性的:它是上下文压力释放阀,阶段结果文件意味着如果用户在新会话中继续,不会丢失任何内容。
提前警告用户内联模式比子Agent调度更慢且上下文负载更重,并且重写器阶段会在此会话中直接执行git操作(分支、提交、工作树)。
Failure handling
故障处理
- An agent dispatch dies (tool error, terminal failure) → the phase file is missing → validator exit 2 → the stateless fixer-retry path (which, finding no file to fix, re-runs the phase). Do not auto-retry more than the 2-retry cap.
- User aborts at any gate → confirm no SOURCE CODE was modified (C5 never started if aborted
before then). Note that and
.migration/artifacts do exist; show the undo commands from C7 if the user wants them gone..saws-migrate/ - Assess skill fails → show the error and stop. User can re-run .
/migration-to-aws:llm-to-bedrock
- Agent调度失败(工具错误、终端故障)→ 阶段文件缺失→验证器退出码2→无状态修复重试路径(由于找不到要修复的文件,会重新运行阶段)。自动重试不超过2次上限。
- 用户在任何门处中止→确认未修改任何源代码(如果在C5之前中止,C5从未启动)。注意和
.migration/工件确实存在;如果用户希望删除它们,显示C7中的撤销命令。.saws-migrate/ - 评估技能失败→显示错误并停止。用户可以重新运行。
/migration-to-aws:llm-to-bedrock