herdr workforce output (6 codex angle-specialists -> claude synthesis): S1 ledger/economy, S2 catalog/registry, S3 storefront (cargstore->M2 Store), S4 Solution Scout (standalone watcher recommended), S5 packaging + 3 seed Solutions (mm-pdf 25cr, agent-scaffold 35cr, competitor-scan 60cr), S6 proposal engine + evidence loop. SPEC-INDEX is the tie-break: 23-row cross-cutting contract table (16 mismatches resolved, e.g. /v1 ledger paths win, m2store://listing/<id> deep link, one m2.market.telemetry.v1 envelope, op_<slug> operator ids, tenant ids from m2-gpt), 8 deduped clarifications with defaults, 4-phase build order where the paid-install wedge does NOT block on fedlearn (local ApplyAdapter until rails land), risk register. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
23 KiB
S5 Spec — Packaging & Seed Solutions
Grounded reads: /tmp/mktspec/BRIEF.md, CONCEPT.md, context/SYSTEM-MAP.md,
/home/m2/m2o/.planning/federated-learning/PLAN.md, frozen marketplace schemas/contracts,
live Docker fleet, live m2-gpt and memory-api health checks, mm-pdf and
agent-scaffold skills.
1. Scope & non-goals
MVP scope
S5 owns the contract for turning a proven outcome into a sellable installable Solution:
- builder workflow from either fedlearn
commercializeor directm2-market publish - canonical bundle layout:
solution.yaml,solution.json,listing.json,payload/,recipe.yaml,permissions.yaml,invoke.md,evidence/ - packaging validation and PR review requirements for
m2/market-registry - install/uninstall/upgrade contract through
m2-marketand them2core-syncapply adapter - pre-apply license check hook against
m2-ledger - evidence attachment for provenance, cost telemetry, permissions, rollback, and installs
- concrete seed bundle specs for
mm-pdf,agent-scaffold, andcompetitor-scan
The MVP must work with the existing frozen schemas/solution.schema.json and
schemas/listing.schema.json. The human-authored source manifest is solution.yaml; the
publish command renders canonical solution.json and listing.json that pass frozen JSON
Schema validation.
Later
- metered usage pricing and revenue sharing by invocation
- external public marketplace packaging
- cryptographic bundle signatures beyond content hash verification
- automated LLM-based tenant scrub beyond deterministic scanner + human attestations
- public coin/exchange or external payment settlement
- service escrow/dispute workflow for job-priced Solutions
Non-goals
- Ledger internals, transaction schema, and platform cut mechanics: S1.
- Catalog indexing/search/ranking and storefront fields beyond package/listing emission: S2/S3.
- Scout matching/proposal logic: S4.
- Hermes build-vs-install proposal composition: S6.
2. User stories + acceptance criteria
Story A — package a direct proven outcome
Given a builder has a repeatable skill/playbook and at least one provenance record,
When they run m2-market package init --from-skill /home/m2/.claude/skills/mm-pdf --id sol_mm-pdf-report,
Then a bundle directory is created with solution.yaml, payload files, deploy recipe,
permissions, invoke docs, and an evidence stub.
Given that bundle directory,
When the builder runs m2-market publish ./bundle --price 25 --seller <operator_id>,
Then the CLI validates schema, permissions, hash, evidence, and tenant firewall rules,
uploads a release asset, and opens a m2/market-registry PR in in_review.
Story B — package from fedlearn commercialize
Given fedlearn curator marks a cluster disposition commercialize,
When the handoff calls the S5 package importer with the staged cluster/core artifact,
Then the importer creates a Solution bundle draft preserving fedlearn provenance, cost
telemetry, applicability, risk class, rollback note, and scrub status.
Given the generated draft includes tenant-derived evidence,
When tenant_scope != "m2-core",
Then publish fails unless owner_initiated: true and
scrub_status.double_scrubbed: true are present and reviewed in the PR.
Story C — install, verify, uninstall, and re-install
Given a published fixed-price listing and a buyer with enough credits,
When m2-market install <listing_id> runs,
Then the CLI checks or purchases a license, verifies bundle hash, calls the apply adapter,
runs the recipe verify command, records install state, and prints the invocation hint.
Given the same listing is already licensed and applied,
When m2-market install <listing_id> runs again,
Then no duplicate debit occurs and the adapter returns no-op success.
Given an installed Solution,
When m2-market uninstall <listing_id> runs,
Then the adapter executes the recipe uninstall steps, leaves the license grant intact,
updates install state to rolled_back, and emits uninstall telemetry.
Story D — upgrade
Given lst_mm-pdf-report-v1.1.0 is published and the buyer has a major-version license for
v1,
When m2-market upgrade lst_mm-pdf-report,
Then the CLI checks license coverage, downloads the new bundle, applies only the versioned
changeset, verifies, and updates state from 1.0.0 to 1.1.0 without a new debit.
Given a new major version 2.0.0,
When a v1 license holder upgrades,
Then the CLI requires a new install purchase unless the listing declares explicit grace
terms.
3. Interfaces & data contracts
Registry paths
Truth lives in Forgejo git.machinemachine.ai/m2/market-registry.
listings/<listing_id>/
├── listing.json
├── solution.json
├── evidence/
│ ├── provenance.jsonl
│ ├── cost.json
│ ├── scrub-attestation.json
│ └── permissions-diff.md
└── README.md
releases/<install_ref>.tar.gz # Forgejo release asset, not committed as a blob
Builder workspaces may live in this repo under solutions/<slug>/, but the registry PR is
the system of record.
Bundle layout
Release asset tarball:
solution.json # canonical frozen schema payload
solution.yaml # source manifest; informational inside release
listing.json # catalog-facing record for this version
recipe.yaml # declarative apply/verify/uninstall/upgrade contract
permissions.yaml # source permission declarations rendered into solution.permissions
invoke.md # operator-facing invocation docs; no secrets
payload/
skills/<skill-name>/...
scripts/...
prompts/...
config/...
evidence/
provenance.jsonl
cost.json
scrub-attestation.json
tests.json
content_hash is sha256: over the normalized tarball with content_hash blanked before
hashing. Publish rejects hashes computed from a dirty or non-normalized bundle.
solution.yaml source manifest
schema_version: m2.solution.source.v1
solution_id: sol_mm-pdf-report
version: 1.0.0
name: MM PDF Report Generator
summary: Render Machine.Machine branded PDF and HTML reports from Markdown.
intent: Generate branded PDF/HTML deliverables from operator-authored Markdown.
seller: op_sdjs
tenant_scope: m2-core
price:
model: fixed
amount: 25
currency: m2cr
license:
terms: "Per-operator install; commercial use inside owned/client workspaces permitted."
major_version_coverage: true
revenue_split:
platform_pct: 10
runtime:
harnesses: ["hermes", "openclaw"]
surfaces: ["desktop"]
adapter: m2core-sync
applicability:
image_classes: ["primus", "agent-latest"]
roles: ["operator", "research", "proposal"]
tool_requirements: ["bash", "docker", "google-chrome-in-target"]
deployment:
recipe_ref: recipe.yaml
entrypoint: "mm-pdf generate <input.md> [--out output.pdf] [--style dark|purple|light]"
verify_command: "mm-pdf --version || test -x ~/.local/bin/mm-pdf"
behavior:
skills:
- payload/skills/mm-pdf/SKILL.md
tools:
- name: docker
purpose: render inside target m2o container
permissions_ref: permissions.yaml
evidence_ref: evidence/provenance.jsonl
Publish renders this into frozen m2.solution.v1 by copying known schema fields and placing
extra source-only fields such as version only in listing.solution_version and release tag.
recipe.yaml
schema_version: m2.recipe.v1
adapter: m2core-sync
install_ref: lst_mm-pdf-report-v1.0.0
targets:
- id: skill
type: directory
source: payload/skills/mm-pdf
dest: "${AGENT_HOME}/.claude/skills/mm-pdf"
mode: "0755"
- id: command
type: file
source: payload/scripts/mm-pdf
dest: "${AGENT_HOME}/.local/bin/mm-pdf"
mode: "0755"
config_merge: []
post_install:
- "mkdir -p ${AGENT_HOME}/.local/bin"
verify:
- "test -f ${AGENT_HOME}/.claude/skills/mm-pdf/SKILL.md"
- "test -x ${AGENT_HOME}/.local/bin/mm-pdf"
uninstall:
- "rm -rf ${AGENT_HOME}/.claude/skills/mm-pdf"
- "rm -f ${AGENT_HOME}/.local/bin/mm-pdf"
rollback:
strategy: restore_backups
note: m2core-sync records file backups before replacement and restores by changeset_hash.
Rules:
- destinations must be under
${AGENT_HOME},${M2_HOME}, or a declared per-solution data directory; host-level writes are rejected for marketplace MVP - no recipe command may contain inline secrets, tokens, or absolute tenant paths
- install and uninstall must be idempotent
- verify commands must be offline-safe and deterministic
- adapter must run canary-first when installing fleet-wide
permissions.yaml
schema_version: m2.permissions.v1
permissions:
- id: fs-write-agent-home
kind: filesystem
scope: "${AGENT_HOME}/.claude/skills/mm-pdf"
access: write
reason: install skill files
- id: docker-exec-local
kind: command
scope: "docker exec <selected m2o container>"
access: execute
reason: render PDF through Chrome inside a desktop container
- id: memory-read
kind: memory
scope: "market:evidence"
access: write
reason: emit install/invoke telemetry
Rendered solution.permissions[] objects are displayed as the install permissions diff in
CLI and M2 Store.
Evidence contracts
evidence/provenance.jsonl:
{"source":"fedlearn:submissions/sub_2026w27_chris_01hxyz","machine":"chris-m2o","session":"herdr-run-2026-07-01T12:00:00Z","excerpt":"Generated branded PDF from Markdown using Chrome headless.","tokens":12000,"wall_time":480}
evidence/cost.json:
{
"schema_version": "m2.solution.cost.v1",
"solution_id": "sol_mm-pdf-report",
"samples": 3,
"build_cost": {"tokens": 180000, "wall_time_seconds": 7200, "credits_equivalent": 18},
"invoke_cost_estimate": {"tokens": 1000, "wall_time_seconds": 90, "credits_equivalent": 1},
"maintenance_cost_estimate": {"credits_per_minor": 5},
"source_refs": ["market:evidence/mm-pdf-2026w27"]
}
evidence/scrub-attestation.json:
{
"schema_version": "m2.scrub.v1",
"tenant_scope": "m2-core",
"owner_initiated": true,
"double_scrubbed": true,
"secret_scan": "passed",
"pii_scan": "passed",
"reviewers": ["op_builder", "op_reviewer"],
"reviewed_at": "2026-07-02T00:00:00Z"
}
Install/invoke telemetry is appended locally, then summarized to market:evidence:
{
"schema_version": "m2.solution.telemetry.v1",
"event_id": "evt_<uuid>",
"event": "install|uninstall|upgrade|invoke",
"operator_id": "op_buyer",
"tenant": "m2-core",
"listing_id": "lst_mm-pdf-report",
"solution_version": "1.0.0",
"machine": "chris-m2o",
"result": "success|failed|rolled_back",
"wall_time": 12.4,
"tokens": 0,
"credits": 25,
"error_class": null
}
CLI verbs
Builder:
m2-market package init --from-skill <path> --id <solution_id> --name <name>m2-market package import-fedlearn --cluster <cluster_id> --out solutions/<slug>m2-market package validate <bundle-dir> [--strict-tenant]m2-market package build <bundle-dir> --out dist/<install_ref>.tar.gzm2-market publish <bundle-dir> --seller <operator_id> --price <credits>
Buyer:
m2-market install <listing_id> [--yes]m2-market uninstall <listing_id> [--yes]m2-market upgrade <listing_id> [--to <semver>]m2-market invoke <listing_id> -- <args>optional wrapper that records invoke telemetry
Admin/review:
m2-market package diff-permissions <old-bundle> <new-bundle>m2-market package evidence-summary <bundle-dir>m2-market package verify-release <install_ref>
Install/uninstall/upgrade sequence
Install:
- Resolve listing from
market:catalog; fetch registrysolution.json. - License hook:
GET /licenses/check?operator_id=<op>&listing_id=<listing>&major=<n>. - If no valid grant:
POST /tx/installwith price, seller, platform cut, and ref. - Download release tarball by
listing.install_ref. - Verify
content_hash. - Adapter preflight:
m2-core-sync plan --bundle <tar> --license-grant <grant_id>. - Apply:
m2-core-sync apply --bundle <tar> --state ~/.m2-market/state.json. - Verify recipe.
- Write install state and telemetry.
Uninstall:
- Confirm installed state exists.
- Run
m2-core-sync uninstall --install-ref <ref>or adapter rollback bychangeset_hash. - Verify declared uninstall checks.
- Mark
rolled_back; do not revoke license by default. - Emit telemetry.
Upgrade:
- Resolve latest published listing version with same listing id.
- Check major license coverage through ledger.
- Compute permission and recipe diff.
- Require confirmation if permissions broaden.
- Apply upgrade changeset; rollback to prior version on verify failure.
- Emit telemetry.
License check hook
Required m2-ledger endpoints consumed by S5 install path:
GET /licenses/check?operator_id=op_buyer&listing_id=lst_mm-pdf-report&major=1
200 {"valid":true,"grant_id":"gr_...","covers_major":1}
404 {"valid":false}
POST /tx/install
{"buyer":"op_buyer","listing_id":"lst_mm-pdf-report","seller":"op_sdjs","amount":25,"currency":"m2cr","ref":"lst_mm-pdf-report:chris-m2o:<uuid>"}
200 {"tx_ids":[1,2],"grant":{"grant_id":"gr_...","covers_major":1}}
POST /tx/refund
{"ref":"lst_mm-pdf-report:chris-m2o:<uuid>","reason":"apply_failed"}
200 {"refunded":true}
The adapter must receive grant_id during plan/apply. A bundle apply without a valid grant
must fail before any file writes.
4. Integration contract with other subsystems
- S1 ledger: S5 calls
/licenses/check,/tx/install,/tx/refund; ledger grants remain authoritative for reinstall/upgrade. - S2 catalog: S5 emits valid
listing.jsonandsolution.json; S2 indexes merged registry records intomarket:catalogand folds telemetry into stats. - S3 store: S3 shows
invoke.md, evidence, price, and permission diff from S5 bundle metadata; install button shellsm2-market install --json. - S4 Scout: S4 proposals deep-link to listing ids; S5 guarantees install refs and invocation hints exist after install.
- S6 proposal engine: S6 consumes
evidence/cost.json, provenance, price model, and invoke docs for build-vs-install comparisons. - fedlearn: fedlearn
commercializecallsm2-market package import-fedlearn; staged provenance and applicability map directly intosolution.evidence[]andapplicability. - m2-core-sync: S5 recipe is the marketplace-specific payload fed to the universal runtime
sync/apply path. Until fedlearn rails land, the existing
ApplyAdapterlocal path can execute the same recipe shape. - memory-api: S5 writes only summarized package evidence to
market:evidence; raw tenant data stays out of shared memory. - Forgejo: PR labels are
market:listing,status:in_review,risk:<low|medium|high>,veto-until:<timestamp>, optionalapproved, optionalveto.
5. Options compared
Source manifest format
- JSON only: aligns with schemas, poor for human packaging.
- YAML source rendered to JSON: best authoring ergonomics while preserving frozen schema.
- Python package metadata: too language-specific.
Recommendation: YAML source plus canonical JSON output.
Install backend
- Direct local file copy: good interim adapter, weak as long-term universal fleet path.
- m2-core-sync: matches locked runtime-sync decision and mixed image constraint.
- Container image install: rejected for MVP; local registry route is broken and secrets must not be baked.
Recommendation: recipe contract targets m2core-sync; local adapter may execute same recipe
while fedlearn rails are incomplete.
Pricing model per package
- Fixed install: deterministic and supported by frozen schema.
- Job price: required by locked decision, but current JSON Schema only enum-validates
fixed.
Recommendation: MVP bundles with direct install use fixed. Job-priced packages are listed
as inventory_type: service or use price_ext.model: job in solution.yaml until
solution.schema.json v2 adds job.
Evidence storage
- Evidence embedded only in
solution.json: too shallow for audit. - Evidence files beside registry listing: reviewable, indexed, and durable.
- Memory-only evidence: not authoritative.
Recommendation: registry evidence files are truth; memory market:evidence is derived and
summarized.
6. Seed Solution package specs
Seed 1 — mm-pdf
Source asset: /home/m2/.claude/skills/mm-pdf.
solution_id: sol_mm-pdf-report
listing_id: lst_mm-pdf-report
version: 1.0.0
name: MM PDF Report Generator
price: {model: fixed, amount: 25, currency: m2cr}
category: documents
tenant_scope: m2-core
install_targets:
- "${AGENT_HOME}/.claude/skills/mm-pdf"
- "${AGENT_HOME}/.local/bin/mm-pdf"
entrypoint: "mm-pdf generate <input.md> [--out output.pdf] [--style dark|purple|light]"
Bundle contents:
payload/skills/mm-pdf/SKILL.mdpayload/skills/mm-pdf/templates/dark.csspayload/skills/mm-pdf/templates/purple.csspayload/scripts/mm-pdfwrapper that calls skill scriptgenerate.shrecipe.yaml,permissions.yaml,invoke.md,evidence/*
Permissions:
- write skill directory under
${AGENT_HOME} - write executable under
${AGENT_HOME}/.local/bin - execute
docker ps,docker exec,docker cpagainst local m2o container - write output PDFs/HTML only to user-selected working directory
- no network secrets; no tenant memory reads required
Runtime deps:
- bash, docker CLI on host/container
- target m2o container with Node/npm and Google Chrome; observed
nasr-m2ohas this - optional Marp path for slides later, not required for MVP
Install targets:
- primus and agent-latest desktops
- canaries:
chris-m2ofirst,gunnar-m2osecond
Evidence:
- skill file path and script provenance from
/home/m2/.claude/skills/mm-pdf - successful local render transcript
- cost sample for Markdown-to-PDF runs
Seed 2 — agent-scaffold
Source asset: /home/m2/.claude/skills/agent-scaffold.
solution_id: sol_agent-scaffold
listing_id: lst_agent-scaffold
version: 1.0.0
name: Agent Workspace Scaffold
price: {model: fixed, amount: 35, currency: m2cr}
category: agent-ops
tenant_scope: m2-core
install_targets:
- "${AGENT_HOME}/.claude/skills/agent-scaffold"
- "${AGENT_HOME}/.local/bin/agent-scaffold"
entrypoint: "agent-scaffold <agent-name> \"<what this agent does>\" [--out <dir>]"
Bundle contents:
payload/skills/agent-scaffold/SKILL.mdpayload/skills/agent-scaffold/scripts/scaffold.pypayload/scripts/agent-scaffoldwrapper aroundpython3 scaffold.pypayload/templates/PRD.md.j2,SOUL.md.j2,MEMORY.md.j2only if extracted from script in a future cleanup; MVP may keep script-generated templates inlineinvoke.mddocumenting env varsM2_MEMORY_API_URL,M2_MEMORY_AGENT_ID,M2_MEMORY_API_KEY
Permissions:
- write
~/agents/<agent-name>/PRD.md,SOUL.md,MEMORY.md - read memory-api through configured endpoint and
X-API-Key - no raw client data export; memory query runs under buyer tenant/agent id
- optional write to git is manual, not automated in MVP
Runtime deps:
- Python 3 standard library
- memory-api reachable from desktop or host; live endpoint verified healthy
M2_MEMORY_API_KEYinjected at runtime, never packaged
Install targets:
- primus and agent-latest desktops
- Hermes/OpenClaw compatible as a CLI/skill, not harness-specific
Evidence:
- source skill and script from
/home/m2/.claude/skills/agent-scaffold - sample scaffold output with no tenant-specific content
- wall-time/token estimate from memory query and local file generation
Seed 3 — competitor-scan
Source asset: no canonical local skill found; package as a new outcome bundle from proven research-report workflow, with first implementation as prompts + scripts rather than a tenant-derived artifact.
solution_id: sol_competitor-scan
listing_id: lst_competitor-scan
version: 1.0.0
name: Competitor Scan Report
price: {model: fixed, amount: 60, currency: m2cr}
category: research
tenant_scope: m2-core
install_targets:
- "${AGENT_HOME}/.claude/skills/competitor-scan"
- "${AGENT_HOME}/.local/bin/competitor-scan"
entrypoint: "competitor-scan \"<company or market>\" --out report.md [--pdf]"
Bundle contents:
payload/skills/competitor-scan/SKILL.mdwith research workflow: scope, source collection, competitor matrix, positioning, pricing, risks, citations, recommendationspayload/prompts/competitor-scan.mdpayload/scripts/competitor-scanorchestrator: accepts subject, writesreport.md, optionally callsmm-pdfif installedpayload/templates/report.mdrecipe.yaml,permissions.yaml,invoke.md,evidence/*
Permissions:
- network egress for web research through approved tools/connectors only
- read/write local report output directory
- optional memory read for prior public market research under buyer tenant
- no raw tenant CRM/doc access by default
- if using browser automation, permission must be explicit and shown in install diff
Runtime deps:
- Hermes or OpenAI-wire harness through m2-gpt
- approved search/browser connector where available
- optional
mm-pdfinstalled for PDF output
Install targets:
- primus and agent-latest desktops
- initial canary should be non-client tenant or
m2-coreonly until evidence is scrubbed
Evidence:
- generic public-market sample only
- citations list in output fixture
- cost telemetry from a dry-run scan: LLM tokens, wall time, number of sources
Pricing note:
- fixed install price
60 m2crfor the reusable workflow - a human/operator-delivered bespoke competitor scan should be a separate service listing
with job pricing once schema v2 supports
price.model: job
7. Risks/edge cases
- Tenant leakage: reject tenant-scoped bundles without owner initiation and double scrub; competitor-scan must not package client-specific examples as seed evidence.
- Secrets in payload: deterministic scanner blocks API keys, JWTs, SSH keys, high-entropy
strings,
.env, browser profiles, and absolute secret paths. - License/apply split brain: if debit succeeds and apply fails, CLI must call refund and record failed install telemetry; grant without apply remains visible for audit.
- Upgrade permission creep: any broadened permission requires explicit confirmation and PR review note.
- Uninstall data loss: recipes may remove installed files but must not delete user-created output directories unless declared as disposable cache.
- Host fragility: install recipes are canary-first, idempotent, reversible, and confined to agent home paths.
- Local registry route is broken: packages are Forgejo release assets, not Docker images or registry pushes.
- Job pricing mismatch: locked business decision allows job pricing, but frozen schema only
validates
fixed; represent jobs as service inventory until schema v2. - Fake evidence: registry PR requires provenance files and at least one reproducible verify or sample output; catalog/memory evidence is not authoritative.
8. [NEEDS CLARIFICATION]
- Which operator id is the seller of record for the three seed Solutions:
op_sdjs,op_m2bd, or a platform-ownedop_m2-core? - Should
competitor-scanMVP be install-only fixed price, or should it launch as the first service/job listing despite the frozensolution.schema.jsononly accepting fixed price? - What exact
m2-core-synccommand names will fedlearn ship for uninstall and upgrade (uninstall,rollback,apply --upgrade), so S5 can replace adapter placeholders without aliasing?