diff --git a/docs/fedlearn-coordination.md b/docs/fedlearn-coordination.md new file mode 100644 index 0000000..761e783 --- /dev/null +++ b/docs/fedlearn-coordination.md @@ -0,0 +1,96 @@ +# 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").