feat: structural diffs for definition migration hooks (friction #5)#28
Conversation
The migration hook could only see two opaque fingerprint hashes, so hosts approved every definition upgrade blindly — unable to distinguish "new transition added" from "place renamed". Now the mismatch says WHAT changed: - every save stamps a compact definition SHAPE (sorted place names + a short hash of each transition's structural record — the same fields the fingerprint covers) under the reserved __workflow_def_shape context key, stripped on load like the fingerprint - on mismatch the handler receives a DefinitionMismatch: workflow ID, both fingerprints, and a DefinitionDiff — places/transitions added, removed, changed, by name; a renamed place reads as remove+add with referencing transitions marked changed; Diff.Additive() is the one-line "new structure only" policy; Diff is nil for pre-shape state (no information, not no change) - BREAKING: DefinitionMigrationFunc now takes (ctx, DefinitionMismatch) instead of (ctx, id, stored, current) — pre-1.0, documented in CHANGELOG - Fingerprint() refactored to share the per-transition record with the shape (hash unchanged) - dogfood: the hook's approval is now a policy — additive changes pass mechanically, non-additive expense-net changes are refused loudly, the payment net's anchor removal keeps its explicit migration, and nil-diff (pre-shape) state is approved with the loader's place validation as backstop - tests: additive add, removal+guard-change, rename shape (+String()), nil diff for pre-shape rows, reserved-key leak checks Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Warning Review limit reached
Next review available in: 26 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (9)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
CI's staticcheck flags dereferencing d after `d := mm.Diff; if d == nil {
t.Fatal }` — it doesn't credit t.Fatal as terminating in this shape. Check
mm.Diff first, assign after, matching the sibling tests it doesn't flag.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #28 +/- ##
==========================================
+ Coverage 80.89% 81.29% +0.40%
==========================================
Files 29 30 +1
Lines 3057 3128 +71
==========================================
+ Hits 2473 2543 +70
Misses 366 366
- Partials 218 219 +1
🚀 New features to boost your workflow:
|
Summary
Friction log #5 — the migration hook could only see two opaque fingerprint hashes, so hosts approved every definition upgrade blindly, unable to distinguish "new transition added" from "place renamed". Now the mismatch says what changed.
Mechanism: every save stamps a compact definition shape — sorted place names plus a short hash of each transition's structural record (the same fields the fingerprint covers) — under the reserved
__workflow_def_shapecontext key (a few hundred bytes; stripped on load like the fingerprint). On a mismatch, the handler receives aDefinitionMismatch:WorkflowID,StoredFingerprint,CurrentFingerprintDiff *DefinitionDiff— places and transitions added / removed / changed, by name. A renamed place reads as remove+add with its referencing transitions marked changed — exactly the shape a reviewer needs.Diff.Additive()makes "new structure only, approve mechanically" a one-line policy;Diff == nilfor state saved by pre-shape versions ("no information", not "no change").DefinitionMigrationFuncis nowfunc(ctx context.Context, mm workflow.DefinitionMismatch) error. The fingerprint hash itself is unchanged (Fingerprint()refactored to share the per-transition record with the shape).Dogfood proof: approval is now a policy instead of blind trust — additive changes pass mechanically (logged with the diff), non-additive expense-net changes are refused loudly, the payment net's anchor removal keeps its explicit
migratePaymentAnchormigration, and nil-diff state approves with the loader's place validation as backstop.Tests: additive add (place+transition, asserted through the hook), removal + guard change (non-additive, by name), rename shape with exact
String()output, nil diff for pre-shape rows, reserved-key leak checks.Roadmap milestone
Post-M5 friction-log-driven feature #5 — with it, every library item in the friction log's ranked list is shipped.
Checklist
gofmt -s -l .prints nothinggo vet ./...passesgo test -race ./...passes (root + examples, run serialized)CHANGELOG.mdupdated under [Unreleased] (Added + Breaking)🤖 Generated with Claude Code