Skip to content

docs(experiments): spec for the listing Created By and schedule filters, Created By column and pagination alignment (#37307) - #37514

Open
oidacra wants to merge 5 commits into
mainfrom
issue-37307-experiments-list-filters-pagination
Open

oidacra wants to merge 5 commits into
mainfrom
issue-37307-experiments-list-filters-pagination

Conversation

@oidacra

@oidacra oidacra commented Sep 11, 2026

Copy link
Copy Markdown
Member

This PR carries the spec for #37307. No implementation yet.

What the work delivers

Four additions to the Experiments listing screen, collected from Global Sprint demo feedback. Each is independently shippable.

  1. Created By filter — a chip that narrows the list to experiments created by one or more chosen people. Options come from the whole user directory rather than only from creators already present in the list, paged in as the option list is scrolled, searched server-side, and shown without counts. Matching is on the creator's user id, which the payload already carries.
  2. Schedule time filter — a single-select chip over the scheduled start date: any schedule, or the last 1, 3, 6 or 12 months. The comparison is a lower bound only, so experiments scheduled to start in the future match every window, and experiments with no schedule are excluded unless "Any schedule" is chosen.
  3. Created By column — the creator's name in the table. Blocked by Expose the experiment creator's username in the Experiments API #37304.
  4. Pagination alignment — closes the gaps that remain between this listing's paginator and Content Drive's.

Filtering stays client-side over the already-loaded set, and both new filters live in the URL alongside the existing ones.

Corrections to the issue's description of the code

The issue describes the current code in seven places that no longer match the branch. Each one changes what the work is, so they are recorded in the spec's "State of the code as found" section and every requirement is written against the code rather than against the issue.

  • The default page size is already 20 and the offered sizes are already 20/40/60. Two of the five listed pagination gaps are already closed.
  • lazyLoadOnInit is already effectively set: the table is unconditionally lazy and the framework default for that flag is on. The defect the issue describes does not exist.
  • Content Drive's paginator-visibility rule cannot be copied literally. It shows the paginator whenever the table is lazy, and this table is lazy, so adopting the expression verbatim gives the opposite of the issue's own acceptance criterion. The spec adopts the intent instead, which is available here because this listing knows its true total.
  • createdBy is serialized by the backend but is not declared on the client's experiment type, so the filter needs a model change and not only store work.
  • A shared lazy multiselect with server-side search and infinite scroll already exists and is publicly exported, so the popover is a reuse rather than the new sibling component the issue anticipated.
  • The users endpoint's page parameter is 1-based, so "resets to page 0" is wording only.

One further finding, from the design review rather than the issue: the single-user lookup endpoint requires administrator rights, or access to both the Roles and Users areas, and refuses everyone else. Resolving a selected creator's name through it would have produced a filter that labels correctly when a person is picked and breaks on reload, for non-administrators only. The spec routes that resolution through the directory search instead, which any back-end user can reach, and records the constraint because the single-user lookup is the call an implementer reaches for first.

Design prototype

Six places where the prototype and the issue disagree are recorded as assumptions with the issue's refinement decisions winning: per-option counts, the chip's count badge, a selectable "Any schedule" row, the window label wording, an initials avatar in the cell, and the "Experiment" column header with no Modified column.

Dependency

The Created By column requires #37304, which adds the creator's display name to the experiment payload. The two filters are not blocked by it and can proceed in parallel.

Contents

64 functional requirements, 16 success criteria, 4 user stories, 30 acceptance scenarios, 10 edge cases and 18 assumptions. No open clarifications remain.

Closes #37307. Visual review page (summarizes; the spec decides): https://claude.ai/code/artifact/2d8d855f-39cd-4ea1-b1d1-046f3433feab

oidacra and others added 3 commits September 10, 2026 17:48
…reated By column, pagination alignment

Spec for #37307, collecting four additive changes to the new Experiments
listing screen: a Created By chip filter over the user directory (server
search, infinite scroll, multi-select, no counts, matched on the creator
id), a single-select schedule time filter with five fixed lower-bound
windows, a Created By column rendering the creator name, and the
remaining Content Drive pagination alignment.

Grounded against the branch rather than against the issue body. Six of
the issue's claims about the current code no longer hold and are
recorded in a "State of the code as found" section, because each one
changes what the work is:

- the default page size and the 20/40/60 options are already in place;
- the lazy-load-on-init flag is already effectively set, so the defect
  the issue describes does not exist;
- Content Drive's paginator-visibility rule, copied literally, would
  show the paginator always here, the opposite of the issue's own
  acceptance criterion, so the spec adopts its intent instead;
- the creator id is serialized by the API but is not declared on the
  client's experiment type, so the filter needs a model change;
- a shared lazy multiselect with server search and infinite scroll
  already exists and is publicly exported, so the popover is a reuse
  rather than the new component the issue anticipated.

53 functional requirements, 15 success criteria, 4 user stories, 28
acceptance scenarios, 10 edge cases. The Created By column is marked
blocked by #37304; the two filters are not. Two open product questions
remain (chip labelling of a selected person after reload, and column
placement per the design prototype); neither sits on a P1 path.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ng filters

Amends the #37307 spec with the answers that were outstanding when it was
first written, plus the scope decisions taken while reviewing it.

Resolved:

- Created By chip labelling after a reload (FR-009a): selected ids are
  resolved to names by lookup on hydration, not derived from the loaded
  experiments. The derived label fails precisely for a creator with no
  experiment in view, which is the case that produces the empty state.
- Created By column placement (FR-032): between Variants and Schedule,
  read from the design project. Added rather than replacing, so Modified
  stays and the table goes to nine columns.

Scope decisions:

- The shared user-directory search lives in data-access and Experiments
  consumes it from there (FR-015); consolidating the two existing
  portlet-local copies is explicitly out of scope (FR-015a), with the
  three-way duplication recorded openly and a follow-up to file.
- Every filter of the list is a query param and view state lives in the
  route, stated as a principle so later filters inherit it (FR-045), with
  an explicit negative for the popover's own option-list search, which is
  transient UI state (FR-045a). Absent-means-default is confirmed as
  satisfying the rule rather than bending it (FR-047).
- The Created By column is display-only and adds no sort field, URL value
  or comparator (FR-034a) — every neighbouring column is sortable, and the
  sort fields are a closed set wired into the address contract.
- The chip's collapsed label follows the shared chip rather than the
  prototype's count badge (FR-016a).

Also corrects FR-029, which as written could be read as requiring the
screen to suppress #37304's deliberate raw-id fallback, and widens the
blocked range to FR-028 through FR-034a: the skeleton-cell and
minimum-width requirements are column work and equally blocked.

Six further prototype-vs-issue divergences are recorded as assumptions,
with the issue's refinement decisions winning in every case.

Both NEEDS CLARIFICATION markers are now gone; 58 requirements, 15 success
criteria, 18 assumptions.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ation

Follow-up to the dissect session on the five requirements added by the
previous commit. FR-009a is replaced by six requirements that settle the
mechanism it had left open, and FR-016a gains the label it was missing.

Resolution now goes through the same directory search the option list
uses, one selected id at a time, and explicitly NOT through the
single-user lookup: that endpoint requires administrator rights or access
to both the Roles and Users areas and refuses everyone else, so building
on it would have produced a filter that works when a person is picked and
breaks on reload, for non-administrators only. The directory search is
open to any back-end user, which is the population that reaches this
screen. The constraint is written down because the single-user lookup is
the call an implementer reaches for first (FR-009b).

That search matches ids as a substring, so a query for one id can return
an id that merely has it as a prefix; the exact match must be selected
rather than the first result (FR-009c).

Names are deliberately not read off the loaded experiments even though
they will be there once #37304 lands (FR-009d). One always-correct path
was preferred over a fast path plus a fallback, because the two would
behave differently during the window when the filter ships and #37304 has
not, and because the fallback would run too rarely to be exercised. The
cost — a request per selected person per hydration — is recorded in the
assumptions rather than glossed.

The chip shows an explicit loading state while resolving (FR-009e), which
extends the shared chip, and falls back to the id if resolution fails
without dropping the selection or breaking the filter, which matches on
ids (FR-009f).

FR-016a now states that the collapsed label follows Status and Goal with
no exception, and says plainly that this trades legibility for
consistency: two long personal names will truncate where two status names
do not. FR-016b pins the unselected label to the shared "All" rather than
the prototype's "All Users".

Adds SC-016 and two US1 scenarios covering a shared link opened cold by a
non-administrator, which is the case the permission finding makes sharp.

64 requirements, 16 success criteria.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@claude

claude Bot commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

Claude finished @oidacra's task in 1m 13s —— View job


Reviewing the spec…

  • Read the four spec documents
  • Verify backend claims (user endpoints, permissions, AbstractExperiment.createdBy, DotExperiment model gap)
  • Verify frontend claims (shared multiselect, pagination constants, narrowing chain, URL contract, duplicate user searches)
  • Post review

oidacra and others added 2 commits September 15, 2026 12:26
…filters

Phase 1 artifacts from /speckit-plan. plan.md, research.md and quickstart.md
stay local per .gitignore; these two carry verified contracts and are tracked
as the Spec-Kit customization note requires.

data-model.md records the two fields added to the client experiment type, the
closed set of schedule windows and their boundary rules, the chip option shape,
and where the two new narrowings sit in the store's computed chain — after the
counts snapshot, alongside status and goal, because placing either earlier would
move the Status and Goal chip numbers that FR-050 requires to stay fixed.

contracts/user-directory-search.md records what the shared capability must
expose and the two endpoint behaviours the caller has to honour: the page
parameter is 1-based despite declaring a default of 0, and the free-text query
matches ids as a substring, so an exact-id match must be selected rather than
the first result. It also records why the single-user lookup must not be used —
it requires administrator rights or both the Roles and Users portlets, so
resolving a name through it would break the chip on reload for non-admins only.

contracts/listing-url-parameters.md records the address contract: the ten
existing parameters unchanged, the two additive ones, absent-means-default as
satisfying the filters-live-in-the-route rule rather than bending it, and the
exclusion of transient popover state.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

Experiments listing: user and time filters, Created By column, and Content Drive-aligned pagination

1 participant