# Coordination note: m2-market ↔ fedlearn MVP Addressed to: the fedlearn MVP effort (plan: `/home/m2/m2o/.planning/federated-learning/PLAN.md` — referenced here, not edited; that plan is fedlearn's to own). From: m2-market spec 001-market-first-wedge (research.md §R2, §R3, §R5; contracts/apply-adapter.md; contracts/registry-layout.md; data-model.md §Solution). ## 1. Context m2-market froze `schemas/solution.schema.json` v1 on **2026-07-02**. This happened *because* the fedlearn manifest freeze (fedlearn's own Task 1.1) had not landed yet. We verified the same day that none of the expected fedlearn rails exist: no `m2/m2-core` repo, no capture or curator CLIs. Per the m2-market constitution (Principle VII, "Simplicity & Sequenced Wedges"), blocking indefinitely on an unlanded dependency wasn't an option, so we froze our own side and are coordinating via this note rather than waiting or forking fedlearn's in-flight work (constitution: "consume, not fork"). This is not a request for fedlearn to change direction — it's a record of what we assumed, so fedlearn's actual manifest freeze can either confirm compatibility or tell us we need a v1→v2 migration on our side. ## 2. The compatibility ask `solution.schema.json` v1 embeds a "manifest-core" subset of fields that we shaped to match the fedlearn submission/manifest design as we understood it from the fedlearn plan. When fedlearn's Task 1.1 manifest freeze lands, we're asking that it remain **field-compatible** with this core — same field names, same types/shapes. Everything outside this list is fedlearn's to define freely; we have no opinion on it. The frozen manifest-core fields, as they appear in `solution.schema.json` v1 (specs/001-market-first-wedge/data-model.md §Solution): | Field | Type | |---|---| | `schema_version` | const string (ours is `m2.solution.v1`) | | `applicability.image_classes` | array | | `applicability.roles` | array | | `applicability.tool_requirements` | array | | `tenant_scope` | string (`m2-core` or a tenant id) | | `evidence` | array of `{source, excerpt?, machine?, session?, tokens?, wall_time?}` | | `content_hash` | string, sha256 | | `scrub_status` | object (present when `tenant_scope` is a tenant id; carries `double_scrubbed`) | If fedlearn's manifest freeze diverges on any of these (different field name, different shape), tell us — we'll plan a schema migration at integration rather than silently drift. ## 3. The commercialize seam When fedlearn's curation pipeline lands, we'd like its `commercialize` disposition to emit a PR against `m2/market-registry` (the Forgejo repo we stood up as registry-of-record — see research.md §R2), in the shape defined by `specs/001-market-first-wedge/contracts/registry-layout.md` §Publish protocol. In short: - A branch `listing/` adding/updating `listings//` (a `listing.json`, a `solution.json`, and an `evidence/` directory). - A PR carrying an evidence summary, price, a permissions diff, and a rollback note. - CI validates the PR mechanically (schema-validate against the mirrored frozen schemas, evidence non-empty, tenant-firewall rules, `content_hash` matches the attached release asset) before any human looks at it. - Human review resolves via label: `veto` → closed/back to draft; `approved` + merge → published, which triggers catalog re-index. This is the same PR/veto shape m2-market's own listing builders use — fedlearn's `commercialize` disposition would be just another producer of this PR shape, not a new protocol. ## 4. The adapter swap m2-market ships a frozen `ApplyAdapter` protocol (`contracts/apply-adapter.md`) with two implementations in v1: `local` (real, ships now) and `m2core-sync` (a stub that raises `RailsNotLanded`, CLI exit 6). When fedlearn's `m2-core-sync` / `m2-core pull --apply` lands, it becomes the real backing for the `m2core-sync` adapter — no changes needed to m2-market's CLI or Store, because they only ever talk to the `ApplyAdapter` interface. **Acceptance for the swap**: all `quickstart.md` scenarios pass unchanged with `adapter = m2core-sync` selected (`config.toml: apply_adapter = "m2core-sync"` or `--adapter m2core-sync`). See contracts/apply-adapter.md for the full protocol (`plan`/`apply`/`verify`/`rollback`, all idempotent) and the state-file merge expectation (`~/.m2-market/state.json` merging with fedlearn's `state.json` design). ## 5. What m2-market does NOT need from fedlearn To keep expectations tight on both sides: - **No ledger.** Value movement and balances are m2-market's own `m2-ledger` service (append-only `tx` table); fedlearn doesn't need to model credits, payouts, or grants. - **No catalog.** `market:catalog` is a memory-api partition owned and indexed by `m2-market-indexer` from `m2/market-registry`; fedlearn's manifest doesn't need catalog- or listing-shaped fields (pricing, seller, revenue split, listing status) — those live only in m2-market's `solution.json`/`listing.json`, layered on top of the manifest-core. - **No store dependency.** The M2 Store (cargstore fork) talks to `market:catalog` and shells out to the `m2-market` CLI for installs; it has no direct dependency on fedlearn services. Questions about this note → m2-market spec 001-market-first-wedge (research.md §R3, "Open coordination items").