#!/usr/bin/env python3
"""The hand-coded dataset of design corrections (source of data/corrections.csv).

One row = one design correction: the owner rejecting one kind of pattern in
work an AI agent produced (or telling the agent in advance to avoid it), in one
project, on one date. A message that rejects three different kinds of pattern
yields three rows. A correction recorded in several places (his message, a
memory note written from it, the commit that reverted it) is ONE row whose
`source` lists every place.

Coding was done by an AI assistant (Claude) from the owner's own records; see
the README codebook. Pattern and replacement fields are paraphrases. `quote`
holds his own words only where the paper quotes them (short, no names).

Evidence ids:
  Tnnnn  a message in data/messages_index.csv (text not published)
  mem:x  memory note x.md (the owner's agent memory, not published; a note
         whose file name contains a person's name is shown as an alias)
  c:h    a commit hash in the named repository
  doc:p  a design document path in the named repository
"""
import csv, json, os

HERE = os.path.dirname(os.path.abspath(__file__))
DATA = os.path.join(HERE, "..", "data")

# Tell taxonomy (section 5.1 of the paper)
TELLS = {
    "COL": "Default colour (purple/AI-blue, neon, gradients, warm paper, grey dark, off accents)",
    "GLO": "Decorative effects (glow, glass, blur, sheen, shading, textures)",
    "TYP": "Generic or robotic type (stock sans, mono and tracked labels, tabular digits, thin or stretched)",
    "ICO": "Generic icons (stock sets, emoji as icons, arrows for everything)",
    "IDN": "Generic marks and identity (typed logos, crude or borrowed marks)",
    "DOT": "Status dots, pills, badges and indicators",
    "SRF": "Surface defaults (loud or nested outlines, inconsistent shapes, flat boxes, see-through bars)",
    "TPL": "Template composition (same section pattern, card for everything, stat dashboards, wasted space)",
    "CLU": "Clutter, over-explaining and copy tells",
    "MOT": "Generic or decorative motion (fade/roll-in jank, grow entrances, loops, ambient drift)",
    "DED": "Dead or under-designed (restraint tipped into dull, plain, lifeless)",
    "NAV": "Duplicate or misplaced entry points (two doors, two bars, stray buttons)",
    "CMP": "Stock components (default nav bar, numpad, spinner, dropdown, snackbar, app icon)",
    "GIM": "Gimmicks (effect catalogues, customisation sprawl, interactive demo widgets)",
    "GEN": "Unspecified 'AI feel' (a general instruction with no named pattern)",
}
EXCESS = {"COL", "GLO", "DOT", "MOT", "GIM", "SRF"}      # the 'too much' pole
BLAND = {"TYP", "ICO", "IDN", "TPL", "DED", "CMP"}       # the 'too safe' pole
# CLU, NAV, GEN are neither pole.

STRATS = {
    "BEN": "Benchmark against named products",
    "REF": "Own reference component or project as the grammar",
    "BAN": "Name the banned patterns",
    "RES": "Research mandate",
    "PRO": "Rendered options or a prototype before building",
    "SHOT": "Screenshot or device review",
    "RESET": "Full visual reset",
    "AUD": "Audit inherited agent work",
}

ROWS = []
def R(date, project, source, ev, tell, pattern, replacement, strat="", owner_req=0, quote=""):
    ROWS.append(dict(date=date, project=project, source=source, evidence=ev, tell=tell,
                     pattern=pattern, replacement=replacement, strategies=strat,
                     owner_requested=owner_req, quote=quote))

T, M, C, D = "transcript", "memory", "commit", "doc"

# ---------------- Bupples (group bill splitting; Flutter) ----------------
P = "bupples"
R("2026-06-13", P, T, "T0001", "CMP", "Stock navigation bar and its icons", "Redesigned navigation system")
R("2026-06-13", P, T, "T0002", "IDN", "App logo", "Completely new mark", "BEN")
R("2026-06-13", P, T + "+" + C, "T0006;c:28be05fe;c:204915eb", "SRF", "High-contrast outlines in dark mode, read as AI slop", "Soften outlines; replace everything on community AI-slop lists", "RES;BAN", quote="it feels like ai slop")
R("2026-06-13", P, T, "T0006", "CMP", "Navigation bar system", "A different bar and system")
R("2026-06-13", P, T, "T0007", "GEN", "Navigation and home 'AI slop'", "Research award-winning designs and apply", "BEN;RES")
R("2026-06-13", P, T, "T0008", "IDN", "Logo that could read as AI slop", "Researched logo direction", "RES")
R("2026-06-14", P, T, "T0012", "SRF", "Elements with mismatched shapes", "One shape language", "SHOT")
R("2026-06-14", P, T, "T0012", "TPL", "Very wide receipt panel showing little (empty space)", "Size the panel to its content", "SHOT")
R("2026-06-14", P, T + "+" + C, "T0012;c:9bc60f7b", "CMP", "Generic loading spinners ('dull')", "Custom mascot loaders, consistent everywhere")
R("2026-06-14", P, T, "T0021", "CLU", "Create, add-expense and settle layouts cluttered and unclear", "Reworked layouts")
R("2026-06-15", P, T, "T0022", "DED", "Landing page 'pretty basic'", "Researched money-app landing page", "RES;BEN")
R("2026-06-17", P, T, "T0025", "CMP", "Default Flutter web app icon", "Mascot mark as the icon")
R("2026-06-28", P, T + "+" + C, "T0059;c:e34d711c;c:01c88429", "GLO", "Glow effects", "Glow removed")
R("2026-06-28", P, T + "+" + C, "T0059;c:e34d711c", "COL", "Default theme and grey AMOLED", "Dark default, true-black AMOLED")
R("2026-06-28", P, T, "T0059", "CLU", "Too much text across the UI", "Shorter copy")
R("2026-06-28", P, T, "T0059", "GLO", "Noticeable blur behind names on bubbles", "Blur removed")
R("2026-06-29", P, T, "T0070", "CMP", "Stock numeric keypad", "Keypad removed", quote="remove the stupid numpad")
R("2026-06-29", P, T, "T0071", "CLU", "Too much text; truncated copy", "Rewrite copy shorter, never ellipsise our own copy")
R("2026-06-29", P, T, "T0072;T0074", "SRF", "White outline and tint on bubbles", "Thin outline in the avatar's colour, no tint")
R("2026-06-30", P, T + "+" + C + "+" + M, "T0072;c:df1087b6;c:5c705a81;c:32f5c7a1;c:0de00462;c:682bf7c7;mem:feedback-bubble-no-entrance", "MOT", "Scale-from-zero grow entrance on bubbles (stranded no-photo bubbles small)", "Full size from frame one; motion comes from the physics drift only", "SHOT", owner_req=1)
R("2026-06-29", P, T, "T0074", "ICO", "Generic icon beside the wordmark", "Removed")
R("2026-06-29", P, T + "+" + C, "T0076;c:aef8951f", "MOT", "Add-expense entrance animation", "A sheet entrance unique to the screen")
R("2026-06-29", P, T + "+" + C, "T0076;c:aef8951f;c:b9cfba06", "CMP", "Default underlines on text (debug yellow) in sheets and splash", "Underlines removed")
R("2026-07-01", P, T, "T0092", "MOT", "Enlarge/shrink animation on QR codes ('wacky')", "Screen simply appears smoothly")
R("2026-07-02", P, T + "+" + C + "+" + D, "T0094;c:ba5dfe21;c:62efd9ba;c:bb3d4fb4;doc:DESIGN.md", "GEN", "AI-slop tells across the app (playbook)", "Anti-slop contract: tokens, one icon voice, forbidden list", "RES;BAN")
R("2026-07-02", P, T + "+" + C, "T0096;c:62efd9ba", "DED", "Mascot chat box 'looks basic'", "Custom chat surface")
R("2026-07-03", P, T, "T0100", "DED", "Basic, unanimated avatar frames", "Animated frames from the mock-up")
R("2026-07-03", P, T, "T0102", "GLO", "Neon, aurora, glow, chrome, crystal and frosted-glass effect themes", "Those effects removed")
R("2026-07-03", P, T, "T0102", "GIM", "Catalogue of novelty premium effects", "Catalogue cut")
R("2026-07-06", P, T, "T0116", "CLU", "Home screen 'super cluttered'", "Friends section removed from home")
R("2026-07-06", P, T, "T0117", "DED", "Pro showcase screen 'dead and dull'", "Reworked showcase")
R("2026-07-07", P, T, "T0119", "CLU", "Helper sentence 'add the first expense to get started'", "Removed; small dismissible hint")
R("2026-07-07", P, T, "T0124", "ICO", "Custom icon set that looked bad", "Custom icons cancelled for now")
R("2026-07-07", P, T, "T0129", "SRF", "Text boxes with two nested outlines", "One edge per surface", "SHOT")
R("2026-07-08", P, T, "T0131", "MOT", "Janky opening animations for sheets and pages", "New opening animation")
R("2026-07-08", P, T, "T0139", "MOT", "Pages roll in text first, background after", "Window first, then content", "")
R("2026-07-08", P, T + "+" + C, "T0143;c:fcfbf834", "MOT", "Same page animation still wrong", "Transform-only push, no fade")
R("2026-07-08", P, T, "T0136", "TPL", "Owed-to-you box styled like the session cards", "A distinct component")
R("2026-07-08", P, T, "T0144", "MOT", "Looping, clipped animation on the upgrade button", "Calm one-shot")
R("2026-07-08", P, T, "T0149", "CLU", "Balance explanation page cluttered", "Reorganised page")
R("2026-07-13", P, T, "T0171", "GIM", "Alternate app icons", "Dropped")
R("2026-07-14", P, T, "T0176", "GIM", "Box grid behind the splash animation", "Plain splash background")
R("2026-07-14", P, T, "T0187", "GIM", "Avatar-ring and profile-cover appearance options", "Options removed")
R("2026-07-18", P, T + "+" + M, "T0208;mem:project-bupples-ui-batch-2026-07-18", "TYP", "Monospace balance digits ('robotic')", "Rounded sans digits as default", quote="the current net balance font is a bit robotic")
R("2026-07-18", P, T, "T0221", "TPL", "Member card with dead space", "Tighter card layout")
R("2026-07-21", P, T, "T0238", "GLO", "Dot texture on solid backgrounds", "Texture removed", "SHOT")
R("2026-07-21", P, T, "T0240", "DED", "Empty home 'super dead'", "Empty state that invites the first action")
R("2026-07-21", P, T, "T0241", "TPL", "Compact card design 'super awkward'", "Card reworked", "SHOT")
R("2026-07-21", P, T, "T0242", "TYP", "Splash wordmark in an outside font", "Wordmark in the app's own face")
R("2026-07-26", P, T, "T0254;T0255", "GLO", "Blur bar on the cover banner", "Removed")
R("2026-07-26", P, T, "T0254", "MOT", "New receipt-scan animation out of place", "Previous animation restored")
R("2026-07-26", P, T, "T0256", "GLO", "Shade filter over profile photos", "Filter removed")
R("2026-07-26", P, T, "T0257", "CLU", "Personal-spending screen throws everything at once", "Sections, calmer framing")
R("2026-07-26", P, M + "+" + D, "mem:project-bupples-soft-ui-receipt-motion-program;doc:DESIGN.md", "TYP", "Large serif headline voice ('hard, robotic, serif-heavy')", "One soft sans for headings and body")
R("2026-07-28", P, T, "T0269", "COL", "Quick-action area colour out of place", "Recoloured")
R("2026-07-28", P, T, "T0269", "CLU", "Long, cluttered subscription screen", "Shorter researched paywall")
R("2026-08-02", P, T, "T0282;T0284", "CLU", "Settle-up flow cluttered and stressful", "Simple step flow")
R("2026-08-03", P, T, "T0298", "GIM", "Forty-odd themed avatar frames", "Frames removed")
R("2026-10-19", P, T + "+" + M, "T0435;mem:feedback-bupples-marketing-captures", "COL", "Promo screenshots mixing themes and colours", "One theme (OLED black), fresh captures")
R("2026-11-01", P, T + "+" + M, "T0520;mem:project-bupples-full-design-rework-2026-11", "GEN", "App feels assembled, not designed", "Full rework drawing on his other projects", "REF;RESET")
R("2026-11-01", P, T + "+" + M, "T0521;mem:project-bupples-full-design-rework-2026-11", "GLO", "App-wide Liquid Glass mode", "Mode removed entirely", owner_req=1, quote="remove the liquid glass mode it sucks so bad")
R("2026-11-01", P, T, "T0522", "TPL", "Features 'built separately and put together'", "Information-architecture rework")
R("2026-11-01", P, T + "+" + M, "T0527;mem:project-bupples-full-design-rework-2026-11", "COL", "Blue in the prototype", "No blue anywhere", "PRO")
R("2026-11-01", P, T, "T0531", "DOT", "Dots around the mascot; mascot repeated everywhere", "Mascot once, top-left; other sections get their own visuals", "PRO")
R("2026-11-01", P, T, "T0531", "ICO", "Icons too heavy", "Simpler, softer icons", "PRO")
R("2026-11-01", P, T + "+" + M, "T0533;mem:project-bupples-full-design-rework-2026-11", "GIM", "Colour, font and theme customisation", "No app customisation")
R("2026-11-01", P, T, "T0532", "GEN", "Generic profile appearance", "Profile 'passport' redesign", "PRO")

# ---------------- Adelante (quotes and widgets; Flutter) ----------------
P = "adelante"
R("2026-06-21", P, T, "T0040", "DED", "Flat and plain screens", "Depth and material")
R("2026-06-21", P, T + "+" + C, "T0040;c:1c3343b", "GLO", "Glow when tapping a navigation icon", "Ink-ripple glow removed; subtle scale")
R("2026-06-21", P, T + "+" + C, "T0043;c:6bc4715", "GLO", "Fake one-spot reflection sheen; shine on buttons", "Flat soft panels; gradient and glow shine dropped", quote="it just looks ugly")
R("2026-07-18", P, M, "mem:project-adelante-overhaul", "MOT", "Plain cross-fade between tabs (ghosting)", "Sequenced fade-through")
R("2026-07-18", P, T, "T0207", "COL", "Nav highlight and background colour 'a lot of apps did it'", "Adjusted to the theme")
R("2026-09-30", P, T, "T0301", "GEN", "Generic, dull, no identity", "New black-and-white identity", "RESET")
R("2026-09-30", P, M, "mem:project-adelante-completion-2026-10-01", "COL", "Agent's ember accent idea", "Monochrome is the brand")
R("2026-09-30", P, M, "mem:project-adelante-completion-2026-10-01", "GLO", "Strong glow", "Restrained glow only")
R("2026-11-01", P, T, "T0525", "CLU", "Home page cluttered", "One loud thing plus one action row")
R("2026-11-01", P, T + "+" + M, "T0525;mem:project-adelante-design-rework-2026-11-01", "TYP", "Display and UI faces he disliked", "One face for everything, picked from a rendered specimen", "PRO")
R("2026-11-01", P, T, "T0525", "MOT", "Stock splash", "Custom mark-drawing splash")
R("2026-11-01", P, M + "+" + D, "mem:project-adelante-design-rework-2026-11-01;doc:docs/design/2026-11-01-design-rework.md", "GLO", "Frosted cards ('cringe looking AI frost')", "Solid tonal plates; frost only on nav and sheets", quote="don't make it cringe looking AI frost")
R("2026-11-01", P, M + "+" + D, "mem:project-adelante-design-rework-2026-11-01;doc:docs/design/2026-11-01-design-rework.md", "MOT", "Fade on everything", "Fade removed; doctrine motion tokens")

# ---------------- OnPlan (hangout planning; Flutter) ----------------
P = "onplan"
R("2026-06-21", P, T, "T0044", "COL", "Accent colour", "New accent")
R("2026-06-22", P, T, "T0045", "COL", "App colours", "New palette")
R("2026-06-22", P, T, "T0045", "TPL", "Home showing only a centred nav bar", "Real home screen")
R("2026-07-18", P, T, "T0203", "COL", "Colours that read as AI slop", "Better palette")
R("2026-07-18", P, T, "T0209", "CMP", "Old, odd navigation bar centred on screen", "New navigation")
R("2026-07-18", P, T, "T0214", "GEN", "Whole UI and navigation bad", "Full redesign", "RESET")
R("2026-07-18", P, T + "+" + M, "T0215;mem:project-onplan-redesign", "COL", "Purple and other 'known AI slop colors'", "Teal from the logo, gold accent; purple banned", "BAN;PRO", quote="without the purple and other known ai slop colors")
R("2026-07-18", P, T, "T0218", "ICO", "Emoji used as icons", "Icons, never emoji")
R("2026-07-18", P, T, "T0218", "DED", "Generic-looking, few animations", "Motion toolkit, more premium")
R("2026-07-18", P, T + "+" + M, "T0219;mem:project-onplan-redesign", "COL", "Palette again (coral)", "Logo colour as the identity", "REF")
R("2026-07-18", P, T, "T0220", "CLU", "Crowded screens", "Uncluttered layout with hints")
R("2026-07-18", P, T, "T0222", "ICO", "Generic icons", "Better icon set", "REF")
R("2026-07-18", P, T, "T0222", "CMP", "Custom nav instead of the native tab bar", "Native iOS tab bar", "REF")
R("2026-07-18", P, T + "+" + M, "T0222;mem:project-onplan-redesign", "DED", "App feels 'meh' and dead", "Adelante as the taste reference", "REF")

# ---------------- Portfolio (yousofselim.com) ----------------
P = "portfolio"
R("2026-07-17", P, T, "T0198", "TPL", "Project slideshow on mobile", "Links on the outer view on mobile")
R("2026-07-29", P, T, "T0272", "TPL", "Sections with empty spots that look basic", "Every section designed for what it shows")
R("2026-07-29", P, T, "T0272", "CLU", "Too much text", "Fewer words, supporting icons")
R("2026-07-29", P, T, "T0276", "GIM", "Dot-mosaic figure with empty dot spaces", "Figure reworked")
R("2026-08-30", P, C, "c:464dddb", "TYP", "Monospace date ranges", "Cleaner text style")
R("2026-10-06", P, T, "T0314", "GEN", "Site that 'seems AI vibe coded'", "Higher-quality, unique design")
R("2026-10-06", P, T, "T0315", "CLU", "Project presentation cluttered", "Cleaner project presentation")
R("2026-10-06", P, T, "T0318", "GEN", "AI-coded feeling", "Researched, modern, rounded, frosted", "PRO;RES")
R("2026-10-07", P, T, "T0325", "SRF", "Cards blending into the background; colours switching", "Separated surfaces and tokens")
R("2026-10-07", P, T, "T0326", "DOT", "Dots beside section headers ('ai coded elements')", "Plain headings")
R("2026-10-07", P, T, "T0326", "CLU", "Too much text and over-explaining; extra name lines", "Cut")
R("2026-10-07", P, T, "T0327", "CLU", "Still too much text", "Cut further")
R("2026-10-07", P, T, "T0328", "TYP", "Overall font", "New font")
R("2026-10-07", P, T, "T0330", "TYP", "Robotic monospace for small details", "Text face for details", quote="i don't like the robotic font")
R("2026-10-07", P, T, "T0332", "DOT", "Location dot", "Presented without a dot")
R("2026-10-08", P, T + "+" + M, "T0334;mem:feedback-portfolio-nav-is-the-benchmark", "GEN", "Uneven care across the page", "The nav pill's grammar everywhere", "REF;AUD", quote="i want that same level of design and care")
R("2026-10-08", P, T + "+" + M, "T0335;mem:feedback-portfolio-nav-is-the-benchmark", "GEN", "AI basic or generic elements", "Named tells refused (lift and glow, zoom, pulsing, fade-ins, purple)", "BAN;RES")
R("2026-10-08", P, T + "+" + M, "T0338;mem:project-portfolio-rebuild-2026-10-07", "MOT", "Envelope doodle and send animation in empty space", "Removed")
R("2026-10-13", P, T, "T0374", "GEN", "Generic and AI stuff", "Identity pass")
R("2026-10-14", P, T, "T0377", "CLU", "Too much text", "Less text")
R("2026-10-14", P, T, "T0377", "DED", "Projects without backgrounds or objects", "Product plates")
R("2026-10-14", P, T + "+" + M, "T0378;mem:project-portfolio-identity-pass-2026-10-14", "ICO", "Arrow glyphs on store and other buttons", "Real store marks and leading icons; no arrows")
R("2026-10-14", P, T + "+" + M, "T0382;mem:project-portfolio-identity-pass-2026-10-14", "COL", "Warm white canvas", "Neutral soft white, not blinding", quote="i don't want my portfolio to be warm white at all")
R("2026-10-14", P, M, "mem:project-portfolio-identity-pass-2026-10-14", "DOT", "Dot-grid tool map", "Tool groups with project icons")
R("2026-10-14", P, C + "+" + M, "c:dc85e4f;mem:project-portfolio-identity-pass-2026-10-14", "NAV", "Skip links appearing as extra visible controls", "Skip links removed")

# ---------------- Tajweed (front end; shared repository) ----------------
P = "tajweed"
R("2026-10-13", P, T, "T0345", "IDN", "Wordmark", "Redrawn wordmark")
R("2026-10-13", P, T, "T0346", "COL", "Purple and blue 'in a generic way'", "Owned purple and blue")
R("2026-10-13", P, T, "T0347", "COL", "Warm paper background", "Cool white", quote="it feels generic and dull and basic and not alive")
R("2026-10-13", P, T, "T0350", "TYP", "Basic fonts", "New type", "BEN")
R("2026-10-13", P, T, "T0350", "DED", "No Duolingo-grade polish", "Duolingo-grade rework", "BEN")
R("2026-10-13", P, T, "T0357", "CLU", "Cluttered and messy screen", "Cleaned up", "SHOT")
R("2026-10-13", P, T, "T0365", "CLU", "Progress section cluttered, calendar expanded", "Collapsed calendar")
R("2026-10-13", P, M, "mem:project-tajweed-duolingo-grade-redesign", "MOT", "Mascot fading and flashing on every state change (another agent's work)", "Mascot never fades", "AUD")
R("2026-10-13", P, M, "mem:project-tajweed-duolingo-grade-redesign", "TYP", "Forced lowercase headings (another agent's work)", "Capitalised headings", "AUD")
R("2026-10-13", P, C, "c:c4364a4", "ICO", "Stock icon font mixed with others", "One icon component")

# ---------------- Spell Quest (timed kids' game) ----------------
P = "spellquest"
R("2026-10-15", P, T, "T0406", "IDN", "Mascot that copied another product's", "Distinct mascot", "REF")
R("2026-10-15", P, T, "T0406", "DED", "Feedback and interaction 'sooooo basic'", "Richer quest path and feedback")
R("2026-10-15", P, T, "T0407", "ICO", "Emoji as icons", "Custom drawings", "BAN")
R("2026-10-15", P, T, "T0407", "CLU", "Em dashes and other AI copy signs", "Removed", "BAN")
R("2026-10-15", P, T, "T0409", "DED", "Character animations feel dead", "Livelier reactions")

# ---------------- Himalaya concept (store) ----------------
P = "himalaya"
R("2026-10-14", P, T + "+" + M, "T0396;mem:feedback-store-must-feel-alive", "ICO", "Generic thin icons", "Fewer, filled or brand-tinted icons", "BEN")
R("2026-10-14", P, T + "+" + M, "T0396;mem:feedback-store-must-feel-alive", "DED", "Calm label-style store that 'feels dead', wasted spacing", "Dense, merchandised, colour from products", "BEN", quote="doesn't feel like how shopee or amazon look or act")
R("2026-10-14", P, T, "T0396", "TYP", "Generic, basic fonts", "Type with personality")
R("2026-10-14", P, T, "T0398", "DED", "Photos, cards and offers dull", "Imagery used properly")
R("2026-10-15", P, T, "T0401", "TYP", "Bold display font 'used alot by ai'", "Different display treatment")

# ---------------- Partner's portfolio (directed for his partner) ----------------
P = "partner-portfolio"
R("2026-10-14", P, T, "T0393", "NAV", "Side navigation tab", "Top navigation")
R("2026-10-14", P, T, "T0393", "TYP", "Font", "New font")
R("2026-10-14", P, T, "T0393", "COL", "Main colours", "New palette")
R("2026-10-14", P, T, "T0394", "CLU", "Text and description clutter", "Less text")
R("2026-10-15", P, M, "mem:feedback-partner-identity [aliased]", "DED", "Plain-type minimal banner ('generic and bad super bad')", "Authentic subject-matter signature, chosen from rendered options", "PRO")
R("2026-10-15", P, T, "T0400", "DED", "Style 'a bit too basic'", "More thematic vibe, not cringe")
R("2026-10-15", P, T + "+" + M, "T0410;mem:feedback-partner-identity [aliased]", "DOT", "Availability status dot", "Availability as a designed fact")
R("2026-10-15", P, M, "mem:feedback-partner-identity [aliased]", "SRF", "Rows of icons in boxes", "Removed")
R("2026-10-15", P, M, "mem:feedback-partner-identity [aliased]", "TYP", "Eyebrow labels everywhere", "Removed")
R("2026-10-15", P, M, "mem:feedback-partner-identity [aliased]", "TPL", "Stat tiles for their own sake", "Removed")
R("2026-10-15", P, M, "mem:feedback-partner-identity [aliased]", "COL", "Overpowering saturated colour blocks", "Small meaningful accents")
R("2026-10-15", P, T, "T0416", "TPL", "Repetitive section design", "Each section its own composition")
R("2026-10-15", P, T, "T0413", "TYP", "Generic fonts and elements", "Distinctive type")
R("2026-10-16", P, M, "mem:feedback-partner-identity [aliased]", "TYP", "Condensed stock sans for the name ('generic, ehh')", "Display face chosen from a rendered sheet", "PRO")
R("2026-10-16", P, M, "mem:feedback-partner-identity [aliased]", "COL", "Navy ground 'tooooo much'", "Near-neutral ink, colour as small accents", "PRO")
R("2026-10-16", P, M, "mem:feedback-partner-identity [aliased]", "CLU", "Explanatory legend line", "Removed", "SHOT")
R("2026-10-16", P, T, "T0418", "TYP", "Robotic monospace labels", "Display face labels", quote="I don't like the robotic font here since it is generic")
R("2026-10-16", P, T, "T0418", "SRF", "Flat boxes without depth", "Layered surfaces")
R("2026-10-16", P, T, "T0419", "ICO", "Arrows everywhere", "Icons; arrows only for back")
R("2026-10-16", P, T, "T0421", "CLU", "Opening page overwhelms", "Calmer first screen")
R("2026-10-16", P, T, "T0421", "SRF", "Double card effect on one section", "Same surface as the rest")

# ---------------- Experts Marine (client site) ----------------
P = "experts-marine"
R("2026-10-12", P, T, "T0340", "IDN", "Typed-out name instead of the logo", "Real logo")
R("2026-10-12", P, T, "T0340", "CLU", "Unnecessary text and film buttons; over-explaining", "Removed")
R("2026-10-12", P, T, "T0340", "ICO", "Icon pack", "Premium icon set")
R("2026-10-12", P, T, "T0340", "DED", "Sections dull, generic, boring scroll", "Reworked sections")
R("2026-10-12", P, T, "T0340", "TYP", "Font", "Adjusted font")

# ---------------- NutriGo (nutrition tracker; Flutter) ----------------
P = "nutrigo"
R("2026-09-30", P, T + "+" + M, "T0302;mem:feedback-nutrigo-ux-bar", "CMP", "Onboarding and popups not like a real onboarding", "One question per screen, plan-building moment", "BEN")
R("2026-10-01", P, T + "+" + M, "T0306;mem:feedback-nutrigo-ux-bar", "CMP", "Default dropdowns, menus and text boxes", "Redesigned controls", "BEN")
R("2026-10-01", P, T, "T0307", "SRF", "Buttons, headers and footers standing out awkwardly", "Quieter chrome")
R("2026-10-01", P, M, "mem:feedback-nutrigo-ux-bar", "ICO", "Generic icons", "Custom icon treatment")
R("2026-10-01", P, M, "mem:feedback-nutrigo-ux-bar", "CMP", "Snackbar that would not dismiss", "No stuck popups")
R("2026-10-02", P, M, "mem:project-nutrigo-three-designs-2026-10-02", "GEN", "Single looks judged 'too generic'", "Three distinct switchable designs", "PRO")

# ---------------- WayClub (group management; web + Flutter) ----------------
P = "wayclub"
R("2026-08-03", P, T + "+" + D, "T0288;doc:docs/ANTI_SLOP.md", "GEN", "UI that could be AI slop", "Pass/fail anti-slop manifesto with grep checks", "BAN;RES")
R("2026-08-03", P, T + "+" + M, "T0289;mem:feedback-wayclub-ux-bar", "CLU", "Cluttered information views", "Few things well, detail behind disclosure")
R("2026-08-03", P, T + "+" + M, "T0289;mem:feedback-wayclub-ux-bar", "DED", "Events without images (database rows)", "Posters, logos and avatars as product")
R("2026-10-17", P, T + "+" + M, "T0428;mem:feedback-wayclub-no-ai-feeling", "GEN", "The AI feeling", "Everything changes: mark, type, colour, shells, copy", "RESET;BAN", quote="make sure it doesn't have the ai feeling and everything is changed")
R("2026-10-17", P, M, "mem:feedback-wayclub-no-ai-feeling", "COL", "Violet-black dark panel", "New colour identity", "RESET")
R("2026-10-17", P, M, "mem:feedback-wayclub-no-ai-feeling", "TPL", "'Hello, name' dashboard with a stats row", "Product-specific home", "RESET")
R("2026-10-17", P, T + "+" + M, "T0429;mem:feedback-wayclub-type-and-white", "TYP", "Tracked uppercase monospace label; stock fonts", "Sentence-case labels in the text face; banned font list", "SHOT;BAN")
R("2026-10-17", P, T + "+" + M, "T0429;mem:feedback-wayclub-type-and-white", "COL", "Warm cream 'paper' backgrounds", "Neutral, faintly cool off-white", "BAN", quote="i want them white but not blinding white and i don't want warm white")
R("2026-10-17", P, T, "T0430", "DOT", "Any AI indicator", "None", "REF;RES")
R("2026-10-17", P, T + "+" + M, "T0431;mem:feedback-wayclub-no-ai-feeling", "CLU", "Clutter, too much text, over-explaining", "A name, a verb and a time")
R("2026-10-19", P, M, "mem:project-wayclub-refocus-2026-10-17", "IDN", "Pennant logo ('super bad', 'so off')", "Seven drawn directions; he chose one", "PRO")
R("2026-10-19", P, M, "mem:feedback-deep-dark-and-no-duplicate-entries", "COL", "Dark mode that reads as dark grey; washed icon plates", "Near-black canvas, deep plates")
R("2026-10-19", P, M, "mem:feedback-deep-dark-and-no-duplicate-entries", "NAV", "A You tab and an Account button for the same thing", "One home per concept")
R("2026-10-20", P, T + "+" + M, "T0442;mem:feedback-wayclub-energy-and-logo-motion", "DED", "Generic, not energised, dull compared with Luma", "Club colour used boldly, kinetic moments", "BEN;SHOT")
R("2026-10-20", P, T + "+" + M, "T0442;mem:feedback-wayclub-energy-and-logo-motion", "SRF", "Stacked hairlines that look awkward", "Dividers only between rows, never two lines", "SHOT")
R("2026-10-20", P, T + "+" + M, "T0442;mem:feedback-wayclub-energy-and-logo-motion", "MOT", "Motion rationed to three moments; spinners", "Custom logo loaders and many small exact animations", "BEN")
R("2026-10-20", P, T + "+" + M, "T0447;T0448;mem:feedback-wayclub-energy-and-logo-motion", "DOT", "Pause indicator on moving posters", "Motion that stops by itself, no control", "BEN", quote="it is an ai indictator and element and looks bad")
R("2026-10-20", P, T + "+" + M, "T0463;mem:feedback-wayclub-energy-and-logo-motion", "GIM", "Interactive demo UI on the landing page", "Composed imagery and calm scroll-linked motion", "PRO", quote="it feels cringe and not premium")
R("2026-10-20", P, T, "T0466", "TPL", "Empty green band under sign-up that feels generic", "Reworked landing section")
R("2026-10-20", P, T + "+" + M, "T0467;mem:feedback-wayclub-type-and-white", "TYP", "Tabular figures with slashed zero ('robotic')", "Proportional figures everywhere")
R("2026-10-20", P, M, "mem:feedback-wayclub-clubs-and-communities", "TYP", "Stretched wide headings", "Normal width everywhere")
R("2026-10-20", P, M, "mem:feedback-wayclub-energy-and-logo-motion", "IDN", "Giant black mark as the hero object", "Composed product imagery")
R("2026-10-20", P, M, "mem:feedback-wayclub-energy-and-logo-motion", "TPL", "Heading plus blue underlined link", "Designed section")
R("2026-10-20", P, T, "T0477", "DED", "Organiser section 'dead and dull'", "Own page and treatment")
R("2026-10-20", P, T, "T0477", "TPL", "Every page and section with the same presentation", "Each section unique")
R("2026-10-20", P, M, "mem:feedback-wayclub-energy-and-logo-motion", "SRF", "See-through sticky headers over posters", "Solid where words sit", "PRO")
R("2026-10-25", P, T, "T0487", "CLU", "Clutter and odd elements", "Luma and Meetup level event pages", "BEN")
R("2026-10-25", P, T, "T0487", "DED", "Tickets that look alike", "Each ticket unique to its event", "BEN")
R("2026-10-25", P, T + "+" + M, "T0495;mem:feedback-wayclub-energy-and-logo-motion", "GLO", "Blur under the register button", "No blur under floating action bars; fade into page tint")
R("2026-10-25", P, T, "T0498", "SRF", "Ticket edges that stand out", "Softer edges")
R("2026-10-25", P, T, "T0498", "IDN", "Mark drawn inconsistently across places", "One mark everywhere, colour by theme")
R("2026-10-25", P, T, "T0501", "MOT", "Unnecessary second entrance animation", "One entrance after the launch")
R("2026-10-25", P, T, "T0506", "DED", "Flat, basic mark", "Material: sheen, highlight, soft shadow", "BEN")
R("2026-10-25", P, T, "T0507", "DED", "Layout and background feel dead", "Lit by the relevant poster")
R("2026-10-26", P, M, "mem:feedback-wayclub-energy-and-logo-motion", "GLO", "Stuck header as a flat frosted slab with a hairline", "Progressive tinted fade, no rule")
R("2026-10-26", P, M, "mem:feedback-wayclub-energy-and-logo-motion", "COL", "Big green fee block", "Calm detail row with a green icon")
R("2026-10-26", P, M, "mem:feedback-wayclub-energy-and-logo-motion", "SRF", "Drawn rings on tickets", "Real cut notches, no outline")
R("2026-10-26", P, M, "mem:feedback-wayclub-energy-and-logo-motion", "DOT", "Marker line on the tab bar; count badges", "Removed")
R("2026-11-01", P, M, "mem:feedback-wayclub-energy-and-logo-motion", "CLU", "Bare-noun button labels", "Verb plus object with a matching icon")

# ---------------- Planket (shared calendar; web + Capacitor) ----------------
P = "planket"
R("2026-10-20", P, T, "T0453", "GEN", "Generic placement", "Well-placed, not generic")
R("2026-10-20", P, T + "+" + M + "+" + D, "T0457;mem:feedback-planket-less-typing;doc:docs/superpowers/specs/2026-10-20-planket-design.md", "MOT", "Things floating in the background", "No ambient motion; custom motion that answers a touch", quote="i don't want stuff flaoting in the background")
R("2026-10-20", P, T, "T0459", "CLU", "Cluttered screens", "Less on screen", "SHOT")
R("2026-10-20", P, T + "+" + M, "T0459;mem:feedback-planket-less-typing", "TYP", "Basic, generic, dull font", "Rounded face chosen from a shortlist", "SHOT;PRO")
R("2026-10-20", P, T, "T0460", "NAV", "Plus button out of place", "Contextual plus that opens a menu")
R("2026-10-20", P, T, "T0460", "ICO", "Friends icon", "Different icon")
R("2026-10-20", P, T + "+" + M, "T0465;mem:feedback-planket-less-typing", "NAV", "Two floating bars stacked", "Action inside its content; never stack bars")
R("2026-10-20", P, T + "+" + M, "T0468;mem:feedback-planket-less-typing", "TYP", "Fancy serif alternatives", "Soft, round, modern face", "PRO")
R("2026-10-20", P, T, "T0471", "ICO", "New calendar icon", "Earlier custom icon kept")
R("2026-10-20", P, T, "T0481;T0483", "CLU", "Overwhelming options", "Fewer choices at once")
R("2026-10-25", P, T, "T0486", "GLO", "White fade under the status bar", "Status bar treatment redone")
R("2026-10-25", P, T, "T0486", "ICO", "App icon inside a dark plate", "Mark fills the icon")
R("2026-10-25", P, T, "T0486", "MOT", "Flickering underline on nav icon", "Steady indicator")
R("2026-10-25", P, T, "T0492", "GLO", "Status-bar white fade still there", "Removed", "SHOT")
R("2026-10-25", P, T, "T0492", "DED", "Empty friends state with nothing in it", "Designed empty state", "BEN")
R("2026-10-25", P, T, "T0503", "CLU", "Many options shown at once on import", "Progressive questions")
R("2026-10-26", P, T, "T0508", "TPL", "Awkward 'everyone' friends section", "Crews plus an add-friend button")
R("2026-10-26", P, T, "T0508", "DED", "'Nobody here yet' state", "Clearer, better-looking state")
R("2026-11-01", P, T, "T0515", "CLU", "Cluttered screens", "Decluttered")
R("2026-11-01", P, T, "T0516", "CLU", "Over-explaining text", "Removed")
R("2026-11-01", P, T, "T0516", "TYP", "Very thin font weights", "Bolder, softer")
R("2026-11-01", P, T, "T0516", "ICO", "Weak approve and deny icons", "Bolder, softer, coloured")
R("2026-11-01", P, T, "T0516", "DED", "App feels dull, not coloured or alive", "Designed backgrounds and colour")

# ---------------- HACKFAM (hackathon teammate matching) ----------------
P = "hackfam"
R("2026-10-17", P, T, "T0427", "GEN", "Non-custom UI and motion", "Custom, premium, not over the top")
R("2026-10-18", P, M, "mem:feedback-audit-inherited-agent-work", "GEN", "Another agent's terse, generic design", "Audit and rework before building on it", "AUD", quote="the work codex did could be mid")
R("2026-10-18", P, T + "+" + M, "T0434;mem:feedback-no-dot-status-indicators", "DOT", "Coloured dot plus label status", "Status as specific words in context", "SHOT", quote="it looks ai generic")
R("2026-10-20", P, T, "T0475", "TPL", "Section presented unlike its neighbours", "Unique, proper layout")

# ---------------- CareerOS (career record SaaS) ----------------
P = "careeros"
R("2026-10-20", P, T + "+" + M, "T0461;mem:project-careeros-build", "NAV", "Two sidebars", "One floating sidebar with nested sections")
R("2026-10-20", P, M, "mem:project-careeros-build", "COL", "Warm white canvas", "Cool mist canvas")

# ---------------- Photoshoot (photo booth; Electron + web) ----------------
P = "photoshoot"
R("2026-10-06", P, T, "T0317", "GEN", "Landing page that looks AI coded", "Proper design and font language")
R("2026-10-19", P, M, "mem:project-photoshoot-landing-redesign", "TPL", "Replica app-window hero", "Real effects over a sample photo")
R("2026-10-25", P, T + "+" + M, "T0496;mem:project-photoshoot-four-photo-rework", "ICO", "Emoji in instructions", "Drawn icons", "BEN")

# Laws: written rules, by project ('*' = stated by him for all his products).
# kind: memory | doc | exec (a test, grep or lint that fails the build)
LAWS = [
    ("bupples", "2026-06-30", "memory", "MOT", "mem:feedback-bubble-no-entrance"),
    ("bupples", "2026-07-03", "doc", "COL;GLO;TYP;ICO;SRF;MOT;CLU", "doc:DESIGN.md (c:ba5dfe21)"),
    ("bupples", "2026-07-03", "exec", "ICO;GLO;MOT", "Icons grep, test/blur_allowlist_test.dart, test/motion_duration_ratchet_test.dart"),
    ("bupples", "2026-11-01", "memory", "GLO;COL;GIM;DOT", "mem:project-bupples-full-design-rework-2026-11"),
    ("adelante", "2026-10-01", "memory", "COL;GLO", "mem:project-adelante-completion-2026-10-01"),
    ("adelante", "2026-11-01", "doc", "GLO;MOT;TYP;CLU;COL", "doc:docs/design/2026-11-01-design-rework.md"),
    ("onplan", "2026-07-18", "memory", "COL;ICO", "mem:project-onplan-redesign"),
    ("portfolio", "2026-10-07", "doc", "SRF;TPL", "doc:docs/design-system.md"),
    ("portfolio", "2026-10-08", "memory", "GLO;MOT;TPL;COL;GEN", "mem:feedback-portfolio-nav-is-the-benchmark"),
    ("portfolio", "2026-10-14", "memory", "COL;ICO;TYP;NAV", "mem:project-portfolio-identity-pass-2026-10-14"),
    ("tajweed", "2026-10-13", "doc", "COL;TYP;MOT", "doc:docs/superpowers/specs/2026-10-13-...-design.md"),
    ("himalaya", "2026-10-14", "doc", "COL;GLO;TYP;ICO;DOT;SRF;TPL;CLU;MOT", "doc:docs/DESIGN.md; docs/research/inputs/04-anti-ai-slop.md"),
    ("himalaya", "2026-10-15", "memory", "DED;ICO;TYP", "mem:feedback-store-must-feel-alive"),
    ("partner-portfolio", "2026-10-15", "memory", "DED;TYP;COL;DOT;SRF;TPL;CLU", "mem:feedback-partner-identity [aliased]"),
    ("nutrigo", "2026-09-08", "doc", "SRF;COL;CMP", "doc:DESIGN.md"),
    ("nutrigo", "2026-10-01", "memory", "CMP;ICO;CLU;SRF", "mem:feedback-nutrigo-ux-bar"),
    ("wayclub", "2026-08-03", "doc", "COL;GLO;SRF;TPL;TYP;ICO", "doc:docs/ANTI_SLOP.md"),
    ("wayclub", "2026-08-03", "memory", "CLU;DED", "mem:feedback-wayclub-ux-bar"),
    ("wayclub", "2026-10-17", "memory", "COL;GLO;TYP;ICO;IDN;DOT;SRF;TPL;CLU;MOT;GEN", "mem:feedback-wayclub-no-ai-feeling; doctrine doc"),
    ("wayclub", "2026-10-19", "memory", "NAV", "mem:feedback-deep-dark-and-no-duplicate-entries"),
    ("wayclub", "2026-10-20", "memory", "DED;MOT;SRF;GIM", "mem:feedback-wayclub-energy-and-logo-motion"),
    ("hackfam", "2026-10-17", "exec", "TYP", "doc:docs/specs/design-system.md (CI greps uppercase, letter-spacing, banned fonts)"),
    ("planket", "2026-10-20", "doc", "COL;GLO;TYP;DOT;MOT;GEN", "doc:docs/superpowers/specs/2026-10-20-planket-design.md"),
    ("planket", "2026-10-20", "memory", "MOT;TYP;NAV", "mem:feedback-planket-less-typing"),
    ("careeros", "2026-10-20", "doc", "NAV;COL", "ADR-023 (mem:project-careeros-build)"),
    ("*", "2026-10-17", "memory", "TYP;COL", "mem:feedback-wayclub-type-and-white ('his other products unless he says otherwise')"),
    ("*", "2026-10-19", "memory", "DOT", "mem:feedback-no-dot-status-indicators ('all his products')"),
]

# Owner-side reversals: a pattern he asked for, or a ban he lifted.
REVERSALS = [
    ("tajweed", "2026-06-20", "2026-10-13", "COL", "Asked for a warm off-white light mode (T0036)", "Rejected warm paper as generic and dull (T0347)"),
    ("bupples", "2026-06-29", "2026-06-30", "MOT", "Asked for a zoom-out entrance on bubbles (T0072)", "Entrance removed after five failed fixes (c:682bf7c7)"),
    ("bupples", "2026-06-29", "2026-07-18", "TYP", "Monospace money digits chosen in the rebuild concept (c:092516b5)", "Called robotic; rounded digits default (T0208)"),
    ("bupples", "2026-07-18", "2026-11-01", "GLO", "Asked for native Liquid Glass on nav and every button (T0208, T0229)", "Mode removed entirely (T0521)"),
    ("adelante", "2026-07-18", "2026-11-01", "GLO", "Asked for the native Liquid Glass nav (T0205); frosted glow identity (2026-09-30)", "Frosted cards called 'cringe looking AI frost' (memory)"),
    ("wayclub", "2026-10-17", "2026-10-25", "GLO", "Agreed ban: no glass or blur on content", "Asked for frost the way Luma and Meetup use it (memory)"),
    ("wayclub", "2026-10-19", "2026-10-20", "MOT", "Motion spec rationed the mark to three moments", "Wanted many custom mark animations (T0442)"),
    ("himalaya", "2026-10-14", "2026-10-14", "DED", "Anti-slop restraint applied (one accent, still, sparse)", "Rejected as dead; wanted store density (T0396)"),
    ("partner-portfolio", "2026-10-15", "2026-10-15", "DED", "Research-compliant subtraction (no mono, no motifs)", "Rejected as generic; later chose dot-matrix and mono labels (memory)"),
]

def main():
    os.makedirs(DATA, exist_ok=True)
    for i, r in enumerate(sorted(ROWS, key=lambda x: (x["date"], x["project"])), 1):
        r["id"] = f"C{i:03d}"
    rows = sorted(ROWS, key=lambda x: x["id"])
    cols = ["id", "date", "project", "source", "evidence", "tell", "pattern", "replacement",
            "strategies", "owner_requested", "quote"]
    with open(os.path.join(DATA, "corrections.csv"), "w", newline="") as f:
        w = csv.DictWriter(f, fieldnames=cols); w.writeheader()
        for r in rows: w.writerow({k: r[k] for k in cols})
    with open(os.path.join(DATA, "laws.csv"), "w", newline="") as f:
        w = csv.writer(f); w.writerow(["scope", "date", "kind", "tells", "where"]); w.writerows(LAWS)
    with open(os.path.join(DATA, "reversals.csv"), "w", newline="") as f:
        w = csv.writer(f); w.writerow(["project", "asked_or_agreed", "reversed", "tell", "before", "after"]); w.writerows(REVERSALS)
    with open(os.path.join(DATA, "codebook.json"), "w") as f:
        json.dump({"tells": TELLS, "excess_pole": sorted(EXCESS), "bland_pole": sorted(BLAND), "strategies": STRATS}, f, indent=2)
    print(len(rows), "corrections,", len(LAWS), "laws,", len(REVERSALS), "reversals")

if __name__ == "__main__":
    main()
