|
1 | 1 | # mcpt-marketing |
2 | 2 |
|
3 | | -Deterministic marketing data layer for MCP Tool Shop. Schema-validated claims, hash-addressed evidence, and reproducible marketing builds. |
| 3 | +Deterministic marketing infrastructure for MCPT tools: **falsifiable claims**, **hash-verified evidence**, and **channel-ready messages** that stay traceable as the product evolves. |
4 | 4 |
|
5 | | -Internally, the schema and IR layer is called **MarketIR** — a structured intermediate representation of tools, audiences, claims, evidence, messages, and campaigns. |
| 5 | +This repo defines **MarketIR** — a small, versioned "marketing intermediate representation" designed to be consumed by generators and the public site ([mcptoolshop.com](https://mcptoolshop.com)) without turning marketing into a manual, fragile process. |
6 | 6 |
|
7 | | -## Ground Rules |
| 7 | +--- |
8 | 8 |
|
9 | | -These rules are non-negotiable. CI enforces them. |
| 9 | +## What this is (and isn't) |
10 | 10 |
|
11 | | -### IDs are stable and permanent |
12 | | - |
13 | | -- IDs follow a namespace pattern: `tool.<slug>`, `aud.<name>`, `claim.<tool>.<slug>`, `ev.<tool>.<slug>.v<n>`, `msg.<tool>.<slug>`, `camp.<tool>.<slug>` |
14 | | -- IDs are **never renamed**. Deprecate instead (`status: "deprecated"`) |
15 | | -- All IDs must be unique across the entire graph |
16 | | - |
17 | | -### Claims must declare status |
| 11 | +**This is:** |
18 | 12 |
|
19 | | -Every claim has a `status`: |
| 13 | +- A structured source of truth for product messaging |
| 14 | +- Claims that are explicitly labeled **proven** vs **aspirational** |
| 15 | +- Evidence artifacts with **sha256 hashes + provenance** |
| 16 | +- Messages that **must trace back to claims** — no drive-by assertions |
20 | 17 |
|
21 | | -| Status | Meaning | |
22 | | -| -------------- | ---------------------------------------- | |
23 | | -| `proven` | Backed by at least one `evidenceRef` | |
24 | | -| `aspirational` | Believed true, evidence not yet captured | |
25 | | -| `deprecated` | No longer valid — kept for audit trail | |
| 18 | +**This is not:** |
26 | 19 |
|
27 | | -**Proven claims require evidence.** If a claim is `proven`, it must reference at least one entry in the evidence manifest. CI rejects proven claims with zero evidence. |
| 20 | +- A blog |
| 21 | +- A CMS |
| 22 | +- A place for vibes-based copy that can't be tested |
28 | 23 |
|
29 | | -### Evidence is hash-addressed |
| 24 | +--- |
30 | 25 |
|
31 | | -Every evidence artifact includes: |
| 26 | +## Core ideas |
32 | 27 |
|
33 | | -- `sha256` hash of the file content |
34 | | -- `bytes` size |
35 | | -- `provenance` object: who/what generated it, from which commit, and any notes |
| 28 | +| Principle | What it means | |
| 29 | +| --- | --- | |
| 30 | +| **Proof-first** | Proven claims must link to evidence. No evidence, no "proven" badge. | |
| 31 | +| **Deterministic** | Content is pinned by a lockfile. Hash drift fails CI. | |
| 32 | +| **Composable** | Messages are views of claims for different channels and audiences. | |
| 33 | +| **Honest** | Anti-claims prevent overreach. If a tool can't do something, say so. | |
36 | 34 |
|
37 | | -This makes evidence tamper-evident and reproducible. |
| 35 | +--- |
38 | 36 |
|
39 | | -### The lockfile is canonical |
| 37 | +## Repository layout |
40 | 38 |
|
41 | | -`marketing/manifests/marketing.lock.json` pins every included file by hash. CI regenerates the lockfile and fails if it differs from what's committed. This guarantees reproducible "marketing releases." |
| 39 | +``` |
| 40 | +marketing/ |
| 41 | + schema/ # MarketIR JSON Schema (2020-12, versioned) |
| 42 | + data/ |
| 43 | + tools/ # One file per tool (claims, messages, positioning) |
| 44 | + audiences/ # One file per audience (pain points, context) |
| 45 | + campaigns/ # One file per campaign (phases, channel sequences) |
| 46 | + marketing.index.json # Root index — everything starts here |
| 47 | + evidence/ # Evidence artifacts (screenshots, reports), hash-addressed |
| 48 | + manifests/ |
| 49 | + evidence.manifest.json # Evidence registry with sha256 + provenance |
| 50 | + marketing.lock.json # Lockfile pinning all files by hash |
| 51 | + scripts/ # validate, hash, gen-lock |
| 52 | +``` |
42 | 53 |
|
43 | | -### Messages must trace to claims |
| 54 | +### Authored vs generated |
44 | 55 |
|
45 | | -Every message should be derivable from claims. If a message asserts something not represented as a claim, that's a schema violation enforced by validation. |
| 56 | +| Type | Files | Edited by | |
| 57 | +| --- | --- | --- | |
| 58 | +| **Authored** | `schema/**`, `data/**`, `evidence.manifest.json` | Humans | |
| 59 | +| **Generated** | `marketing.lock.json` | `gen-lock.mjs` script | |
46 | 60 |
|
47 | | -### Deterministic serialization |
| 61 | +Everything must be reachable from `marketing/data/marketing.index.json`. No orphan files. |
48 | 62 |
|
49 | | -All JSON files use: |
| 63 | +--- |
50 | 64 |
|
51 | | -- Stable key ordering (sorted) |
52 | | -- Stable array ordering (by ID) |
53 | | -- Trailing newline |
| 65 | +## Determinism contract |
54 | 66 |
|
55 | | -This prevents "same data, different diff" noise. |
| 67 | +### IDs are stable and permanent |
56 | 68 |
|
57 | | -## Repo Structure |
| 69 | +IDs follow a namespace pattern and are **never renamed** — deprecate instead. |
58 | 70 |
|
59 | 71 | ``` |
60 | | -marketing/ |
61 | | - schema/ # JSON Schema (2020-12) definitions |
62 | | - data/ |
63 | | - tools/ # One file per tool |
64 | | - campaigns/ # One file per campaign |
65 | | - audiences/ # One file per audience |
66 | | - evidence/ # Evidence artifacts (screenshots, reports) |
67 | | - manifests/ # evidence.manifest.json + marketing.lock.json |
68 | | - scripts/ # validate, hash, gen-lock |
| 72 | +tool.<slug> → tool.zip-meta-map |
| 73 | +aud.<name> → aud.ci-maintainers |
| 74 | +claim.<tool>.<slug> → claim.zip-meta-map.deterministic-output |
| 75 | +ev.<tool>.<slug>.v<n> → ev.zip-meta-map.build-screenshot.v1 |
| 76 | +msg.<tool>.<slug> → msg.zip-meta-map.web-blurb |
| 77 | +camp.<tool>.<slug> → camp.zip-meta-map.launch |
69 | 78 | ``` |
70 | 79 |
|
71 | | -## Usage |
| 80 | +All IDs must be unique across the entire graph. |
| 81 | + |
| 82 | +### Claim status is explicit |
| 83 | + |
| 84 | +| Status | Rule | |
| 85 | +| --- | --- | |
| 86 | +| `proven` | Must include at least one `evidenceRef`. CI rejects proven claims with zero evidence. | |
| 87 | +| `aspirational` | Allowed, but must be labeled. Upgrade to proven only when evidence is added. | |
| 88 | +| `deprecated` | Kept for audit trail. Never deleted. | |
| 89 | + |
| 90 | +### Evidence is hash-verified |
| 91 | + |
| 92 | +Every evidence artifact includes `sha256`, `bytes`, and a `provenance` object (generator, source commit, notes). This makes evidence tamper-evident and reproducible. |
| 93 | + |
| 94 | +### Lockfile is canonical |
| 95 | + |
| 96 | +`marketing.lock.json` pins every included file by hash. CI regenerates the lockfile and fails if it differs from what's committed. Same data, same build, every time. |
| 97 | + |
| 98 | +### Messages trace to claims |
| 99 | + |
| 100 | +Every message references claims via `claimRefs`. If a message asserts something not represented as a claim, validation fails. |
| 101 | + |
| 102 | +### Deterministic serialization |
| 103 | + |
| 104 | +All JSON uses sorted keys, stable array ordering, and trailing newlines. This prevents "same data, different diff" noise. |
| 105 | + |
| 106 | +--- |
| 107 | + |
| 108 | +## Local workflow |
72 | 109 |
|
73 | 110 | ```bash |
74 | 111 | npm install |
75 | | -node marketing/scripts/validate.mjs # Schema + invariant checks |
76 | | -node marketing/scripts/gen-lock.mjs # Regenerate lockfile |
77 | | -node marketing/scripts/gen-lock.mjs --check # Fail if lock differs (CI mode) |
| 112 | + |
| 113 | +# Format check (Prettier) |
| 114 | +npm run format:check |
| 115 | + |
| 116 | +# Schema + invariant validation |
| 117 | +npm run validate |
| 118 | + |
| 119 | +# Lockfile drift check (CI mode) |
| 120 | +npm run lock:check |
| 121 | +``` |
| 122 | + |
| 123 | +**Typical development loop:** |
| 124 | + |
| 125 | +1. Edit or add files under `marketing/data/**` |
| 126 | +2. Add evidence entries to `marketing/manifests/evidence.manifest.json` (and artifacts under `marketing/evidence/` if applicable) |
| 127 | +3. Regenerate the lockfile: `node marketing/scripts/gen-lock.mjs` |
| 128 | +4. Validate: `npm run validate` |
| 129 | +5. Format: `npm run format:check` (fix with `npm run format`) |
| 130 | + |
| 131 | +--- |
| 132 | + |
| 133 | +## How it's consumed (site bridge) |
| 134 | + |
| 135 | +The public site treats this repo as a **read-only upstream**. No runtime fetches — everything is resolved at build time. |
| 136 | + |
78 | 137 | ``` |
| 138 | +mcpt-marketing (MarketIR, this repo) |
| 139 | + │ |
| 140 | + │ fetch + sha256 verification (lockfile-enforced) |
| 141 | + ▼ |
| 142 | +vendor snapshot (build-time, gitignored in site repo) |
| 143 | + │ |
| 144 | + │ Astro static build |
| 145 | + ▼ |
| 146 | +mcptoolshop.com |
| 147 | +``` |
| 148 | + |
| 149 | +The site's `fetch-marketir.mjs` script downloads files referenced in the lockfile, verifies every hash, and writes a local snapshot. If any hash mismatches, the build aborts. This keeps marketing traceable and reproducible. |
| 150 | + |
| 151 | +--- |
| 152 | + |
| 153 | +## Contribution rules |
| 154 | + |
| 155 | +The quality bar is simple and non-negotiable: |
| 156 | + |
| 157 | +- **Every claim must be falsifiable** — testable in principle, not just feel-good copy |
| 158 | +- **Upgrade aspirational → proven** only when you add evidence |
| 159 | +- **Messages must reference claims** — if it's said, it must be claimed |
| 160 | +- **Add anti-claims** whenever a tool is likely to be misused or misunderstood |
| 161 | +- **No orphan content** — everything must be reachable from the index |
| 162 | + |
| 163 | +--- |
79 | 164 |
|
80 | 165 | ## License |
81 | 166 |
|
82 | | -MIT |
| 167 | +MIT (see [LICENSE](LICENSE)). |
0 commit comments