# Plan — Argument Learning & Corpus Marketplace

The next axis: arguments accrue stats across plays, the AI stops repeating itself, and the marketplace evolves from a flat catalogue into a tiered, learnable corpus.

This is a Stage 2 build that runs orthogonal to [[plan_burdenshift.md]]. Burden Shift gave each round its trap dynamics; Argument Learning gives each *argument* a lifecycle.

---

## The core insight

A single AI evaluation tells you whether *this* argument was good *this* time. Across N plays of the same case, you get a real value vector: how often this argument lands a trap, how steeply its effectiveness decays as the AI learns to defend it, which defenses have ever beaten it, which characters fall for it.

Once we have that, three things unlock at once:

1. **AI no longer repeats itself.** Prior failed defenses are fed back to the AI prompt — it must invent a new angle, not rehash the obvious one.
2. **Arguments have an objective ranking.** "Best argument ever made in the Law case" becomes computable.
3. **The marketplace becomes a real economy.** Arguments have lifecycles, prices, decay curves, ownership royalties. Players can earn IA passively from a single great trap that gets reused.

---

## Goals (in order of priority)

1. **Anti-repetition** — the AI never gives the same defense twice for a known argument. The "Truman effect" is killed by design.
2. **Comparative value** — every argument has a real cross-play effectiveness score, not just one judge's opinion.
3. **Lifecycle economics** — fresh kills are premium; decayed arguments are cheap; the market churns.
4. **Educational corpus** — each historical case becomes a research dataset of attacks and defenses over time.
5. **Passive-earn for top authors** — players who invent legendary arguments earn IA every time their work is reused.

---

## Data model

### `argument_stats` (server-side, postgres)

Per argument-hash + case-id + character-id:

```sql
CREATE TABLE argument_stats (
  arg_hash         VARCHAR(64),     -- hash of argument text
  case_id          VARCHAR(64),
  target_character VARCHAR(64),     -- the character it was used against
  uses             INTEGER DEFAULT 0,
  trap_triggers    INTEGER DEFAULT 0,  -- forced an extraordinary claim
  trap_lands       INTEGER DEFAULT 0,  -- claim was STRUCK or WITHDRAWN
  trap_misses      INTEGER DEFAULT 0,  -- claim was PROVED
  avg_jury_shift   DECIMAL(4,2) DEFAULT 0,
  total_ia_won     INTEGER DEFAULT 0,
  effectiveness    DECIMAL(4,3) DEFAULT 0.5,  -- 0..1 rolling score
  last_used_at     TIMESTAMP,
  decay_slope      DECIMAL(5,3) DEFAULT 0,    -- per-use change in effectiveness
  PRIMARY KEY (arg_hash, case_id, target_character)
);
```

### `argument_events` (event log, append-only)

Every time an argument is used, a row lands here. We aggregate into `argument_stats` via triggers or a nightly job — both views matter (snapshot for marketplace, log for analysis).

```sql
CREATE TABLE argument_events (
  id            SERIAL PRIMARY KEY,
  arg_hash      VARCHAR(64),
  trial_id      VARCHAR(64),
  player_id     VARCHAR(64),
  case_id       VARCHAR(64),
  target_character VARCHAR(64),
  jury_shift    INTEGER DEFAULT 0,
  triggered_extraordinary  BOOLEAN DEFAULT false,
  burden_verdict           VARCHAR(20),  -- proved | withdrawn | failed | null
  ia_change     INTEGER DEFAULT 0,
  created_at    TIMESTAMP DEFAULT NOW()
);
```

### `defense_corpus` (the responses, all of them)

```sql
CREATE TABLE defense_corpus (
  id              SERIAL PRIMARY KEY,
  defense_hash    VARCHAR(64),
  argument_hash   VARCHAR(64),     -- the attack it was answering
  case_id         VARCHAR(64),
  character_id    VARCHAR(64),     -- which character delivered it
  mode            VARCHAR(20),     -- prove | withdraw | defend
  full_text       TEXT,
  outcome         VARCHAR(20),     -- proved | withdrawn | failed
  trial_id        VARCHAR(64),
  author_id       VARCHAR(64),     -- player who authored (null for AI)
  cited_evidence  VARCHAR(255),
  created_at      TIMESTAMP DEFAULT NOW()
);
CREATE INDEX idx_defense_argument ON defense_corpus(argument_hash, outcome);
CREATE INDEX idx_defense_character ON defense_corpus(character_id, outcome);
```

### `corpus_unlocks` (purchases of read access)

```sql
CREATE TABLE corpus_unlocks (
  id            SERIAL PRIMARY KEY,
  player_id     VARCHAR(64),
  unlock_type   VARCHAR(30),  -- defense | attack | pack | dossier_consult
  unlock_target VARCHAR(64),  -- defense_hash / arg_hash / pack_id / trial_id
  paid_ia       INTEGER,
  author_share  INTEGER,      -- to original author
  house_share   INTEGER,
  unlocked_at   TIMESTAMP DEFAULT NOW()
);
```

---

## Sprint 1 — Server-side argument-stats foundation

**Goal:** every argument used in a trial gets an event row, and stats roll up cleanly.

- Create `argument_events` + `argument_stats` tables (`api/init-argument-stats-schema.php`).
- New endpoint `POST /api/argument-event.php` — accepts `{ arg_hash, trial_id, player_id, case_id, target_character, jury_shift, triggered_extraordinary, burden_verdict, ia_change }`.
- Wire `submitArgument` and the post-eval flow in `courtroom.html` to fire this endpoint asynchronously when an argument is used.
- Aggregate updates: on every event, recompute `argument_stats` row for the (arg_hash, case_id, character) tuple. `effectiveness` is an exponentially-weighted moving average of `(trap_lands + 0.5*trap_triggers + jury_shift/12) / uses`.
- `decay_slope` updates: difference between effectiveness at last_used vs current.

**Acceptance:** after 5 plays of the Law case, querying `argument_stats` for the "corpse of France" argument shows realistic uses, trap_lands, and a decaying effectiveness.

---

## Sprint 2 — Defense corpus capture

**Goal:** every AI (and eventually player) substantiation is stored, with outcome, so the AI can avoid rehashing.

- Create `defense_corpus` table (in the same schema-init script).
- New endpoint `POST /api/defense-event.php` — accepts `{ defense_hash, argument_hash, case_id, character_id, mode, full_text, outcome, trial_id, author_id, cited_evidence }`.
- Fire from `resolveBurdenChallenge` after the verdict lands.
- Index by `(argument_hash, outcome)` so the prompt-injection lookup is fast.

**Acceptance:** after 5 plays where Law substantiates against the same attack, querying `defense_corpus` returns 5 rows with their outcomes and texts.

---

## Sprint 3 — Anti-repetition prompt injection

**Goal:** the AI never repeats a struck defense.

- Update `TribunalAI.substantiateClaim` in `tribunal-ai.js`:
  - Before composing the prompt, fetch up to 5 prior **struck** defenses for `(argument_hash, character_id)` from `defense_corpus`.
  - Inject them under a `PREVIOUSLY STRUCK DEFENSES — DO NOT REHASH:` section.
  - Also fetch up to 2 prior **proved** defenses with a `PRIOR SUCCESSFUL DEFENSES — DRAW INSPIRATION BUT VARY THE ANGLE:` framing.
- Tune the prompt so the AI varies *angle*, not *facts* (we don't want fabricated history).
- New endpoint `GET /api/defense-corpus.php?arg_hash=…&character_id=…&outcome=…&limit=…` for the lookup.

**Acceptance:** play the same trap argument three times in a row; receive three substantially different AI substantiations.

---

## Sprint 4 — Marketplace stats display

**Goal:** when browsing the marketplace, the player can see how an argument has performed.

- Extend `marketplace.php` browse/featured payloads to join against `argument_stats` and return `uses`, `effectiveness`, `decay_slope`, `last_used_at`, `trap_lands`.
- Update `buildMkPill` in `courtroom.html` to render:
  - Effectiveness bar (0-100%)
  - "Last landed: 3 trials ago" or "Never used"
  - Decay indicator (↘ −12% over last 5 uses) for veterans
- Trap listings get an extra "Trap conversion: X/Y" stat.

**Acceptance:** in the marketplace, a popular trap shows its conversion rate and recent decay; a fresh-listed trap shows "Never reused — premium fresh."

---

## Sprint 5 — In-trial dossier consult

**Goal:** the player can spend IA mid-trial to see top archived attacks for the current accused.

- Add a "🔍 Consult Archive (15 IA)" button to the player HUD, next to the intern.
- Clicking it: spends IA, takes the player's turn (turnState='consulting'), fetches `GET /api/argument-archive.php?case_id=…&character_id=…&exclude_used=true&limit=3` — returns top 3 effectiveness arguments the player hasn't yet used in this trial.
- Display in a modal with verbatim text (since they paid). Player can "copy to argument input" for one-click use, or close.
- Log a `corpus_unlocks` row (type=`dossier_consult`).

**Acceptance:** consulting the archive in a Law trial returns 3 attacks the player hasn't used, costs 15 IA, and the texts are usable as-is.

---

## Sprint 6 — Post-trial archive browsing

**Goal:** after the trial, the case archive page becomes a real research tool.

- Build a new "Case Archive" view (extend or replace existing `archives.html`):
  - Lists all arguments tried for this case across all plays
  - Sortable: effectiveness, recency, IA total won, trap conversion, author
  - Each row shows anonymized stats; full text requires unlock (5-25 IA depending on effectiveness)
- Author attribution shown ("listed by carrollspt") — links to leaderboard
- A "Top Killer Attacks" panel highlights the highest-effectiveness items
- Each unlock posts to `corpus_unlocks` and triggers the royalty split (Sprint 8).

**Acceptance:** visiting the Law case archive shows a sortable table of all attacks attempted, with effectiveness stats free and full text behind a per-item IA paywall.

---

## Sprint 7 — Character Defense Packs (DLC bundles)

**Goal:** curated bundles of successful defenses for each character, purchasable as one-time DLC.

- Add `character_packs` table — pack_id, character_id, name, description, price_ia (default 50), curator_id, pack_metadata (JSONB).
- Build a curation script (manual at first; later auto-curated by effectiveness threshold): selects top 20 proved defenses for a character → bundles into a pack.
- New endpoint `POST /api/character-pack.php?action=purchase` — verifies IA, grants unlock for every defense in the pack, posts a single `corpus_unlocks` row.
- "Pack Marketplace" sidebar tab — lists available packs with thumbnails, prices, "X defenses, all proved" summary.
- Unlocked packs add to the player's intern's available material — when the intern drafts an argument, it can reference defense-pack content as evidence.

**Acceptance:** buying the Locke Defense Pack for 50 IA grants read access to its 20 defenses + tags the player's intern with `locke_defense_pack:1`.

---

## Sprint 8 — Author royalties + throne mechanic

**Goal:** authors earn IA when their work is reused — but with a meritocratic cap and a refutation-bounty system that lets new champions dethrone old ones.

### Base royalty splits

- Add `royalty_payouts` table — payout_id, recipient_id, source_unlock_id, source_type, amount_ia, paid_at.
- On every `corpus_unlocks` insert, compute splits:
  - Defense unlock: 40% author / 60% house
  - Attack unlock: 40% author / 60% house
  - Pack purchase: 50% split across pack contributors weighted by their defenses' effectiveness / 50% house
  - Dossier consult: 100% house (no individual author — it's a service)
- Author IA earned credits to ledger with reason `royalty_<type>`.

### Per-argument hard cap

- Each argument has a lifetime royalty ceiling — **1000 IA per argument** (tunable). Once an argument has paid its author 1000 IA in total royalties, future unlocks pay the house side only.
- Prevents bitcoin-style accumulation. Forces top authors to keep inventing rather than living off one hit.

### Throne mechanic — refutation transfers future stream

- For each (case_id, target_character, argument_hash) tuple, track a "current champion" attacker — the author who is currently earning the unlock royalties.
- When a *defense* against a famous attack proves effective consistently — formally, when a new defense's `effectiveness > threshold` AND it has been used N times against the same attack with a high success rate — the attack's effectiveness decays.
- At a configurable threshold (say: attack effectiveness drops below 0.3 AND a counter-defense has shown >0.7 effectiveness over 5+ uses), the throne **transfers**:
  - The original author retains all historical royalties already paid out.
  - **Future** unlock royalties on that argument flow to the new champion (whoever authored the dethroning counter-defense).
  - A `throne_transfer` event posts to a public log so the audience sees the title change.
- Same throne mechanic applies to defenses: an attack that consistently beats a famous defense can claim that defense's future royalty stream.

### Hall of Throne (public)

- A new page `case/[case_id]/throne` shows current champion attacks and defenses per character.
- Visible in the case archive, the marketplace, and the public corpus view (Sprint 9). Drives competitive dynamics — players hunt to dethrone famous champions.

### Storage

```sql
ALTER TABLE argument_stats ADD COLUMN royalty_paid_total INTEGER DEFAULT 0;
ALTER TABLE argument_stats ADD COLUMN current_champion_id VARCHAR(64);  -- nullable until first throne event

CREATE TABLE throne_events (
  id              SERIAL PRIMARY KEY,
  case_id         VARCHAR(64),
  target_character VARCHAR(64),
  asset_type      VARCHAR(20),    -- 'attack' | 'defense'
  asset_hash      VARCHAR(64),
  previous_champion VARCHAR(64),
  new_champion    VARCHAR(64),
  trigger_event_id INTEGER,       -- the dethroning event
  created_at      TIMESTAMP DEFAULT NOW()
);
```

### Royalty earnings UI

- "Royalty Earnings" panel in the player's account view: lifetime IA earned, current champion holdings, throne transfer history (won and lost).

**Acceptance:**
- Player A authors a trap argument, lands its first kill, earns 4 IA per unlock for the first 250 unlocks (1000 IA cap), then payouts stop.
- Player B authors a counter-defense that consistently beats the same attack; effectiveness crosses threshold; throne transfers; player B now earns royalties on any future unlocks of player A's argument.
- A public `throne_events` entry records the title change with both player aliases.

---

## Sprint 9 — Public corpus (the film/education layer)

**Goal:** anonymous aggregate stats on each case, free to browse, fuels SEO and educational reach.

- New page `case/[case_id]/archive` (static-cached, regenerated nightly):
  - Total trials run
  - Most-tried attack vectors (top 10, anonymized)
  - Most-defended-by character
  - Effectiveness leaderboards (no full text)
  - Trends over time chart
- Designed for the film/educational consumer who isn't a player — but with prominent "Sign up to play" CTAs.

**Acceptance:** `moral.money/tribunal/case/john_law/archive` is publicly accessible, shows realistic aggregate stats, has no verbatim corpus content.

---

## Resolved decisions

These four design questions were settled before build kicked off — captured here so the implementation lands the right shape on first try.

### 1. First-mover advantage → capped + throne mechanic
**Decision:** per-argument lifetime royalty cap (1000 IA) PLUS a refutation-bounty throne mechanic. Old champions keep historical earnings; refuting defenses claim the *future* stream. See Sprint 8 for full mechanic.
**Why:** the user explicitly wanted meritocracy over patent-income dynamics — early innovators shouldn't get permanently rich just for being lucky/early, and late-comers must have a real path to overtake them with better work. The bitcoin-comparison is the anti-pattern. Throne mechanic creates real competitive drama for the watching audience.

### 2. Corpus moderation → pre-publication auto-scan
**Decision:** every listing runs through automated content checks (toxicity API + jailbreak heuristic detector + coherence/length minimums) before going live. Flagged listings hit an admin review queue.
**Why:** the corpus feeds the AI prompt — bad content amplifies. Pre-scan is cheap, fast, catches ~90% of slop, and prevents poisoning the wells. Adds a few seconds of latency to listing, acceptable.

### 3. AI prompt cost → aggressive caching + full corpus injection
**Decision:** restructure the substantiation prompt so case context + prior defenses live in a cacheable prefix block. Inject up to 5 struck defenses + 2 proved per call. First trial of a case pays full cost; repeats hit Anthropic's prompt cache.
**Why:** with cache hits, repeat trials of the same case are ~10x cheaper. Full corpus injection gives the AI maximum material to work with for variation. Right long-term economics for a product that expects many trials per case.

### 4. Stat recalculation → hybrid (real-time counters, batch derived)
**Decision:** increment counters (uses, trap_lands, ia_won) on every event for instant marketplace updates. Recompute effectiveness EMA + decay slope + throne thresholds via nightly cron.
**Why:** counters are O(1) increments — cheap. EMA + decay require windowing over recent events, which gets heavy at scale. Hybrid gives the player fresh-feeling stats on the metrics they care about most while keeping infra costs sustainable.

---

## Implementation order recap

With decisions settled, the natural build order is:
1. Sprint 1 (schema + event log) — foundation
2. Sprint 2 (defense corpus) — capture
3. Sprint 3 (anti-repetition) — the headline AI win, payoff visible immediately
4. Sprint 4 (marketplace stats display) — surfaces the work
5. Sprint 5 (in-trial consult) — opens the gameplay loop
6. Sprint 6 (post-trial archive) — opens the IA sink
7. Sprint 7 (character packs) — DLC layer
8. Sprint 8 (royalties + throne) — closes the economic loop
9. Sprint 9 (public corpus) — SEO + education layer

Sprints 1-3 are the minimum viable corpus (data + AI behavior change). Sprints 4-8 are the gameplay/economy layer. Sprint 9 is outward-facing.

---

## File map

- `api/init-argument-stats-schema.php` — Sprint 1 schema
- `api/argument-event.php` — Sprint 1
- `api/defense-event.php` — Sprint 2
- `api/defense-corpus.php` — Sprint 3 (read)
- `api/argument-archive.php` — Sprint 5 (read)
- `api/character-pack.php` — Sprint 7
- `tribunal/js/tribunal-ai.js` — Sprint 3 prompt injection
- `tribunal/courtroom.html` — Sprints 1, 2, 4, 5 wiring
- `tribunal/archives.html` — Sprint 6
- `tribunal/case-archive-public.html` — Sprint 9 (new)
- DB migrations: `argument_stats`, `argument_events`, `defense_corpus`, `corpus_unlocks`, `character_packs`, `royalty_payouts`
