Skip to content

Upgrade seed types from any declared starter baseline - #567

Merged
callumalpass merged 5 commits into
mainfrom
feat/seed-upgrade-baselines
Oct 3, 2026
Merged

callumalpass merged 5 commits into
mainfrom
feat/seed-upgrade-baselines

Conversation

@callumalpass

Copy link
Copy Markdown
Contributor

Implements Connect's side of mdbase-spec 05A seed-upgrade baselines: mdbase-dev/mdbase-spec#59 (f5f5743).

What changed

@mdbase-dev/connect-protocol

  • upgrade_from on a type-pack manifest resource is one baseline or a non-empty list of { digest, document, version? }. This applies to mdbase-app.schema.json and to connect-protocol.v1.schema.json, which previously had no upgrade_from at all, so devkit-built packs could not carry one. The single-object form is unchanged.
  • New validateTypePackProvision(value, path?) in ./manifest. It holds the existing resource-set and digest checks, now shared by validateAppManifest and the devkit, plus the 05A baseline rules: seed types only; digest = sha256(document); distinct digests; not the resource's own digest; same type kind and name as the desired document; version, if present, equals the document's. Issues point at the offending baseline, e.g. /provisions/type_packs/0/manifest/resources/0/upgrade_from/2/digest. The kind/name/version checks parse frontmatter with yaml, which is now a protocol dependency (already used by devkit, sync, ui, editor and server).
  • TypePackResourceDiff.upgrade_baseline and receipt resources' origin_digest.

mdbase-connect-protocol (Rust): TypePackManifestResource.upgrade_from is now Option<Value>, passed through verbatim, and the single-baseline TypePackSeedUpgradeBase struct is removed. Connect never read it: the pack digest covers the exact form, and mdbase validates it. A test round-trips both forms and checks them against the schema.

@mdbase-dev/connect (client SDK): TypePackResourceDiff.upgradeBaseline and receipt originDigest, translated in wireTypePackResource/wireTypePackReceipt.

@mdbase-dev/connect-dev: defineTypePack accepts upgradeFrom: [{ document, version? }] on resources. It computes the digests, defaults version to the one the document declares, always emits the list form, and validates with validateTypePackProvision.

Editor: requireGuidedPersonSetup accepts a seed type update only when the engine-reported upgradeBaseline.digest is one of the bundled resource's declared baselines (single or list). Before, it checked installedDigest against the single upgrade_from. merged is now currentDigest !== upgradeBaseline.digest. If the engine preserves the Person seed with a reason (05A step 5: origin unknown or unlisted), setup returns { kept: true } and the panel shows Person type kept as it is in place of the review button, so the "update available" row no longer loops. Everything else is still rejected as before.

Portal: type and copy for list baselines and kept types. Docs: docs/portable-people.md, devkit README, CHANGELOG.

Fixtures

In apps/editor/src/test/person-starter-upgrade.assessment.json, the upgradeBaseline and originDigest values and the whole new unknownOrigin case are hand-constructed from the spec until the engines report them. merged now assumes a lock that records the v2 origin. unknownOrigin's assessment and lock digests are placeholders.

Merge ordering

  • Until the engine bump, the current mdbase-rs pin reports no upgrade_baseline, so the Editor's v2→v3 Person upgrade would stop for review in Types. Land this with or after the Connect engine bump.
  • Lists are rejected by engines older than 05A.

Verification

  • pnpm ci:local --node (Node 24): everything passes except check:architecture. See below.
  • protocol node tests 77/77, client 666, devkit 15, editor 536 (65 files), connect-protocol Rust 71, clippy and fmt clean on the crate.

Architecture budget: needs approval

typeScriptExportDeclarations is 2692; its reviewed budget is 2691 (+1, from the new exported validateTypePackProvision, which keeps the devkit from running a second validator). The budget is not raised here. Rust public declarations went down by 3 (3368 → 3365).

mdbase-spec 05A (mdbase-dev/mdbase-spec#59) lets a seed type's
`upgrade_from` list every previously shipped starter, and has engines merge
an edited seed only against the baseline its lock records as origin.

Protocol: `upgrade_from` accepts one baseline or a non-empty list of
`{ digest, document, version? }` in both the app-manifest and protocol
schemas. The provision checks move into `validateTypePackProvision`, shared
by app-manifest validation and the devkit, which rejects baselines on
non-seed types, digest mismatches, duplicates, the resource's own digest, a
different type kind or name, and a `version` the document does not declare,
at the offending baseline's path. Assessments gain `upgrade_baseline` (SDK
`upgradeBaseline`) and receipts `origin_digest` (`originDigest`). The Rust
manifest passes `upgrade_from` through verbatim (the pack digest covers it;
mdbase validates it) instead of a single-baseline struct.

Devkit: `defineTypePack` accepts `upgradeFrom: [{ document, version? }]` on
seed types, computing digests and defaulting `version` to the document's.

Editor: guided Person setup accepts a seed update only when the engine
reports an `upgradeBaseline` the bundled pack declares, and reports a Person
type the engine preserves with a reason as kept, instead of offering the
update again.
…export budget

validateTypePackProvision lets devkit reuse the protocol's 05A validation instead
of keeping a second copy; it is the one added export.
The engine now plans seed upgrades from any listed baseline chosen by the
lock's origin_digest and reports upgrade_baseline, which the Editor gate in
this PR relies on.
@callumalpass
callumalpass added this pull request to the merge queue Oct 3, 2026
Merged via the queue into main with commit ab936db Oct 3, 2026
39 checks passed
@callumalpass
callumalpass deleted the feat/seed-upgrade-baselines branch October 3, 2026 04:14
callumalpass added a commit to mdbase-dev/mdbase-reader that referenced this pull request Oct 3, 2026
* List every earlier starter as a seed upgrade baseline

Pack beta.4 named only the beta.3 starters as `upgrade_from`, so a
collection installed from an earlier pack was merged against the wrong
document: upgrading an edited beta.1 seed treated beta.1's `match`
rules, which beta.3 removed, as the collection's own edit and restored
them.

mdbase-spec 05A (mdbase-dev/mdbase-spec#59) lets a seed list every
starter it supports and has engines choose the baseline from the lock's
seed origin. Pack beta.5 ships the same version-2 starters and lists,
newest first, each distinct starter Reader has shipped, with its
`version`:

- reader-source: beta.3 (82869c1), beta.2 (54f46e7), beta.1 (e8a3fca)
- reader-annotation: beta.3 (1fb7e75), beta.1 (9b6b0fc)

beta.2 changed only reader-source, and the beta.3 starters were also
served as beta.1 between #20 and #26. The new baselines are the exact
released bytes from 5c55c7d and fde2582; the released beta.2 pack is
added as a fixture.

An unedited starter from any of them is replaced with the exact
version-2 bytes. An edited seed is merged against the starter it was
installed from; for beta.1 and beta.2 that removes the top-level
`match` rule, which 05A leaves to manual review, so the upgrade fails
closed instead of restoring it. A seed whose lock predates recorded
origins is kept with a reason.

Verification installs packs with @callumalpass/mdbase 0.3.0-rc.9, which
supports baseline lists. Until a Connect release includes
mdbase-dev/mdbase-connect#567, @mdbase-dev/connect-dev rejects them, so
connect-protocol 0.1.0-beta.124 is patched with that PR's schema change;
drop the patch when moving to that release.

* Move to Connect SDK 0.1.0-beta.125 and drop the manifest-schema patch

* Restore the production extension manifest
callumalpass added a commit to mdbase-dev/mdbase-writer that referenced this pull request Oct 3, 2026
* List every earlier reader-source starter as an upgrade baseline

Pack beta.4 named only the beta.3 reader-source starter as
`upgrade_from`, so a collection holding an earlier starter was merged
against the wrong document. mdbase-spec 05A (mdbase-dev/mdbase-spec#59)
lets a seed list every starter it supports, and engines choose the
baseline from the lock's seed origin.

Pack beta.5 lists the same baselines as Reader's pack beta.5, byte for
byte and under the same paths, newest first with their `version`:
Reader's beta.3 starter (82869c1, Writer's beta.3), beta.2 (54f46e7)
and beta.1 (e8a3fca, Writer's beta.1 and beta.2). The existing
byte-identity test now covers every listed baseline against Reader's
copies.

Until a Connect release includes mdbase-dev/mdbase-connect#567,
@mdbase-dev/connect-dev rejects baseline lists, so connect-protocol
0.1.0-beta.124 is patched with that PR's schema change. Drop the patch
when moving to that release.

* Move to Connect SDK 0.1.0-beta.125 and drop the manifest-schema patch
callumalpass added a commit to callumalpass/tasknotes-app that referenced this pull request Oct 3, 2026
rc.18 carries the same task starter as rc.17, but its seed lists every
earlier published starter (type versions 4, 3, 2 and 1) as `upgrade_from`
baselines, so a collection holding any of them gets the reviewed upgrade.
The manifest test now asserts the list form and each baseline's digest.

The list form needs a Connect release with mdbase-dev/mdbase-connect#567.

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant