keyword-table-restructure

ARCHIVED

"The average searches of the erank tag report are the same stats as the average searches of the keyword tool and the bulk tool. Lets combine all the erank data that we have into one grouped set of columns."

STAGES

  1. proposal09-21
  2. requirements09-21
  3. design09-21
  4. tasks09-21
  5. build—
  6. archived09-21

CAPABILITIES — 4 IN ONE CHANGE

  • big-join-table2 requirements
  • erank-merged-source4 requirements
  • keyword-listing-subrows5 requirements
  • keyword-table-grouping5 requirements

OUTCOMES — AND HOW EACH IS MEASURED

  • ✓1.1An exact value beats a capped one — corpus: `folk art embroidery` = 6 over `< 20`not stated
  • ✓1.2Two exact values agree, so the choice is free — corpus: `personalized gift` = 41,355 from two agreeing toolsnot stated
  • ✓1.3A capped value is still better than nothing — corpus: capped values retained where no exact existsnot stated
  • ✓1.4The one known collision still favours the exact reading (`beginner embroidery`) — corpus: `beginner embroidery` holds exact `20`not stated
  • ✓1.5The cap survives the merge — `bulkValueLabel` renders the `<`; covered by the component suitenot stated
  • ✓1.6Provenance renders as initials (`KT · B · T`) — live: `Reported by` shows `KT`, `KT · T`, `T`not stated
  • ✓1.7A tool counts as reporting when it saw the keyword — `reported_by` is built from sub-object presence, not per-fieldnot stated
  • ✓1.8More rows gain a ratio — `demandRatio` reads merged valuesnot stated
  • ✓1.9A ratio built on a cap is shown as an upper bound — ratio inherits `searchesCensored`; unit-testednot stated
  • ✓1.10Each bucket covers a contiguous run of columns — live: buckets span contiguous runs after the Targeting/Ranked swapnot stated
  • ✓1.11Ad results sit under Performance, not Targeted — live: ad columns sit under Performancenot stated
  • ✓1.12A thin bucket is not padded out — live: Targeted renders at one column plus the listing columns, unpaddednot stated
  • ✓1.13Bucket and band rules are distinguishable — live: 3px full-opacity bucket rule over 2px/50% band rulenot stated
  • ✓1.14The ungrouped keyword column carries no rule — live: the Keyword column carries no label or rulenot stated
  • ✓1.15A label pins to the left edge of the scroll region — verified in-browser at scrollLeft 3065: the `Performance` cell starts 79px off-screen left while its label renders at +12, on screennot stated
  • ✓1.16One label hands over to the next — same measurement: buckets scrolled fully past render their labels off-screen, so one label gives way to the nextnot stated
  • ✓1.17Numeric columns align right — unchanged production behaviour (`column.numeric ? "text-right"`); 30 of 33 columns carried the flag before this changenot stated
  • ✓1.18Text columns align left — as above; `Keyword`, `Found via`, `Listing` are the three without itnot stated
  • ✓1.19The agreed names render — layout test asserts the renamed headersnot stated
  • ✓1.20A two-line header keeps its break — two-line headers preserved via `U+2028`not stated
  • ✓1.21Several listings become several rows — traction test: four tagged listings become four sub-rowsnot stated
  • ✓1.22A keyword with no related listings stays a single row — traction test: no related listing leaves a single rownot stated
  • ✓1.23The count stays on the parent — live: `Listings` count renders on the parentnot stated
  • ✓1.24An ad-matched listing that carries no such tag still gets a row — traction test: ad-matched, untagged listing gets its own rownot stated
  • ✓1.25A landed-on listing that carries no such tag still gets a row — landed-on listings join by id the same waynot stated
  • ✓1.26Facts align to the listing they describe — layout test asserts exactly one column named `Listing`not stated
  • ✓1.27The band names Etsy as the matcher — band test asserts `matched by Etsy`not stated
  • ✓1.28A blank mark makes no claim — `advertised` defaults false and renders `—`, never `not advertised`not stated
  • ✓1.29A sort orders parents, not sub-rows — sort tests: parents reorder, sub-rows filtered out of `bodyRows()`not stated
  • ✓1.30Presence and absence compose into one query — `has Etsy Ads — Views` narrowed 2,310 rows to **14** in the browser — exactly the 14 ad keywords in the corpus; both directions unit-testednot stated
  • ✓1.31A matching sub-row keeps its parent visible — parent rows stay visible when a sub-row's value matches — `columnHasValue` asks the listings, and the parent is what rendersnot stated
  • ✓1.32The table ignores the page's width cap — live: renders at full width, no 1200px capnot stated
  • ✓1.33Width does not remove the need to scroll — live: 4,056px scrollWidth against a 960px viewport — still scrollsnot stated
  • ✓1.34All three header tiers pin, not just the column headers — verified in-browser: bucket, band and column-header keyword cells all report `sticky` when frozennot stated
  • ✓1.35Headers stay while the rows scroll — verified: `thead` reports `sticky` and holds while rows scrollnot stated
  • ✓1.36The corner holds both — verified at scrollLeft 3000 with freeze on — the keyword column holds at viewport x=0 while the table shows Etsy Adsnot stated
  • ✓1.37Freezing stays the reader's choice — verified: the toggle reads `Freeze keyword · off` on loadnot stated

WHAT HAPPENED

  1. ARCHIVED

    proposal and specs and design and tasks and archive landed

    2026-09-21 · 1 pull request
    • #512chore(openspec): archive five shipped keyword-explorer changes — SHIPPED

History read from a manifest built at 2026-09-30 (09e7bcc).

1 pull request, found by commits touching the change folder