# Feature Specification: M2 Marketplace — First Wedge **Feature Branch**: `001-market-first-wedge` **Created**: 2026-07-02 **Status**: Draft **Input**: User description: "M2 Marketplace first wedge: schemas, m2-ledger, commercialize curation, market:catalog + m2-market CLI, cargstore revival to M2 Store, 3-5 seeded Solutions, Solution Scout v0, one real paid install between two operators" (CONCEPT.md v0.2 §12) ## User Scenarios & Testing *(mandatory)* ### User Story 1 - Paid install via CLI (Priority: P1) An operator (buyer) searches the catalog for a capability they need, inspects a listing's evidence and price, and installs it. The install debits their credit wallet, credits the seller (minus platform cut), grants a license, and applies the Solution bundle to their machine through the existing sync/apply path. This is the commercial loop's spine — every other story feeds it. **Why this priority**: Without buy→debit→grant→apply working end-to-end, nothing else in the marketplace has meaning. It is independently valuable: even with zero storefront UI and zero Scout, two operators can transact via CLI. **Independent Test**: On a machine with a funded wallet, run `m2-market search `, `m2-market show `, `m2-market install `; verify ledger shows the debit and seller credit, a license grant exists, and the bundle's files/config are applied and invocable. **Acceptance Scenarios**: 1. **Given** a listed Solution priced at 40 credits and a buyer wallet holding ≥40 credits, **When** the buyer runs `m2-market install `, **Then** the ledger records a debit of 40 from the buyer, a credit of 36 to the seller and 4 to the platform (10% cut), a license grant is recorded, and the bundle is applied idempotently to the buyer's machine. 2. **Given** a buyer wallet holding fewer credits than the listing price, **When** they attempt install, **Then** the install is refused before any apply happens and no ledger transaction or license grant is created. 3. **Given** a completed install, **When** the same install is re-run, **Then** the apply is idempotent (no duplicate debit; re-apply is safe or a no-op with the existing license). 4. **Given** an applied Solution, **When** the operator invokes its documented entrypoint, **Then** the packaged outcome executes on their machine. --- ### User Story 2 - Publish a Solution with evidence (Priority: P1) A builder packages a proven outcome (e.g. the mm-pdf branded-report generator) as a Solution: a manifest-superset bundle with price, seller, license, and provenance evidence. They submit it for listing; it passes the curation pipeline (scored PR, human veto) with the `commercialize` disposition and lands in the registry of record and the semantic catalog. **Why this priority**: Supply side of the loop. Story 1 cannot demo without at least one real listing; seeding 3–5 Solutions from proven outcomes is part of this wedge. **Independent Test**: Package one existing proven outcome, submit it, approve the listing PR, and verify it is retrievable via `m2-market search` with its evidence and price visible. **Acceptance Scenarios**: 1. **Given** a valid Solution bundle with price and provenance, **When** the builder submits it for listing, **Then** a review PR is created carrying evidence, price, permissions, and rollback info, and the listing is NOT discoverable until the PR is merged. 2. **Given** a submitted listing missing provenance evidence, **When** it enters curation, **Then** it is rejected by validation before human review. 3. **Given** a merged listing, **When** any operator searches the catalog semantically, **Then** the listing is returned with name, summary, price, rating placeholder, and evidence summary. 4. **Given** tenant-derived work, **When** submission is attempted by anyone other than the owning operator, **Then** the submission is refused (tenant firewall). --- ### User Story 3 - Credit wallets and starter grants (Priority: P2) Each operator has a wallet. The platform issues starter grants to active operators so the economy can bootstrap. Balances derive from an append-only transaction log; a daily snapshot is committed to the registry host for audit. **Why this priority**: Story 1 needs wallets to debit, but a minimal hardcoded grant would suffice for the very first transaction; full wallet lifecycle is its own increment. **Independent Test**: Issue a starter grant to a fresh operator id; verify balance query returns the grant amount; verify the daily snapshot job writes a balance file into version control. **Acceptance Scenarios**: 1. **Given** a new operator id, **When** a starter grant (default 100 cr) is issued, **Then** their balance reflects it and the grant appears as an append-only transaction with reason `grant`. 2. **Given** any sequence of transactions, **When** balances are queried, **Then** they equal the fold of the transaction log (no stored balance drifts from derived balance). 3. **Given** a day with ≥1 transaction, **When** the snapshot job runs, **Then** a balance snapshot is committed to the audit repo. --- ### User Story 4 - M2 Store (cargstore revival) on canaries (Priority: P3) An operator on a canary desktop opens the M2 Store app, browses the catalog rendered from `market:catalog`, opens a Solution page showing evidence, price, and permissions diff, and installs with one click — same ledger + apply path as the CLI. **Why this priority**: The storefront makes the loop humane but the CLI already closes it. Canary-only (chris-m2o, gunnar-m2o) per the constitution's deployment principle. **Independent Test**: On one canary desktop, open the store, find a seeded listing, click install, and verify the same post-conditions as Story 1's scenario 1. **Acceptance Scenarios**: 1. **Given** the store app pointed at the live catalog, **When** it renders the front page, **Then** seeded listings appear with name, summary, category, price. 2. **Given** a Solution page, **When** the operator clicks Install, **Then** the identical debit→grant→apply sequence of Story 1 executes and the UI reports success/failure truthfully. 3. **Given** an install failure after debit, **When** the failure is detected, **Then** the operator sees a clear error and a compensating refund transaction is recorded. --- ### User Story 5 - Solution Scout v0 on one canary (Priority: P3) While an operator works, a per-desktop watcher summarizes session intent from structured lifecycle/run summaries (never raw keystrokes), matches it against tenant-allowed catalog listings, and — on a high-confidence hit — shows a non-blocking proposal with a deep link to the listing. Propose-only, opt-in, rate-limited. **Why this priority**: Demand-side engine; valuable but the wedge's success criterion only requires discovery "via Scout **or** Hermes/CLI". Ships last, on one canary. **Independent Test**: On an opted-in canary, run a session that resembles a seeded listing's intent; verify a proposal appears within the session with a working deep link, and that opting out or exceeding the daily rate cap suppresses proposals. **Acceptance Scenarios**: 1. **Given** an opted-in desktop and a session whose summary semantically matches a listing above threshold, **When** the match fires, **Then** a non-blocking notification with the listing's name, rating, coverage, and price appears with an install deep link. 2. **Given** an opted-out desktop, **When** the same session runs, **Then** no session data leaves the machine and no proposal is shown. 3. **Given** N proposals already shown today (rate cap), **When** another match fires, **Then** it is suppressed. 4. **Given** a proposal, **When** the operator dismisses or accepts it, **Then** the outcome is recorded as listing-quality evidence (conversion signal). --- ### Edge Cases - Install interrupted between ledger debit and apply completion → apply must be resumable or a compensating refund recorded; never a paid-but-not-applied end state without a visible remediation path. - Listing updated (new version) after purchase → existing license covers which versions? (v1: license covers the purchased major version; updates within it are free re-applies.) - Seller delists a purchased Solution → existing licenses and installed bundles remain valid. - Two installs of the same listing racing on one machine → second is a no-op under the existing idempotent apply semantics. - Catalog index diverges from registry of record → registry wins; index must be rebuildable from it (constitution II). - Buyer and seller are the same operator (self-purchase) → allowed but flagged; conversion signals from self-purchases are excluded from listing quality metrics. - Scout matches against a listing the tenant may not see → must be impossible by construction: matching runs against tenant-allowed listings only. ## Requirements *(mandatory)* ### Functional Requirements - **FR-001**: The system MUST define a frozen v1 `solution.schema.json` as a superset of the fedlearn manifest, adding at minimum: price, seller/operator id, license terms, and revenue-split fields. - **FR-002**: The system MUST define a frozen v1 `listing.schema.json` covering catalog presentation: id, name, summary, category, keywords, price, seller, evidence references, rating/conversion placeholders, and install reference. - **FR-003**: The system MUST provide an append-only credit ledger recording transactions `{ts, from, to, amount, reason: install|payout|grant|route|earn, ref}` with balances always derived from the log. - **FR-004**: The ledger MUST authenticate API callers (per-key auth) and MUST commit a daily balance snapshot to the version-controlled audit location. - **FR-005**: Installing a listing MUST atomically-in-effect: verify funds, debit the buyer, credit the seller minus the platform cut (default 10%, configurable), record a license grant, then trigger the existing sync/apply path; on apply failure a compensating refund transaction MUST be recorded. - **FR-006**: The curation pipeline MUST support a third disposition `commercialize` alongside promote-to-core and reject/park, using the existing PR + human-veto flow, with a listing PR template requiring evidence, price, permissions, and rollback notes. - **FR-007**: The system MUST index merged listings into a semantic catalog partition (`market:catalog`) searchable by meaning, scoped to tenant-allowed listings, and fully rebuildable from the registry of record. - **FR-008**: The system MUST provide an `m2-market` CLI with at minimum `search`, `show`, and `install` commands, where `install` performs the FR-005 sequence. - **FR-009**: Operators MUST have wallets keyed to operator identity (fleet tenancy model), and the platform MUST be able to issue starter grants (default 100 cr). - **FR-010**: The storefront (M2 Store, evolved from cargstore) MUST render the catalog, show listing detail with evidence/price/permissions, and drive installs through the same ledger + apply path as the CLI; deployment is canary-only in this wedge. - **FR-011**: The Solution Scout MUST run per-desktop, opt-in via desktop policy config, consume only structured session/run summaries (never raw keystrokes or raw client data), summarize on-box before any egress, match only tenant-allowed listings, be rate-limited (default: max 5 proposals/day), and be propose-only (install always requires a human click). - **FR-012**: Accepted and dismissed Scout proposals MUST be recorded as listing quality evidence (proposal→install conversion). - **FR-013**: At least 3 Solutions packaged from already-proven outcomes MUST be listed with real evidence (proposed set: mm-pdf branded-report generator, agent-scaffold workspace generator, competitor-scan report). - **FR-014**: Install telemetry (who/when/machine/outcome) MUST land back in the memory system as pricing/quality evidence attached to the listing. - **FR-015**: Tenant-derived work MUST be commercializable only when owner-initiated and doubly-scrubbed; submissions violating the tenant firewall MUST be rejected automatically. ### Key Entities - **Solution**: installable bundle — intent, agent behavior, tools, runtime refs, memory schema, permissions, deployment recipe, price, evidence. Conforms to `solution.schema.json`; versioned in the registry of record. - **Listing**: the catalog-facing record of a Solution (or other inventory type) — presentation + commercial fields + evidence refs. Conforms to `listing.schema.json`; truth in the registry, indexed in `market:catalog`. - **Operator**: human identity over N machines (fleet tenancy); may act as buyer, builder, seller, resource owner. Owns exactly one wallet in v1. - **Wallet / Transaction**: operator's credit position, derived from append-only transactions `{ts, from, to, amount, reason, ref}`. - **License Grant**: record tying an operator to a purchased listing version, checked by the install/apply path. - **Proposal**: a Scout suggestion event — listing, confidence, shown/dismissed/accepted, feeding conversion metrics. ## Success Criteria *(mandatory)* ### Measurable Outcomes - **SC-001**: One real paid install completes between two distinct operators (e.g. m2bd buys sdjs-operator's package): discovered via CLI/Hermes/Scout, bought with credits, applied via the standard path, ledger reflecting debit/credit/cut — the loop closes commercially once. - **SC-002**: ≥3 Solutions listed with real provenance evidence, each passing curation review. - **SC-003**: 100% of installs have a matching ledger transaction and license grant; zero applies without a recorded debit (audited from the daily snapshot). - **SC-004**: Ledger balances recomputed from the transaction log match reported balances exactly at every daily snapshot. - **SC-005**: An operator can go from `m2-market search` to an invocable installed Solution in under 10 minutes on a canary desktop. - **SC-006**: Scout v0 on one canary produces ≥1 correct proposal (matching listing shown for a genuinely related session) with zero raw-input egress, honoring opt-in and rate caps. - **SC-007**: Install telemetry from SC-001's install is queryable as evidence on the listing afterward. ## Assumptions Recorded per constitution: recommended defaults from CONCEPT.md §14 open forks are ASSUMED here and flagged until the operator confirms (also mirrored in `.m2herd/overview.json` open_questions): - **Ledger substrate** (operator steer, README 2026-07-02): standalone `m2-ledger` service (SQLite, API-key auth) NOW; recorded future direction — it may evolve into a crypto-style ledger managed inside extended m2-gpt billing. v1 interfaces must not preclude that migration (keep ledger API separable from storage). - **Pricing v1** (operator steer): fixed price per install as the default; the operator notes that sometimes another m2o takes a *job* for a solution — service-style fulfillment pricing. v1 transacts fixed-price installs only, but `listing.schema.json` must not preclude a job/service fulfillment variant (reason codes `route|earn` already exist). - **Storefront path** (operator steer): MVP Electron app (cargstore revival) that connects to Coolify and other platform parts using credentials issued via m2-gpt; `web/` variant deferred. - **Scout host**: OPEN — operator marked "explore solution" (§14.4). Plan phase must carry a short exploration spike (standalone supervised watcher vs Hermes plugin vs herdr plugin) before Scout implementation; Scout v0 remains last-sequenced so this does not block the wedge. - **First Solutions**: mm-pdf, agent-scaffold, competitor-scan (§14.5 proposed). - **Economics**: platform cut 10%, starter grant 100 cr, both configurable (§14.6 defaults). - **Dependency**: fedlearn MVP rails (manifest schema, `m2/m2-core` registry, capture CLI, curation PR/veto, `m2-core-sync` apply, memory partitions) are in herd execution NOW and land before or during this wedge; where a rail is not yet landed, the plan phase must sequence around it or stub against its frozen interface. - Payout to fiat/external money is out of scope; payouts are manually reconciled. - Resource/Service inventory types are catalog-schema-ready but not transacted in this wedge; only Solutions are bought/sold. - Public web marketplace, external payments, and public coin/exchange are out of scope.