---
title: Decide whether the nine KeepTradeCut data-view columns collapse to three plus a series param
type: task
status: draft
description: >-
  Researched and recommended against on 2026-09-24: the collapse is nearly free to migrate but
  breaks picker search and header labels. Blocked on react-table gaining param-derived header_label
  and param-value search indexing.
base_uri: user:task/league/data-views/collapse-keeptradecut-columns-to-series-param.md
created_at: '2026-09-25T04:22:43.378Z'
entity_id: ce064152-e072-4617-a7b1-be06a7e31d2e
owner_identity_uri: █████████████████████████
priority: Low
public_read: true
tags:
  - user:tag/league-xo-football.md
updated_at: '2026-09-25T04:22:43.378Z'
visibility_analyzed_at: '2026-11-05T23:48:45.180Z'
---

## Context

Nine data-view columns surface KeepTradeCut's three value products — a value and two ranks for each of crowdsourced, tradesourced and Crowd+Trades. The question this task holds is whether they should instead be THREE columns (`value`, `overall_rank`, `position_rank`) carrying a `series` param.

The idea was raised, researched and **recommended against on 2026-09-24**. This entity exists so the research is not re-done, and so the collapse can be reconsidered the moment its prerequisite lands.

## Why it is blocked rather than rejected

Two consumer-surface defects make the collapse a net loss today. Both live in `react-table`, and both are fixable.

- **The picker's search cannot see a param.** `table-column-controls.js:349-353` bypasses the group tree entirely once the user types, fuzzy-ranking on `column_title || column_id`. With the series in a param, typing "trade" or "blend" matches nothing — the user must add a Value column first, then find a dropdown. Today it lands on the column immediately.
- **A param cannot change a header label.** `table-header.js:456` renders `header_label` as a static string; a param contributes only a ` · suffix` (`:341-350`). Nine distinct headers become `Value · tradesourced`. `column_title` likewise collapses from nine to three, and league's notices surface reads `column_title` (`app/views/components/data-view-notices/index.js:33`).

**Unblocks when `react-table` gains param-derived `header_label` AND indexes param values in the picker's fuzzy match.** Either alone is insufficient.

## What the research established, so it is not repeated

**Migration is close to free, and that is measured rather than assumed.** Against production on 2026-09-24:

| Column id | `user_data_views` | `urls` (immutable) |
| --- | --- | --- |
| `player_keeptradecut_value` | 24 | 121 |
| `player_keeptradecut_overall_rank` | 2 | 4 |
| `player_keeptradecut_position_rank` | 2 | 4 |
| each of the six `tradesourced_*` / `blend_*` | 0 | 0 |

The three survivors of a collapse are exactly the three crowd ids, which keep their names. If `series` is DERIVED so an absent param resolves to crowdsourced — the pattern `is_superflex` and `as_of_month_day` already use in `player-keeptradecut-column-definitions.mjs` — the crowd alias hashes do not move either, so no saved view, short URL or redis entry is disturbed and no migration rule is needed.

**`COLUMN_ID_RENAMES` could not express this anyway.** It is strictly 1:1 id-to-id (`libs-shared/data-views-saved-view-migration.mjs:744`). An id-to-id-plus-param merge would be a new branch in `migrate_column_entry`.

**The alias key is not the obstacle the source comment claims.** `player-keeptradecut-column-definitions.mjs:824` rejects this design because it "would put the param in the alias key" — but the key already carries `date`, `year`, `year_offset`, `as_of_month_day`, `is_superflex` and `row_axes`. The incidents that comment cites were caused by a load-bearing param being OMITTED from the key, not by params being in it. Correct that comment when the collapse lands, or when it is abandoned.

**Server cost is four hooks, and KeepTradeCut is better positioned than the precedent.** A dynamic `column_name` needs `select_as`, `main_select`, `main_group_by`, `main_where` and `main_select_string_year_offset_range`; the generic paths read `column_name` as a static property in six places. KeepTradeCut already declares `main_where` and the offset-range override. `team_unit_dvoa` is the existing precedent and it is missing `main_where` — tracked separately at [[user:task/league/data-views/fix-where-clause-dynamic-column-resolution.md]].

**Edit surface is 34 files**: 30 fixtures under `test/data-view-queries/` (the `keeptradecut-*` glob finds only 23 — scope by content), 5 specs, 9 field-index descriptions, 9 SPA field definitions, and `docs/data-view-specs/column-families/external-ratings.json`.

**One upside beyond ergonomics.** `player_keeptradecut_tradesourced_position_rank` is 45 bytes against the 60-byte alias budget; collapsing walks away from the truncation limit `docs/guides/data.md:325` documents.

## What shipped instead

Picker clutter — the only uncontested benefit of the collapse — was addressed on 2026-09-24 by nesting the six non-crowdsourced fields under `KEEPTRADECUT` sub-groups, moving no column id. See the `column-groups.js` and `keeptradecut-table-fields.js` commit in league.

## Not to be confused with

[[user:task/league/rename-keeptradecut-crowd-value-column.md]] renames the DATABASE columns (`keeptradecut_value` to `crowdsourced_value`). It is independent of this and neither blocks the other.
