Problem
durableCheckpointKey hashes only profile + region + commandsJSON. Two distinct deploys whose plans happen to produce the same command sequence (same skeleton + same VPC layout, different GitHub repo) collide on the same ~/.clanker/checkpoints/aws-<sha>.json and restore stale bindings (IMAGE_URI, DEPLOY_ID, ECR URIs, etc.) into the wrong run.
Where
internal/maker/checkpoint_store.go:123-144
Fix
Include plan.Question (or a hash of the repo URL extracted from it) in the checkpoint key:
func durableCheckpointKey(profile, region string, commands []Command, question string) string {
h := sha256.New()
h.Write([]byte(profile + "|" + region + "|"))
enc := json.NewEncoder(h)
enc.Encode(commands)
h.Write([]byte("|" + question))
return hex.EncodeToString(h.Sum(nil))
}
Also write question into the checkpoint JSON and refuse to load if it doesn't match — defence in depth.
Acceptance criteria
- Two deploys with identical command sequences but different
plan.Question resolve to distinct checkpoint files
- Loading a checkpoint with a mismatched
question field returns "checkpoint mismatch, ignoring" and starts fresh
- Test: two plans, same commands, different questions → distinct files on disk
Problem
durableCheckpointKeyhashes onlyprofile + region + commandsJSON. Two distinct deploys whose plans happen to produce the same command sequence (same skeleton + same VPC layout, different GitHub repo) collide on the same~/.clanker/checkpoints/aws-<sha>.jsonand restore stale bindings (IMAGE_URI,DEPLOY_ID, ECR URIs, etc.) into the wrong run.Where
internal/maker/checkpoint_store.go:123-144Fix
Include
plan.Question(or a hash of the repo URL extracted from it) in the checkpoint key:Also write
questioninto the checkpoint JSON and refuse to load if it doesn't match — defence in depth.Acceptance criteria
plan.Questionresolve to distinct checkpoint filesquestionfield returns "checkpoint mismatch, ignoring" and starts fresh