fix(stable-memory): defer migration rules to migrating-motoko-actors, add mops check-stable - #344
Conversation
Skill Validation ReportValidating skill: /home/runner/work/icskills/icskills/skills/stable-memoryStructure
Frontmatter
Markdown
Tokens
Content Analysis
Contamination Analysis
Result: passed Project Checks |
PR #344 (fix/stable-memory-record-field-migration) reworks this exact section and already defers migration rules to migrating-motoko-actors with the inline-vs-chain distinction. Keeping only the mechanical renames the skill-rename requires (migrating-motoko -> migrating-motoko-actors, and the writing-motoko reference elsewhere) so #345 doesn't duplicate #344 or enlarge the merge conflict on that line. The Copilot cross-ref concern is addressed by #344.
|
Heads-up on interaction with #345 (the Motoko-skills upstream migration to #345 renames the Motoko skills: This PR already forward-references
No changes needed here now — just merge #345 first, then rebase. 👍 |
… migration The Mistakes #5 table said 'Adding a field -> No [migration]'. That is true only for adding a NEW top-level persistent variable; adding a field to a record TYPE that a persistent variable holds requires an explicit migration expression under EOP — even when the field is optional, and regardless of whether the record is top-level or stored in a collection. Verified by controlled experiment (moc 1.9.0, core 2.6.1, --default-persistent-actors): new var / widen Nat->Int / no-op all upgrade cleanly; adding an optional field to a record (top-level var, Map value, or var-record-in-Map) all trap with 'RTS error: Memory-incompatible program upgrade'. Reworded the table + added a 'Common surprise' note, and an adversarial eval (WITH 3/3 | baseline 0/3 — the baseline confidently claims it is migration-free).
…tors, add mops check-stable Per upstream maintainer feedback: whether a change needs a migration is variant-dependent (enhanced vs. legacy migration), so a flat table in stable-memory is one variant away from being wrong. Delete the table and defer the migration rules/styles to migrating-motoko-actors, keeping only what is uniquely this skill's concern: - a rejected upgrade is not data loss (the EOP persistence guarantee) - the one robust fact: changing a record type an existing persistent variable holds is incompatible and needs a migration (even an optional added field, regardless of where the record lives) - prevention: enable stable-compatibility checking in `mops check` to catch this at check time instead of the runtime RTS error Depends on #327 (references the post-sync skill name migrating-motoko-actors). Eval reshaped to the accurate claim + the mops check prevention: WITH 4/4, baseline 0/4.
2ed77fe to
0b62077
Compare
There was a problem hiding this comment.
Pull request overview
This PR updates the stable-memory skill guidance to avoid maintaining an error-prone “which changes need a migration” table, and adds an eval case to ensure agents correctly warn that record-type changes in persisted Motoko state can require migrations and should be caught pre-deploy.
Changes:
- Remove the migration “needs migration?” table and replace it with a pointer to the Motoko migration skill plus a concise invariant about record-type incompatibility under EOP.
- Add guidance to catch stable-compatibility issues before deploy via mops stable checking.
- Add an adversarial output eval covering “adding an optional field to a persisted record in a Map”.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| skills/stable-memory/SKILL.md | Reworks Motoko upgrade/migration guidance; removes the table and adds pre-deploy checking advice. |
| evaluations/stable-memory.json | Adds an adversarial eval ensuring the skill warns about migration needs for persisted record-type changes and recommends mops stable checking. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
…k-stable PR review (Copilot): the deferral line credited migrating-motoko-actors with 'two migration styles' including the legacy `(with migration = ...)` syntax, but that skill covers only the mops-managed chain and explicitly rejects the inline syntax (which is retired). Reworded to defer just the chain rules, and made the 'depends on the migration style' point concrete (enhanced chain = type-only field needs a migration; plain persistent actor with an initializer does not). Also named the `[canisters.<name>.check-stable]` mops config that runs the stable-compatibility check against the deployed .most.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.
Suppressed comments (1)
evaluations/stable-memory.json:3
- The evaluation file's description says it only tests mo:core Map dot-notation usage, but this PR adds an additional adversarial eval about stable-compatibility/migrations. Update the description to reflect the broader scope so future maintainers don't miss why this eval exists.
"description": "Evaluation cases for the stable-memory skill. Tests whether agents write persistent actors in the dot-notation call style mo:core requires (moc >= 1.7.0) instead of passing Map's implicit compare argument explicitly.",
"output_evals": [
{
"name": "Adversarial: adding a field to a persisted record needs a migration, and mops check catches it",
…eval PR review (Copilot, suppressed): the eval file description only mentioned mo:core Map dot-notation, but this PR added an adversarial migration / stable-compatibility case. Updated the description so the file's scope is clear.
|
Re the suppressed comment ( |
Problem
Mistakes #5 carried a table of "which changes need a migration," and its "Adding a field → No" row was misleading: under EOP, changing a record type a persistent variable holds (e.g. adding even an optional field to a record stored in a
Map) is an incompatible change rejected at runtime withRTS error: Memory-incompatible program upgrade.But the deeper issue is the table itself. Per upstream-maintainer feedback, whether a plain added field needs a migration is variant-dependent — enhanced migration has no initializers for stable fields (so adding one needs a migration), while the ordinary
persistent actorwith field initializers does not for a new variable. A flat table instable-memoryis therefore always one variant away from being wrong, and the authoritative rules live in the migration skill, not here.Change
(with migration = ...)) are deferred tomigrating-motoko-actors, which owns them.mops check(mops-cli) so the compiler flags an incompatible change at check time against the previous.most, instead of surfacing the runtimeRTS erroron the upgrade call.Evidence
Controlled experiment (moc 1.9.0, core 2.6.1,
--default-persistent-actors) confirmed a record-type change traps regardless of where the record lives (top-levelvar,Mapvalue, var-record in aMap); adding a new persistent variable or widening avaris compatible.Independently corroborated by
mops checkstable-compatibility checking, which reports the same change as[M0170], tracing the field through theMapinternals to the record and directing you to write a migration — i.e. the exact runtime trap, caught before deploy.Evals
Reshaped the adversarial eval to the accurate claim + the
mops checkprevention. WITH skill 4/4; baseline 0/4 — baseline confidently calls the change "backward-compatible, no migration needed," which is exactly the belief this corrects.Eval run (WITH vs baseline)
Note on merge order
This references
migrating-motoko-actors, introduced by the Motoko upstream migration (#345, part of #327). #345 has now merged, and this branch is rebased onto it — the cross-reference resolves and the one overlapping line (the old migration-table row / renamed cross-ref) is reconciled in favour of this rework. No dependency remains; ready to come out of draft.🤖 Generated with Claude Code