From a5f247aecd3916f248321a4bd5ac31becaa4109d Mon Sep 17 00:00:00 2001 From: Codex Date: Sun, 8 Nov 2026 19:02:48 +0100 Subject: [PATCH] docs(roadmap): extend the pipeline into 2027 with six sourced initiatives Follows #1293, which landed the ten specs for the committed initiatives. That PR was merged before this work was pushed, so it ships separately. The roadmap ended at I-21. Three agents take work from it every day, so the pipeline needed depth, and depth is only useful if it is grounded. Six initiatives, each from a verified gap in a second market sweep covering angles the first pass missed - Discord, accessibility, cEDH meta sources, offline apps, collection apps and localisation: - I-22 Verification as a public surface. Six products generate decks and none publishes a verification contract. The validator is already deterministic and /api/v1 already exists. - I-23 The pod's own surface. Otterly MTG, Mana Grove and an open-source Commander bot already answer bracket questions in Discord. None carries a pod's declared Rule 0 agreement, which is I-15's artifact. - I-24 Decks a screen reader can play from. Blind players adapt cards with NFC tags read by a phone; braille fails because marked cards risk disqualification. No deckbuilder emits output shaped to be heard. - I-25 A third locale, chosen on evidence. Every AI deckbuilder found is English-only. Nine catalogues sit dormant here, and the spec refuses to pick from catalogue convenience. - I-26 Collections arriving from elsewhere. Scanning is already a non-goal, so import is the only honest way a collection is populated. - I-27 Learning while building. Tools assume the vocabulary and teaching lives in video. Nobody explains a rule at the moment it fires, and the repo already carries mtg-rules and mtg-learn skills. Four things the sweep ruled out are recorded so the next pass does not re-derive them. The most useful: tournament win rates stay blocked. EDHTop16, the best candidate, publishes commander meta share and entry counts but no win rates, no match-level results and no public API; MagicMeta and LucidPuzzle derive their tiers from it. The 2027 specs are deliberately less detailed than the Next-horizon ones. Committing to interface detail eighteen months early produces precision that ages rather than guides. Six and not twenty, stated in the roadmap: beyond these the sweep stopped producing gaps this product is positioned to fill, and inventing more would fill a roadmap without filling a pipeline. Verified on current dev: tsc clean, lint clean, 3510 tests passing, prettier clean, every relative link resolves. Co-Authored-By: Claude Opus 5 (1M context) --- docs/product/roadmap.md | 179 ++++++++++++++++++ docs/product/specs/README.md | 28 ++- .../i22-verification-as-a-public-surface.md | 66 +++++++ .../product/specs/i23-the-pods-own-surface.md | 69 +++++++ ...i24-decks-a-screen-reader-can-play-from.md | 65 +++++++ docs/product/specs/i25-a-third-locale.md | 65 +++++++ ...i26-collections-arriving-from-elsewhere.md | 76 ++++++++ .../specs/i27-learning-while-building.md | 72 +++++++ 8 files changed, 619 insertions(+), 1 deletion(-) create mode 100644 docs/product/specs/i22-verification-as-a-public-surface.md create mode 100644 docs/product/specs/i23-the-pods-own-surface.md create mode 100644 docs/product/specs/i24-decks-a-screen-reader-can-play-from.md create mode 100644 docs/product/specs/i25-a-third-locale.md create mode 100644 docs/product/specs/i26-collections-arriving-from-elsewhere.md create mode 100644 docs/product/specs/i27-learning-while-building.md diff --git a/docs/product/roadmap.md b/docs/product/roadmap.md index 161ab15f..2cba808a 100644 --- a/docs/product/roadmap.md +++ b/docs/product/roadmap.md @@ -1056,6 +1056,185 @@ Two snapshots can be compared from a recorded seed and sample size, and a rerun --- +# 2027 Horizon + +The initiatives above carry the work already committed. The six below extend the pipeline into 2027. Each comes from a **verified gap** in the 2026-11-08 market sweep, not from a brainstorm, and each names the evidence that produced it. + +Read them as hypotheses with a stated basis, not as commitments. A 2027 initiative is promoted to Next only when its spec's open questions are answered and its dependency has shipped. + +**Why six and not twenty.** Beyond these, the sweep stopped producing gaps the product is positioned to fill. Adding further initiatives would mean inventing them, which fills a roadmap without filling a pipeline. The honest way to extend 2027 further is another dated sweep, not a longer list. + +--- + +## I-22: Verification As A Public Surface + +**Spec:** [`specs/i22-verification-as-a-public-surface.md`](specs/i22-verification-as-a-public-surface.md) + +**Outcome:** another tool, a Discord bot or a tournament organiser can submit a decklist and receive the same deterministic verdict a player sees in the product, with its rules and its data dates. + +**Status:** Later +**Priority:** Later — 2027 +**Impact / effort:** High / medium +**Depends on:** I-02's claim typing. Do not expose a verdict whose provenance is not yet modelled internally. + +The sweep found six products generating decks and none publishing what was checked. The product's validator is its differentiator, and a differentiator nobody can call is a feature; a differentiator other tools depend on is a position. A read-only `/api/v1` already exists, so the surface is an extension rather than a new system. + +### Scope + +- [ ] Accept a decklist and a format, and return the deterministic verdict: legality, colour identity, singleton, banlist, Game Changers, bracket inputs. +- [ ] Return the rule and the data date behind every judgement, never a bare boolean. +- [ ] Version the contract, and keep an older version answering while a newer one exists. +- [ ] Rate-limit and authenticate per consumer, with a documented quota. +- [ ] Publish no recommendation through this surface. Verification only. + +### Definition of done + +A third party submits a list and receives a versioned, dated, rule-level verdict that matches what the product shows its own players for the same list. + +--- + +## I-23: The Pod's Own Surface + +**Spec:** [`specs/i23-the-pods-own-surface.md`](specs/i23-the-pods-own-surface.md) + +**Outcome:** a playgroup can ask for a deck's bracket, Game Changers and Rule 0 sheet inside the Discord server where it already argues about them, without anyone opening a browser. + +**Status:** Later +**Priority:** Later — 2027 +**Impact / effort:** Medium / medium +**Depends on:** I-15 pod sheets, and I-22 if the surface is built on the public contract rather than a private one. + +Otterly MTG, Mana Grove's `/bracket` command and several Commander companion bots already live in these servers, which is the evidence the demand is real. None of them carries a pod's declared Rule 0 agreement — that is I-15's artifact, and Discord is where the conversation it supports actually happens. + +### Scope + +- [ ] A command returning a deck's bracket and Game Changers with their data dates. +- [ ] A command rendering a consented Rule 0 sheet; never an unconsented one. +- [ ] Explicit, revocable linking between a Discord account and a product account. +- [ ] No deck mutation from the bot. Read and report only. +- [ ] State the same uncertainty the product states. A bot reply is not permitted to sound more certain than the web surface. + +### Definition of done + +A pod reads a consented sheet and a dated bracket in its own server, and nothing the bot can do changes a deck. + +--- + +## I-24: Decks A Screen Reader Can Play From + +**Spec:** [`specs/i24-decks-a-screen-reader-can-play-from.md`](specs/i24-decks-a-screen-reader-can-play-from.md) + +**Outcome:** a blind or low-vision player can read a complete deck — names, costs, full Oracle text, zones and tokens — through assistive technology, and take that reading to a table. + +**Status:** Later +**Priority:** Later — 2027 +**Impact / effort:** Medium / medium + +Blind players reach Magic today through community work: NFC tags on sleeves read by a phone, and a fan-made screen-reader mod for Arena. Braille failed because it thickens cards and marked cards are a disqualification risk. No deckbuilding site in the sweep publishes an assistive-technology-first output. The product already generates text exports and proxy PDFs, so the distance is short and the position is uncontested. + +### Scope + +- [ ] An export shaped for screen readers: structured headings per zone, full Oracle text, costs spelled out rather than symbol-only. +- [ ] Mana symbols carry text alternatives everywhere, including in the deck view. +- [ ] Make the deck view operable end to end by keyboard and screen reader, and assert it in tests rather than claiming it. +- [ ] Do not ship an audio player or a reader of our own. Serve the assistive technology the player already uses. +- [ ] Involve at least one assistive-technology user before calling any slice done. + +### Definition of done + +A deck's complete contents are reachable by screen reader and by keyboard, and an export exists that an assistive-technology user can read away from the site. + +--- + +## I-25: A Third Locale, Chosen On Evidence + +**Spec:** [`specs/i25-a-third-locale.md`](specs/i25-a-third-locale.md) + +**Outcome:** a third language is activated with its navigation, warnings, dates, prices and card surfaces translated and tested as one experience. + +**Status:** Later +**Priority:** Later — 2027 +**Impact / effort:** Medium / medium +**Depends on:** I-11's activation rule, which already forbids routing a dormant catalogue. + +Nine catalogues are dormant. Every AI deckbuilder found in the sweep is English-only, which makes a non-English market the least contested expansion available — but the choice must come from evidence rather than from catalogue convenience. Scryfall already supplies localised card data for the candidates. + +### Scope + +- [ ] Choose the locale from stated evidence: player population, Scryfall card-data coverage, and whether prices in that market are representable without implying a quote. +- [ ] Complete and human-review the catalogue before routing it. +- [ ] Test dates, numbers, pluralisation, mana symbols and card text together, as I-11 requires. +- [ ] State what is not localised — card data Scryfall does not carry in that language — rather than falling back silently. + +### Definition of done + +One additional locale is routed, reviewed and covered end to end, and the surfaces it cannot localise say so. + +--- + +## I-26: Collections Arriving From Elsewhere + +**Spec:** [`specs/i26-collections-arriving-from-elsewhere.md`](specs/i26-collections-arriving-from-elsewhere.md) + +**Outcome:** a player can bring a collection out of the app that already holds it, at printing level, without retyping it. + +**Status:** Later +**Priority:** Later — 2027 +**Impact / effort:** High / medium +**Depends on:** I-06 printing-level ownership. Importing at Oracle level would discard exactly the information that makes I-16 and I-06 trustworthy. + +Collections already live in ManaBox, Moxfield, Deckbox and in spreadsheets, and ManaBox is the scanner most paper players use. The sweep found collection-to-deck ranking in five products; the precondition for all of it is getting the collection in. The product's own non-goals exclude building a scanner, which makes import the only honest path to a populated collection. + +### Scope + +- [ ] Import from the CSV exports of the major collection apps, mapping to printing identity. +- [ ] Preview before writing: matched rows, unmatched rows, and duplicates, with the same disclosure discipline the deck import preview already uses. +- [ ] Never silently merge. An ambiguous printing is reported, not guessed. +- [ ] Record the source and date of an import, so a collection's provenance is readable later. +- [ ] Support re-import as reconciliation rather than duplication. + +### Definition of done + +A collection exported from another app lands at printing level with its unmatched rows disclosed, and a second import reconciles instead of duplicating. + +--- + +## I-27: Learning While Building + +**Spec:** [`specs/i27-learning-while-building.md`](specs/i27-learning-while-building.md) + +**Outcome:** a new Commander player can understand _why_ the product flags something, in the moment, without leaving the deck. + +**Status:** Later +**Priority:** Later — 2027 +**Impact / effort:** Medium / medium + +The beginner audience is the largest in Commander and the one the category serves worst: tier lists and optimisers assume the vocabulary. The repository already carries `mtg-rules` and `mtg-learn` skills and a comprehensive rules reference, and I-03 already explains warnings. This initiative connects assets the project already owns rather than acquiring new ones. + +### Scope + +- [ ] Attach a short, sourced explanation to each warning class — colour identity, singleton, bracket inputs, companion rules — reachable in one action from the warning. +- [ ] Link to the comprehensive rules reference where a rule is quoted, with its rules version. +- [ ] Keep explanations deterministic and authored. Do not generate rules text with the model. +- [ ] Never block or gate a build behind a lesson. + +### Definition of done + +Every warning class the product raises can be explained in place, from an authored, sourced note, without leaving the deck. + +--- + +### What the sweep ruled out for 2027 + +Recording these saves the next pass from re-deriving them: + +- **Tournament win rates remain blocked.** EDHTop16, the most promising candidate found, publishes commander meta share and entry counts but **no win rates, no match-level results and no public API**. MagicMeta and LucidPuzzle derive their tiers from it. The roadmap's existing block stands, and the reason is now recorded. +- **Card scanning** stays a non-goal: ManaBox owns it, it is a native-camera capability, and I-06's own scope defers it behind printing-level ownership. +- **A table companion** — life totals, commander damage, turn timers — is served by Discord bots and the official app, and is a different product from a deckbuilder. I-19 covers the only table need the product should meet. +- **Marketplace, cart and checkout** remain excluded by the existing non-goals. I-06 hands off to sellers; it does not become one. + +--- + # Completed Foundation These capabilities are not future bets. They are part of the product baseline: diff --git a/docs/product/specs/README.md b/docs/product/specs/README.md index 11509be6..3a658f62 100644 --- a/docs/product/specs/README.md +++ b/docs/product/specs/README.md @@ -12,7 +12,7 @@ Every spec follows the same shape, matching the house format already used by [`c The **Delivery slices** table is the part that matters for automation: each slice is independently reviewable, and the dependency column says which ones cannot start yet. Three scheduled agents pick work from this roadmap every day — the dependency edges are what stop them colliding. -## Index +## Committed work | Spec | Initiative | Status | The one-line reason it exists | | ------------------------------------------------------------------------------- | ---------- | ------ | ----------------------------------------------------------------------------------------------------- | @@ -27,6 +27,32 @@ The **Delivery slices** table is the part that matters for automation: each slic | [Collaborative review](i20-collaborative-review.md) | I-20 | Later | Archidekt gives collaborators direct write access; propose-and-accept exists nowhere | | [Reproducible probability bench](i21-reproducible-probability-bench.md) | I-21 | Later | Five tools simulate thousands of hands; none publishes a seed or an interval | +## 2027 horizon + +Six initiatives extending the pipeline into 2027, each from a verified gap in the same sweep. They are hypotheses with a stated basis, not commitments: a 2027 initiative is promoted to Next only once its open questions are answered and its dependency has shipped. Their specs are deliberately less detailed than the ones above — committing to interface details eighteen months early produces precision that ages rather than guides. + +| Spec | Initiative | The gap it answers | +| --------------------------------------------------------------------------------- | ---------- | ------------------------------------------------------------------------------------------ | +| [Verification as a public surface](i22-verification-as-a-public-surface.md) | I-22 | Six products generate decks; none publishes a verification contract | +| [The pod's own surface](i23-the-pods-own-surface.md) | I-23 | Three Discord bots answer bracket questions; none carries a pod's declared agreement | +| [Decks a screen reader can play from](i24-decks-a-screen-reader-can-play-from.md) | I-24 | Blind players adapt cards with NFC tags; no deckbuilder emits output shaped to be heard | +| [A third locale, chosen on evidence](i25-a-third-locale.md) | I-25 | Every AI deckbuilder found is English-only; nine catalogues sit dormant here | +| [Collections arriving from elsewhere](i26-collections-arriving-from-elsewhere.md) | I-26 | Scanning is a non-goal, so import is the only honest way a collection gets populated | +| [Learning while building](i27-learning-while-building.md) | I-27 | Tools assume the vocabulary; teaching lives in video. Nobody explains a rule when it fires | + +### What the sweep ruled out for 2027 + +Recorded so the next pass does not re-derive them: + +- **Tournament win rates stay blocked.** EDHTop16, the most promising candidate, publishes commander meta share and entry counts — **no win rates, no match-level results, no public API**. MagicMeta and LucidPuzzle derive their tiers from it. The roadmap's existing block stands. +- **Card scanning** stays a non-goal: ManaBox owns it, it is a native-camera capability, and I-06 defers it behind printing-level ownership regardless. +- **A table companion** — life totals, commander damage, timers — is already served by Discord bots and the official app, and is a different product. +- **Marketplace and checkout** remain excluded. I-06 hands off to sellers; it does not become one. + +### Why six + +Beyond these, the sweep stopped producing gaps this product is positioned to fill. Further initiatives would be invention, which fills a roadmap without filling a pipeline. Extending 2027 further is the job of another dated sweep, not a longer list. + ## What the sweep concluded Three findings shaped every spec above. diff --git a/docs/product/specs/i22-verification-as-a-public-surface.md b/docs/product/specs/i22-verification-as-a-public-surface.md new file mode 100644 index 00000000..82849f6a --- /dev/null +++ b/docs/product/specs/i22-verification-as-a-public-surface.md @@ -0,0 +1,66 @@ +# Spec: Verification As A Public Surface (I-22) + +> **Initiative:** [I-22 in the roadmap](../roadmap.md) · **Status:** Later — 2027 · **Researched:** 2026-11-08 +> **Depends on:** I-02's claim typing. **Owns:** the external verdict contract. **Does not own:** recommendations, which never travel through this surface. + +A 2027-horizon spec. Its requirements are deliberately less detailed than a Next-horizon spec: committing to interface details eighteen months early produces precision that ages rather than guides. + +## Overview + +The product's differentiator is a deterministic verdict nobody else publishes. Inside the product it is a feature. Exposed as a contract other tools depend on, it becomes a position: a Discord bot, a tournament organiser or a competing builder can ask "is this list legal, and by which rule" and get an answer with its rule and its data date attached. + +## What the market does + +The sweep of 2026-11-08 found six products generating Commander decks — ManaTap, Farseek, DeckCheck, MTG Master, ManaForge, CommanderSalt — and **none publishing a verification API**. Several validate internally; DeckCheck documents that its AI output varies between runs. + +Related surfaces that do exist: + +- **Scryfall** publishes card data as free infrastructure every competitor consumes. It is the proof that an openly consumed contract becomes the category's reference point. +- **Commander Spellbook** publishes combo data openly and is consumed by this product already. +- **Moxfield** went the other way: no public API, Cloudflare in front of programmatic requests. The sweep recorded third-party tools moving to paste and CSV as a result. + +The opening is the unclaimed middle: nobody is the place you send a list to find out whether it is legal and why. + +## Current state in this codebase + +- A **versioned read-only external API under `/api/v1`** already exists — the surface is an extension, not a new system. +- `src/lib/deck/bracket.ts`, colour-identity and legality validation, banlist and Game Changers detection are already deterministic and already tested. +- The verdict is currently **applied**, not **described**: there is no internal shape carrying "this judgement, by this rule, from data dated X". I-02 slice 1 creates it, which is why this initiative depends on it. + +## Functional requirements + +1. **Submit a list, receive a verdict.** Decklist plus format in; legality, colour identity, singleton, banlist, Game Changers and bracket inputs out. +2. **Never a bare boolean.** Every judgement carries the rule that produced it and the date of the data behind it. A verdict a consumer cannot explain to their own user is not worth exposing. +3. **Versioned, with an overlap.** A new contract version does not retire the previous one on the same day; consumers need a window. +4. **Authenticated and quotaed**, per consumer, with the quota documented rather than discovered by hitting it. +5. **Verification only.** No card suggestions, no generated text, no AI output of any kind crosses this boundary. The surface is valuable precisely because it is deterministic. +6. **Identical to what players see.** The same list submitted to the API and opened in the product produces the same verdict. A divergence is a defect, and a test must be able to catch it. + +## Non-goals + +- Recommendations, generation or any model output. +- Write access of any kind. Nothing outside the product mutates a deck. +- A free unlimited tier. Scryfall can absorb anonymous load; this product cannot, and pretending otherwise ends in an outage. +- Becoming a card-data source. Scryfall owns that, and the existing strategic boundary says so. + +## Testing strategy + +- **Parity:** a fixture corpus of lists produces identical verdicts through the API and through the internal path. This test is the point of the initiative. +- **Contract:** every judgement in a response carries a rule and a data date; one that does not fails. +- **Versioning:** a request pinned to version n keeps its shape after n+1 ships. +- **Isolation:** no route in this surface can write — asserted against the Prisma client, as I-16's read-only route requires. + +## Delivery slices + +| # | Slice | Depends on | +| --- | --------------------------------------------------------------------- | ---------- | +| 0 | **I-02 slice 1** — claims typed internally with rule and date | blocking | +| 1 | Verdict shape, internal, with the parity test against the player path | 0 | +| 2 | `/api/v1` endpoint, single version, authenticated | 1 | +| 3 | Quota, documentation, and the read-only assertion | 2 | +| 4 | Version negotiation and an overlap window | 2 | + +## Open questions + +- Who are the first consumers? Building a public contract before one real consumer exists is how APIs acquire the wrong shape. I-23's Discord surface is the natural first client, and building it _on_ this contract would validate the shape before anyone external depends on it. +- Does publishing the verdict invite competitors to consume the differentiator rather than buy it? Probably — and that is also how Scryfall became indispensable. Worth deciding deliberately rather than by default. diff --git a/docs/product/specs/i23-the-pods-own-surface.md b/docs/product/specs/i23-the-pods-own-surface.md new file mode 100644 index 00000000..a42a4f17 --- /dev/null +++ b/docs/product/specs/i23-the-pods-own-surface.md @@ -0,0 +1,69 @@ +# Spec: The Pod's Own Surface (I-23) + +> **Initiative:** [I-23 in the roadmap](../roadmap.md) · **Status:** Later — 2027 · **Researched:** 2026-11-08 +> **Depends on:** I-15 pod sheets. Built on I-22's contract if that ships first. + +A 2027-horizon spec: scope and intent are firm, interface details are deliberately left open. + +## Overview + +The Rule 0 conversation does not happen on a deckbuilding site. It happens in a Discord server, thirty seconds before the first turn, or in the thread where the pod organises the evening. This initiative puts the two artifacts that conversation needs — the dated bracket and the consented Rule 0 sheet — where the conversation already is. + +## What the market does + +Discord is an established Magic surface, and bots already occupy the adjacent space. + +| Bot | What it does | +| ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **Otterly MTG** | Deck analysis explaining a deck's strength against the Commander power brackets, combo detection, Moxfield import, a "Recommander" suggestion tool, and a companion web builder | +| **Scry / Mana Grove** | Finds cards by effect, and a `/bracket` command that returns a decklist's bracket | +| **MTG Commander bot** (open source) | Life tracking for four players, commander damage, Scryfall card search, dice, session management | + +The existence of three independent bots answering bracket and card questions is the evidence that the demand is real and that nobody needs convincing to install one. + +**What none of them carries:** a pod's _declared_ agreement. Every bot classifies a deck from its list. I-15's sheet records what four people actually said they were bringing — speed, combos, extra turns, denial, proxies, house rules — and that artifact has no home in the place the agreement is made. + +## Current state in this codebase + +- No Discord integration, no bot, no OAuth link to a third-party identity beyond NextAuth's Google provider. +- `src/lib/deck/bracket.ts` and the Game Changers detection produce exactly the values a `/bracket` reply needs. +- Public deck pages and share tokens exist (I-08), with the rule that private decks and share tokens stay out of search indexes — the same discipline must extend to anything the bot can echo. + +## Functional requirements + +1. **Dated bracket on request.** A command returns a deck's bracket, its Game Changers, and the date of the data behind both. +2. **Consented sheets only.** The bot renders an I-15 sheet only where consent was given for that pod. An unconsented sheet is not merely hidden — the bot must be unable to fetch it. +3. **Explicit account linking.** A Discord identity is linked to a product account by a deliberate, revocable action. Revoking takes effect immediately. +4. **Read and report only.** No command mutates a deck, a collection, a sheet or ownership. The bot has no write path at all. +5. **The same uncertainty.** A bot reply carries the same source labels and freshness dates the web surface shows. A one-line reply must not sound more certain than the page it summarises. +6. **No private leakage.** A deck that is private stays unreachable through the bot, including by anyone who knows its id. + +## Non-goals + +- Life tracking, commander damage, dice or turn timers. Three bots already do it, and it is not this product. +- Deck building inside Discord. +- Card search. Scryfall's own bot and Mana Grove serve it. +- A presence in any other chat platform before this one is validated. + +## Testing strategy + +- **Permission:** every command, invoked for a deck the caller does not own and has no consent for, returns refusal — enumerated per command. +- **Consent:** revoking a pod consent makes the sheet unfetchable on the next call, not merely unrendered. +- **Parity:** a bracket reported by the bot equals the bracket the product shows for the same deck at the same moment. +- **Write isolation:** the bot's credentials are rejected by every mutating route. + +## Delivery slices + +| # | Slice | Depends on | +| --- | ---------------------------------------------------------- | --------------- | +| 1 | Account linking, revocable, with no command yet | — | +| 2 | `/bracket` returning bracket, Game Changers and data dates | 1 | +| 3 | Consented I-15 sheet rendering | 1, I-15 slice 3 | +| 4 | Private-deck isolation tests and the write-path assertion | 2, 3 | + +Slice 4 is not a cleanup pass: it is the slice that makes the first three safe to leave running, and it should not trail them by more than one PR. + +## Open questions + +- Build on I-22's public contract, or on a private internal one? Using I-22 makes this initiative its first real consumer and validates that contract before anyone external depends on it — a strong argument for sequencing I-22 first even though it is the larger piece. +- Does a bot create a support surface the project cannot staff? A bot that is down is a visible failure in someone's server. Worth an explicit decision about what "unmaintained" would look like before shipping. diff --git a/docs/product/specs/i24-decks-a-screen-reader-can-play-from.md b/docs/product/specs/i24-decks-a-screen-reader-can-play-from.md new file mode 100644 index 00000000..13c0b333 --- /dev/null +++ b/docs/product/specs/i24-decks-a-screen-reader-can-play-from.md @@ -0,0 +1,65 @@ +# Spec: Decks A Screen Reader Can Play From (I-24) + +> **Initiative:** [I-24 in the roadmap](../roadmap.md) · **Status:** Later — 2027 · **Researched:** 2026-11-08 +> **Owns:** assistive-technology-first deck output. **Does not own:** general UI accessibility, which is an acceptance threshold on every I-13 slice. + +## Overview + +A blind player can own a Commander deck and cannot read it. This initiative makes the deck's complete contents — names, costs, full Oracle text, zones, tokens — reachable through the assistive technology the player already uses, and exportable so it travels to a table. + +## What the market does + +Nothing in the deckbuilding category serves this. The accessibility work in Magic is being done by players, not by tools. + +- A blind player has adapted cards since 2020 using **NFC tags** that let a phone's screen reader read out a full card when the card is brought near. That system carried him to the National Modern Championship in Soria, December 2024. +- **Braille failed** for a structural reason worth recording: it thickens cards, making decks hard to shuffle, and marked cards read as signalling in sanctioned play — a disqualification risk. +- **Accessible Arena**, a fan-made mod by a blind player, adds screen-reader support and keyboard navigation to almost all of MTG Arena. Wizards ships no accessible client itself; that is the community's standing request. + +**The read.** The adaptation layer is the phone's screen reader, and the missing input is **structured deck text a screen reader can move through**. Every deckbuilding site, this one included, emits lists designed to be looked at. None emits one designed to be heard. The gap is small in engineering terms and entirely uncontested. + +## Current state in this codebase + +- Plain-text and multi-format exports exist (I-10); proxy PDF export exists (I-06). Both are visual artifacts. +- Mana symbols render as Scryfall SVGs and as coloured pills. Their text alternatives have never been audited for a screen reader reading a 100-card list aloud — "W U B R G" read as five letters is not the same as "one white, one blue". +- `docs/rules/` carries the comprehensive rules reference, and localized Oracle text is already available where Scryfall provides it. +- I-04 and I-13 carry general accessibility work. This initiative is the **output**, not the chrome. + +## Functional requirements + +1. **An export shaped to be heard.** Structured headings per zone, one card per block, full Oracle text included, and mana costs spelled in words rather than symbols alone. +2. **Text alternatives everywhere.** Every mana symbol, every bracket indicator, every legality badge carries an alternative that reads correctly in a sentence — in both supported locales. +3. **The deck view is operable.** End-to-end keyboard and screen-reader operation of the deck view, asserted by automated tests rather than claimed in a changelog. +4. **Serve the player's own tools.** No bundled audio player, no in-house reader, no proprietary format. The output targets screen readers already in use. +5. **No separate degraded page.** The accessible path is the same deck, exported differently — not a stripped parallel site that drifts. + +## Non-goals + +- Building a screen reader, a voice interface, or an audio player. +- NFC tag generation or physical card adaptation. +- Claiming conformance to a standard without an audit. Say what was tested and by whom. +- Replacing the proxy PDF, which serves a different need. + +## Testing strategy + +- **Automated:** the deck view passes an accessibility scan with zero violations at the level I-13's thresholds require; every interactive element has a visible focus state. +- **Semantic:** the export's heading structure is well-formed and zone transitions are announced. +- **Content:** a mana cost renders as readable words in both locales; a symbol-only alternative fails the test. +- **Human:** at least one assistive-technology user reviews a slice before it is called done. This requirement is not optional and not replaceable by a scanner. + +## Delivery slices + +| # | Slice | Depends on | +| --- | -------------------------------------------------------------------------------- | ---------- | +| 1 | Audit the deck view with a screen reader and record what fails | — | +| 2 | Text alternatives for mana, bracket and legality indicators, both locales | 1 | +| 3 | Screen-reader export with zone headings and full Oracle text | 2 | +| 4 | Keyboard and screen-reader operation of the deck view, with automated assertions | 2 | +| 5 | Review with an assistive-technology user, and act on it | 3, 4 | + +Slice 1 is cheap and will likely reshape slices 2 to 4. Do not plan past it in detail. + +## Open questions + +- Who reviews? A spec that requires a human reviewer and does not name how to find one is a spec that quietly drops the requirement. Commander accessibility communities exist and should be approached before slice 1, not after slice 4. +- Does the export belong in I-10's format contracts, with fixtures and round-trip tests, or is it a one-way artifact? One-way is simpler and probably right: nothing re-imports an audio-shaped list. +- Localized Oracle text is incomplete outside English. The export must state what it could not localise rather than silently mixing languages mid-deck. diff --git a/docs/product/specs/i25-a-third-locale.md b/docs/product/specs/i25-a-third-locale.md new file mode 100644 index 00000000..3415b4fa --- /dev/null +++ b/docs/product/specs/i25-a-third-locale.md @@ -0,0 +1,65 @@ +# Spec: A Third Locale, Chosen On Evidence (I-25) + +> **Initiative:** [I-25 in the roadmap](../roadmap.md) · **Status:** Later — 2027 · **Researched:** 2026-11-08 +> **Depends on:** I-11's activation rule, which already forbids routing a dormant catalogue. + +## Overview + +Nine catalogues sit dormant. I-11 already states the rule for activating one: navigation, warnings, dates, prices and card surfaces translated and tested as a single experience. This spec adds the part I-11 leaves open — **which** locale, and on what evidence. + +## What the market does + +The clearest finding of the 2026-11-08 sweep, and the one nobody seems to have acted on: **every AI deckbuilder found is English-only.** ManaTap, Farseek, DeckCheck, MTG Master, ManaForge, OffMeta, CardMystic, Find That Card, Imskir — not one advertises a second language. + +The incumbents are barely better. Moxfield, Archidekt and EDHREC are English-first; ManaBox is the notable exception, advertising multiple languages alongside its offline database. + +Meanwhile Scryfall already publishes localised card names, type lines and Oracle text for the major printing languages, so the card layer is not the obstacle — the interface and the review are. + +**The read.** A non-English Commander market is the least contested expansion available to this product, and it already ships two reviewed locales while competitors ship one. The risk is not translation; it is activating a locale whose card data or prices cannot be represented honestly. + +## Current state in this codebase + +- English and French routed; a locale switcher and a catalogue parity guard exist. +- Localised card names, type lines, rules text and images where Scryfall provides them. +- Nine dormant catalogues — `de`, `it`, `es`, `ja`, `zh`, `ko`, `ru`, `pt` — deliberately unrouted. A dormant prefix returns a 404 in English, which is already tested. +- Prices are USD throughout, formatted per locale, explicitly **not** relabelled as a local-market quote (#980, #1015). + +The infrastructure is complete. What is missing is a decision and a review. + +## Functional requirements + +1. **Choose on stated evidence.** The selection records three things: the size of the Commander population in that language, the completeness of Scryfall's card data for it, and whether prices for that market can be shown without implying a quote. The record lives in this spec when the decision is made. +2. **Human review before routing.** No locale is routed on machine translation alone. I-11's rule stands. +3. **Test the locale as one experience** — dates, numbers, pluralisation, mana symbols and card text together, not field by field. +4. **State the limits.** Where Scryfall carries no card text in that language, say so on the surface rather than falling back silently to English mid-list. +5. **Prices stay honest.** Either represent the local market properly, or keep USD with its existing disclosure. Do not invent a conversion. + +## Non-goals + +- Activating several locales at once. The parity guard makes adding a catalogue cheap and reviewing it expensive; the review is the work. +- Right-to-left layout support, unless the chosen locale needs it — in which case it is a separate, larger initiative and must be said so before the choice is made. +- Localising player-authored content: primers, notes and comments stay in the language their author wrote them. + +## Testing strategy + +- **Parity:** the catalogue guard passes for the new locale with no missing keys. +- **Routing:** the locale resolves, and the previously dormant prefix stops returning the English 404. +- **Combined:** one test exercises a date, a number, a plural, a mana symbol and a card name together on one page in the new locale. +- **Fallback disclosure:** a card Scryfall does not carry in that language renders with its stated fallback, not a silent English substitution. + +## Delivery slices + +| # | Slice | Depends on | +| --- | ------------------------------------------------------------ | ---------- | +| 1 | Record the choice and its evidence in this spec | — | +| 2 | Complete the catalogue and obtain human review | 1 | +| 3 | Card-data coverage audit and the fallback disclosure surface | 1 | +| 4 | Route the locale and run the combined experience test | 2, 3 | +| 5 | Price representation decision for that market | 3 | + +Slice 1 is a decision, not code, and it blocks everything. It is also the slice most likely to be skipped — which is how a half-translated locale reaches production. + +## Open questions + +- Which locale? The honest answer is that this spec cannot decide it from a competitive sweep alone; it needs the product's own traffic and the card-data audit from slice 3. Deciding from catalogue convenience — "Spanish is nearly done" — is exactly the failure I-11 was written to prevent. +- Does a third locale increase the review burden on every future feature? Yes, and permanently. That cost belongs in the slice-1 decision rather than being discovered in 2028. diff --git a/docs/product/specs/i26-collections-arriving-from-elsewhere.md b/docs/product/specs/i26-collections-arriving-from-elsewhere.md new file mode 100644 index 00000000..fe904a1d --- /dev/null +++ b/docs/product/specs/i26-collections-arriving-from-elsewhere.md @@ -0,0 +1,76 @@ +# Spec: Collections Arriving From Elsewhere (I-26) + +> **Initiative:** [I-26 in the roadmap](../roadmap.md) · **Status:** Later — 2027 · **Researched:** 2026-11-08 +> **Depends on:** I-06 printing-level ownership. Importing at Oracle level discards exactly what makes I-16 and I-06 trustworthy. + +## Overview + +Every collection feature in the product assumes a populated collection. Nobody types twenty thousand cards. This initiative gets a collection **in**, at printing level, from the apps that already hold it. + +## What the market does + +The sweep found collection-to-deck ranking in five products — SuperBrew, DeckFinder, ManaBuilder, MTG Agents, ManaForge. All of them share one precondition, and it is the same one this product has: the collection must arrive from somewhere. + +Where collections actually live: + +- **ManaBox** — the scanner most paper players use. Free, offline card database, camera scanning, CSV export. It is the de facto on-ramp for paper collections. +- **Moxfield**, **Deckbox**, **Archidekt** — collection features alongside deckbuilding, with CSV export. +- **Spreadsheets** — still the largest single format, and the reason a tolerant CSV importer matters more than any single app integration. +- **MTG Arena** — a different inventory with wildcards; ManaForge reads it, and the product's non-goals exclude it. + +**The constraint that shapes this spec.** Camera scanning is already a stated non-goal: it is a native-camera capability, ManaBox owns it, and I-06 defers it behind printing-level ownership anyway. Import is therefore not one path among several — it is the **only** honest way this product gets a populated collection. + +## Current state in this codebase + +- `src/lib/collection/parse.ts`, `printing-csv.ts`, `acquisition-csv.ts` — CSV handling exists, oriented to **export**. +- Deck import has a mature preview discipline (I-10): unresolved names disclosed before confirmation, duplicates surfaced, zones labelled, and confirmation disabled when nothing resolves. That discipline is the model to copy here. +- Collection ownership is tracked, with the printing-level model still open in I-06. +- **Missing:** any collection import, from any source. + +## Functional requirements + +1. **Accept the real formats.** CSV exports from the major collection apps, plus a generic mapping for spreadsheets. Column mapping is explicit and reviewable, not guessed silently. +2. **Map to printing identity.** Set code, collector number, finish and language where the source provides them. A row that resolves only to an Oracle card is reported as ambiguous, not assigned a printing. +3. **Preview before writing**, with matched rows, unmatched rows and duplicates — the same disclosure the deck import preview already performs. +4. **Never merge silently.** An ambiguous printing is listed for the player to resolve or skip. Guessing here corrupts cost calculations everywhere downstream. +5. **Record provenance.** Each import stores its source app and date, so a collection's history is readable later. +6. **Re-import reconciles.** A second import of the same source updates quantities rather than duplicating rows, and says what it changed. + +## Data notes + +- An import is a reviewable transaction: a staged set of rows, a preview, then an explicit commit. A half-applied import is worse than a refused one. +- Store the raw source row alongside the resolved printing. When a mapping later proves wrong, the original is still there to re-resolve. + +## Non-goals + +- Camera or barcode scanning, in any form. +- MTG Arena inventory and wildcards. +- Continuous sync with another app. One-way, player-initiated import. Sync implies conflict resolution, which is a different initiative. +- Writing collections back out to those apps. Export already exists and is not this initiative's concern. + +## Testing strategy + +- **Fixtures per source.** A real exported CSV per supported app, committed as a fixture, with its expected resolution. Formats change; fixtures are how that is noticed. +- **Ambiguity:** a row resolving to several printings appears in the preview as ambiguous and writes nothing on commit unless resolved. +- **Idempotence:** importing the same file twice leaves quantities unchanged and reports zero additions. +- **Atomicity:** an import failing midway leaves the collection exactly as it was. +- **Scale:** a 20 000-row file previews within the route's deadline, or streams with progress. + +## Delivery slices + +| # | Slice | Depends on | +| --- | ----------------------------------------------------------- | ---------- | +| 0 | **I-06 printing-level ownership** — blocking | — | +| 1 | Generic CSV import with explicit column mapping and preview | 0 | +| 2 | Printing resolution with ambiguity reporting | 1 | +| 3 | Commit as an atomic transaction, with provenance recorded | 2 | +| 4 | Per-app fixtures and presets, starting with ManaBox | 2 | +| 5 | Re-import reconciliation with a change report | 3 | + +Slice 4 is where this initiative earns its keep: a ManaBox preset turns "export, map twelve columns, hope" into one action for the largest group of paper players. + +## Open questions + +- How much mapping should be automatic? Auto-detecting a known app's header row is a large convenience and a quiet source of wrong imports. Detect, then **show what was detected** and require confirmation. +- Foils, signed cards, proxies and condition: ManaBox tracks proxy and signed state as first-class data. I-06's model must decide whether those travel, or the import silently flattens a distinction the player cares about. +- Is there a legal or terms-of-service constraint on consuming another app's export on the player's behalf? The player owns their data and initiates the transfer, which is the defensible position — but it should be checked, not assumed. diff --git a/docs/product/specs/i27-learning-while-building.md b/docs/product/specs/i27-learning-while-building.md new file mode 100644 index 00000000..340295b3 --- /dev/null +++ b/docs/product/specs/i27-learning-while-building.md @@ -0,0 +1,72 @@ +# Spec: Learning While Building (I-27) + +> **Initiative:** [I-27 in the roadmap](../roadmap.md) · **Status:** Later — 2027 · **Researched:** 2026-11-08 +> **Owns:** authored explanations attached to warnings. **Does not own:** the warnings themselves, which stay in I-03. + +## Overview + +The product tells a new player their deck breaks colour identity. It does not tell them what colour identity _is_. This initiative attaches a short, authored, sourced explanation to every warning class, reachable in one action, without leaving the deck. + +## What the market does + +The beginner audience is the largest in Commander and the worst served by tooling. The sweep found two separate worlds that never meet: + +- **Tools assume the vocabulary.** EDHREC, Moxfield, Archidekt, the bracket calculators and every AI builder present inclusion rates, Lift, brackets and salt to someone presumed to already know what they mean. DeckCheck's DTI and PowerTune are proprietary scales explained in a support page, not at the point of use. +- **Teaching lives in media.** Tolarian Community College and Commanders Quarters built large audiences explaining this in video; the competitive-landscape document already identifies them as the beginner-influence channel. Written guidance lives in articles on Draftsim, RateMyDecks and PreconForge. + +**The gap is the join, again.** Nobody explains the rule _at the moment the rule fires_. A player who has just been told their deck is illegal is the most motivated learner in Magic, and every tool sends them to a search engine. + +This product is unusually well placed, and not because of ambition: the assets already exist. + +## Current state in this codebase + +- `.agents/skills/mtg-rules` and `.agents/skills/mtg-learn` — rules and learning skills already in the repository. +- `docs/rules/` — the comprehensive rules reference, with its dated version. +- I-03 already ships: explanations and next actions for legality warnings, the rule or calculation behind a legality warning shown on demand, and hard errors separated from strategic suggestions. +- `docs/product/user-guide.md` exists. + +So I-03 already explains **what the product computed**. This initiative explains **the rule of the game behind it** — a different question, and the one a beginner is actually asking. + +## Functional requirements + +1. **One explanation per warning class**, not per card: colour identity, singleton, format legality, banlist, Game Changers, companion rules, bracket inputs, deck size. +2. **One action away.** Reachable from the warning itself, inline, without navigation that loses the deck state. +3. **Authored and deterministic.** Written by a person, stored as content, reviewed. **The model never generates rules text** — this is the same boundary I-02 draws around legality, applied to teaching. +4. **Sourced and versioned.** Where an explanation quotes the comprehensive rules, it cites the rule number and the rules version it was written against. +5. **Never a gate.** No lesson blocks a build, no tutorial interrupts, nothing must be dismissed before continuing. The existing onboarding modal — which currently covers the landing page and breaks an e2e test — is the anti-pattern to avoid repeating. +6. **Both locales**, following I-11's rule: an explanation that is not reviewed in a locale is not shown in it. + +## Non-goals + +- A course, a curriculum, or progress tracking. +- Generating rules explanations with the LLM. +- Replacing the comprehensive rules reference. This links to it; it does not restate it. +- Teaching deckbuilding strategy. The rules are objective; strategy is the copilot's job and is labelled as reasoning. +- Any interruption of an experienced player's flow. + +## Testing strategy + +- **Coverage:** every warning class the product can raise has an explanation; a class without one fails the test. This is what stops the content drifting behind the code. +- **Determinism:** explanations come from stored content; no provider call occurs on this path. +- **Citation:** an explanation quoting a rule carries a rule number and a rules version. +- **Non-blocking:** with explanations present, every build flow completes without opening one. +- **Locale:** an unreviewed locale shows no explanation rather than an English one. + +## Delivery slices + +| # | Slice | Depends on | +| --- | ----------------------------------------------------------------------------------------- | ---------- | +| 1 | Content model, with the coverage test over warning classes | — | +| 2 | Authored explanations for the hard legality classes — colour identity, singleton, banlist | 1 | +| 3 | In-place reveal from the warning, non-blocking | 2 | +| 4 | Rule citations with the rules version | 2 | +| 5 | Bracket and Game Changers explanations | 3 | +| 6 | French review and locale gating | 2 | + +Slice 1 is deliberately first: a coverage test that fails when a new warning class ships without an explanation is what keeps this initiative from decaying into half-written help text. + +## Open questions + +- Who writes them? This is content work with a refresh cadence, and content without an owner dates — `design-system.md` is the cautionary example already in this repository. If nobody owns it, do not start it. +- Does the comprehensive rules version need to be surfaced to the player, or only recorded? Recording it is the minimum; surfacing it may be noise for the beginner this initiative is for. +- Is there an audience overlap with I-15's Rule 0 sheets? A player learning what "extra turns" means and a pod declaring it are the same vocabulary, and sharing the content would keep one definition rather than two.