/ v0.1-plan.org
v0.1-plan.org
  1  #+title: WhoWroteThis v0.1 — Plan
  2  #+author: Xavier Brinon
  3  #+date: [2026-04-17 Fri]
  4  #+startup: indent
  5  #+options: ^:{} toc:nil num:nil
  6  #+description: Synthesis of the 2026-04-17 grilling session: v0.1 scope, decisions, and action order. Source of truth for the MVP build.
  7  
  8  * Context
  9  Output of a grill-me session on 2026-04-17 that resolved 15 decisions
 10  about the v0.1 build. The public product name is /WhoWroteThis/; the
 11  repo stays =WriterAIScore=. /Blaze Check/ (see
 12  [[file:local-extension-idea.org][local-extension-idea.org]]) is a
 13  deliberately retained *rhetorical foil*, not a product — it exists to
 14  sharpen the neutrality rule by contrast.
 15  
 16  See:
 17  - [[file:README.md][README.md]] — product overview
 18  - [[file:UBIQUITOUS_LANGUAGE.md][UBIQUITOUS_LANGUAGE.md]] — canonical glossary
 19  - [[file:GUARDRAILS.md][GUARDRAILS.md]] — *currently stale*, titled for Blaze Check; rewrite is Step 1
 20  
 21  * v0.1 Scope Summary
 22  ** Product
 23  - Public name :: WhoWroteThis
 24  - Repo :: WriterAIScore (unchanged)
 25  - License :: GPLv3
 26  - Stance :: neutral — show numbers, never labels
 27  
 28  ** Surface and Data Flow
 29  - Trigger surface :: Amazon /dp/ product page only
 30  - Data source :: Amazon /author/ page, reached via author ID from byline
 31  - Fetch strategy :: eager, gated on tab visibility, 7-day cache, per-tab rate cap
 32  - Disambiguation :: Amazon author ID (canonical; no Google Books dependency)
 33  - Counting unit :: Amazon's parent-ASIN grouping
 34  - Date source :: Amazon's displayed publication date (JSON-LD / microdata preferred, localized-text fallback)
 35  - Numbers shown :: rolling 12-month count AND calendar-year count
 36  - Baseline / threshold / colour :: *none*
 37  
 38  ** Info Card
 39  Copy (stat-block format), composed through =chrome.i18n=:
 40  
 41  #+begin_example
 42  Publication velocity (per Amazon)
 43  Last 12 months: <N>
 44  <YYYY>: <M>
 45  See full catalog →
 46  #+end_example
 47  
 48  - Failure state, transient :: retry button
 49  - Failure state, permanent :: silent (no card)
 50  - Never :: asserts a wrong number, applies colour, or labels anyone
 51  
 52  ** Locales
 53  - 13 Amazon domains :: =.com=, =.co.uk=, =.ca=, =.com.au=, =.fr=, =.de=,
 54    =.it=, =.es=, =.nl=, =.co.jp=, =.in=, =.com.br=, =.com.mx=
 55  - UI language :: =chrome.i18n= reads browser language; 9 =_locales/=
 56    JSON files (en, fr, de, es, it, nl, ja, hi, pt_BR); fallback to en
 57  
 58  ** Stack
 59  - Language :: TypeScript strict
 60  - Framework :: WXT
 61  - Testing :: Vitest parser tests + Playwright E2E against fixtures (PR
 62    gate); daily live-canary job auto-opening GH issues on failure;
 63    monthly =pnpm refresh-fixtures=; weekly personal canary on
 64    daily-driver locales; "Report a broken page" link in popup
 65  - Telemetry :: =Telemetry= interface + =consoleTelemetry= concrete;
 66    =telemetry.enabled= hardcoded =false=; five events: =parser_ok=,
 67    =parser_failed=, =card_rendered=, =retry_clicked=, =fetch_duration=
 68  
 69  ** Launch
 70  - Chrome Web Store :: day D (unlisted beta first)
 71  - Firefox AMO :: day D+7 (after Chrome build stable for a week)
 72  - Edge :: not submitted — Edge users install from the Chrome Web Store
 73  - Monetization :: none; grant applications (Knight, Mozilla MIECO,
 74    Omidyar) pursued in parallel
 75  - Privacy policy :: GitHub Pages, linked from popup and from CWS listing
 76  - Launch model :: 2-week unlisted beta → public; target ≥10 engaged beta testers
 77  
 78  * Explicitly Deferred — Not in v0.1
 79  - /author/ page rendering + graph view → v0.2
 80  - Search results surface → v0.3
 81  - Backend / multi-source enrichment (Wikipedia, Goodreads, server-hosted user reports) → v0.4
 82  - PostHog telemetry concrete → v0.2+ with explicit first-run consent, default OFF
 83  - Firefox release → v0.1.1 at D+7
 84  - Safari → v0.6 per original roadmap
 85  - Baseline / genre / percentile / threshold / colour coding :: possibly never; revisit after usage
 86  - Settings page → v0.2+
 87  - "i" explainer tooltip → later version
 88  - Per-year sparkline on /dp/ Info Card → v0.2 (belongs on /author/)
 89  - Reissue-edition special handling → later
 90  
 91  * Action Order
 92  
 93  Urgent-first. Each step is small and independently committable.
 94  
 95  ** 1. Rewrite GUARDRAILS.md
 96  - Currently titled /# Project Guardrails: Blaze Check/ — stale, enforced by active hooks
 97  - Rewrite for WhoWroteThis / WriterAIScore
 98  - Align Ethical Labeling section with the neutrality rule (no labels, only numbers)
 99  - Add: user-visible strings must go through =chrome.i18n=
100  - Add: the Adapter boundary must never throw; returns =AuthorCatalog | null=
101  
102  ** 2. ADR 0001 — Neutral-vs-Accusatory Framing
103  - Captures the keystone decision
104  - Records /Blaze Check/ as the archived rejected alternative
105  - Cites [[file:local-extension-idea.org][local-extension-idea.org]] so
106    the foil's contribution to the rule is preserved
107  
108  ** 3. README.md + UBIQUITOUS_LANGUAGE.md cleanup
109  - README :: drop /"Velocity vs. Baseline"/ phrasing; add the
110    WhoWroteThis public name; resolve the name-vs-scope caveat; update
111    the Info Card description
112  - UBIQUITOUS_LANGUAGE :: resolve the rename caveat; move =Baseline=
113    out of the v0.1 row of the Versioned Scope table; optionally note
114    that Burst falls out of the 12-month-vs-calendar-year divergence
115    rather than being a separate v0.2 feature
116  
117  ** 4. ADR 0002 — Tech Stack
118  - WXT, TypeScript strict, GPLv3
119  - Client-side only (no backend in v0.1)
120  - =chrome.i18n= browser-language-driven
121  - Rationale: defer complexity, architect for pluggability (Adapter, Telemetry, Baseline)
122  
123  ** 5. LICENSE + Privacy Policy draft
124  - =LICENSE= :: full GPLv3 text at repo root
125  - =docs/privacy.md= :: short, honest — stored data, 7-day TTL, no
126    exfiltration, opt-in consent dialog in future version
127  
128  ** 6. Vanilla WebExtension Scaffold
129  #+begin_quote
130  *Revised 2026-04-17:* the original plan (below) specified WXT +
131  TypeScript strict. [[file:docs/decisions/0003-vanilla-webextensions.md][ADR 0003]] reversed that on a learning-value
132  driver. The authoritative spec for Step 6 is now
133  [[file:docs/prds/0001-vanilla-scaffold.org][PRD 0001 — Vanilla WebExtension Scaffold]]. The summary below is
134  retained for historical continuity but is superseded by the PRD.
135  #+end_quote
136  
137  Superseded summary (see PRD 0001 for the active spec):
138  - Vanilla MV3 =manifest.json= (hand-written, ≤60 lines, Chrome + Firefox compatible)
139  - =content-scripts/dp.js= (plain JS, single =console.log= line)
140  - =host_permissions= :: the 13 Amazon domains
141  - =chrome.i18n= scaffolding :: =_locales/en/messages.json= at repo root
142  - =jsconfig.json= with =checkJs: true= for JSDoc type-checking
143  - =web-ext= CLI (Mozilla first-party) for =dev=, =build=, =lint=
144  - No build framework, no TypeScript emit, no bundler
145  
146  ** 7. First Adapter milestone — author ID extraction
147  - =amazon/AmazonAdapter.ts= implements =Adapter=
148  - Input :: DOM of an Amazon /dp/ page
149  - Output :: Amazon author ID string, or =null= if no linked byline
150  - Fixture :: at least one =.com= product page HTML at =tests/fixtures/amazon-com-dp-<asin>-2026-04.html=
151  - Vitest test asserts the expected author ID is extracted
152  
153  ** 8. Second Adapter milestone — /author/ catalog parse
154  - Extend =AmazonAdapter= with =fetchAndParseCatalog(authorId)=
155  - Returns =AuthorCatalog | null= with =[{ parentAsin, title, publishedAt }]=
156  - Fetch via =fetch(authorUrl)= from content script
157  - Fixture :: one =.com= /author/ page HTML; Vitest asserts book count
158    matches hand-counted truth (the integrity test)
159  
160  ** 9. Counting + Info Card render
161  - =Counter= pure function :: takes =AuthorCatalog=, returns ={ rolling12mo, calendarYear }=
162  - =InfoCard= component renders the stat block adjacent to byline
163  - Failure state :: retry button; on retry, calls =fetchAndParseCatalog= again
164  
165  ** 10. Primary-locale fan-out
166  - =.co.uk=, =.fr=, =.de= via =LocaleConfig= entries against the single =AmazonAdapter=
167  - Fixtures for each
168  - =chrome.i18n= =_locales/= for fr, de
169  
170  ** 11. Remaining locales
171  - =.ca=, =.com.au=, =.it=, =.es=, =.nl=, =.co.jp=, =.in=, =.com.br=,
172    =.com.mx= =LocaleConfig= entries
173  - Fixtures optional per locale; smoke test via manual canary
174  
175  ** 12. Telemetry seam + Playwright E2E
176  - =Telemetry= interface, =consoleTelemetry= concrete
177  - Wire the five events at their call sites
178  - Playwright E2E :: renders the content script against fixture HTML;
179    asserts Info Card DOM and text
180  
181  ** 13. Live canary + report-broken link
182  - GitHub Actions workflow :: daily scheduled Playwright against a
183    hand-picked list of real Amazon URLs; opens an issue on failure with URL + locale
184  - Browser-action popup :: single "Report a broken page →" link
185    pre-filling a GH issue
186  
187  ** 14. Store prep
188  - Icon + screenshots
189  - Chrome Web Store listing copy (en)
190  - Privacy policy published at GitHub Pages
191  - Developer account ($5)
192  - Publish unlisted
193  
194  ** 15. Beta
195  - Recruit ≥10 beta testers (American Scholar readership,
196    trust-and-safety researchers, Mastodon/Bluesky networks)
197  - 2-week window
198  - Triage every report-broken and every dogfood failure
199  - Flip to public when no open criticals remain
200  
201  * Invariants
202  These must not drift during implementation:
203  
204  - Neutrality :: the Info Card never labels, never colours, never
205    thresholds
206  - Silence :: the Adapter never throws; the Info Card either shows the
207    correct number, a retry affordance, or nothing — never a wrong number
208  - Attribution :: /"per Amazon"/ (or its localized equivalent) always
209    appears in the Info Card copy
210  - Privacy :: no data leaves the browser in v0.1; telemetry is a
211    code-present seam with a =false= flag, nothing more
212  - Ubiquitous language :: code identifiers and user-visible copy use
213    the canonical terms from UBIQUITOUS_LANGUAGE.md (post-cleanup)
214  - Architecture :: one Adapter interface, concretes added only when a
215    new surface (marketplace or data source) is actually shipped
216  
217  * Open questions for later versions
218  Parked, not forgotten:
219  
220  - v0.4 backend :: breaks the /no-data-leaves-the-browser/ rule;
221    requires explicit consent dialog, careful scope (engineering
222    telemetry only, no user-behavior tracking)
223  - Monetization at v0.4 :: client-side is free to run forever; backend
224    costs money; revisit when runtime costs exceed grant + personal
225    funding
226  - Name durability :: /WhoWroteThis/ is locked for v0.1; reconsider if
227    someone trademarks something similar or if the question-form proves
228    awkward in practice
229  - Cross-marketplace :: Goodreads, Barnes & Noble, Apple Books, Kobo
230    appear in UBIQUITOUS_LANGUAGE.md as valid Marketplaces but are not
231    in the v0.1–v0.4 roadmap above
232  
233  * Session provenance
234  This plan is the synthesis of a 15-question grill-me session on
235  2026-04-17. The decision tree walked each branch with a recommendation;
236  where the recommendation was accepted, it's reflected above. Memory
237  files at
238  =~/.claude/projects/-Users-xavierbrinon-Documents-Projects-WriterAIScore/memory/=
239  preserve the core decisions and the "architect-for-pluggability,
240  defer-complexity" pattern for future sessions.