Repository navigation
037: Filter the Collection by Location - #174
Merged
Merged
Conversation
… selection
Spec 037 plan Phase 1 (model layer). CollectionFilter::Place parses the
`location` value into its canonical string ("", "none" or an id of at
most 18 digits) and applies it as a plain predicate on lots.location_id.
CollectionFilter reads the account's locations once (places?, the
select's options and the chosen name) and resolves the URL's value
against them for display; the grid drops its place line under a location
filter. bulk_selections gains location_filter (default "", null false);
BulkSelection compares and restarts with it and applies it unresolved,
so a removed or foreign location selects nothing (decision 7).
BulkRemoval keeps the location when it restarts the selection.
Ruling: the down migration drops the column with SQLite's native
ALTER TABLE DROP COLUMN rather than remove_column, so the table isn't
copied and its marks aren't cascaded. Cost if wrong: a rollback on a
SQLite older than 3.35, which Rails 8.1 doesn't support anyway.
Ruling: implemented by this session itself, not per-phase subagents,
as the Orca brief forbids helper agents except the review.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…ge, bulk mode and their redirects Spec 037 plan Phase 2 (controllers and helpers). The page reads `location` into the grid or table; collection_listing_path carries it and leaves it out for all; the sort headers carry the table's resolved location. Edit many stores the parsed value; a bulk submission uses `rendered_location` (canonical, never re-resolved) for its context, pagers, sorts, actions and Done, and Filter applies the select's value, keeping the page only when neither filter changed. BulkSelected's return path carries the stored location; the Undo controller needed no change (it re-reads its return URL). Request specs cover AC-1.2–1.4, 2.1, 3.1, 4.2, 5.1–5.3, 5.5, 5.6, 5.8, 6.1, 6.2 (two accounts) at the controller level. Ruling: AC-5.8's refusal page re-renders under the URL's location, which no longer resolves, so it shows all locations (decision 7); the count line has no "of". Asserted on the count line here; the select's markup is Phase 3. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Spec 037 plan Phase 3. The filter bar shows the design system's
FilterSelect ("All locations", "No location", then the account's
locations in Location.ordered order) with a Filter button, only while
the account has a location. In bulk mode the select joins the bulk
form and the existing default `go=filter` button is made visible beside
it (still the first submit in tree order); the form carries
`rendered_location`. Pagers, the bulk pager, the view switch and Edit
many carry the location; the empty sentence names the location or
"without a location".
Ruling: the empty sentence is a partial (collections/_no_match), not the
plan's `no_match_message` helper: a helper string is escaped whole, so
its literal quotes came out as " and broke spec 004's existing
body assertions; a partial keeps them raw with no html_safe. Cost if
wrong: none in the browser, the text is the same.
Ruling: no CSS was needed; the select and button sit in
.c-filterbar__filters as FilterSelect lays them out (checked at 390px
by the system spec).
Ruling: the system spec was written after the views (the request
markup specs were the red step for this phase).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Spec 037 plan Phase 4. Measures the collection page under a location filter (5,000 lots over 300 locations, two other accounts' lots in the table): every page under 500 ms (largest: the unfiltered table, 163 ms), so the reserve [account_id, location_id] index is not added. verification.md records per-AC evidence and the statement counts; the implementation review and manual checks follow. The collection-and-lots area doc gains the location filter, tiles under it and the selection's location (each with its source) and drops #47 from "Not yet"; the roadmap, the specs index and CLAUDE.md's locations paragraph say it is built. Ruling: the measurement is a `:timing` request spec (run with SCANNER_TIMING=1, never gating), per the brief's "measurements as timing specs". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ble pager under a location Findings 1–3 of spec 037's implementation review (Opus, read-only, SPEC-ALIGNED, minor): SelectionState shows a selection's ticks under its location and nothing under another (AC-5.3); the removal confirm page's Cancel and Back carry the location and the filtered table pages its lots (AC-5.6, AC-1.4); the confirm page for a selection whose location was removed sends the collector back with "Select at least one item." (AC-5.5). The code already did each; these pin it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Records the Mode B review (SPEC-ALIGNED, five minor findings: three fixed by afe0ce8's tests, this file's sections, the local Gemfile.lock kept out) and the manual checks from the PR evidence: desktop and 390px shots in light and dark, and a walkthrough GIF of the filter in grid and table view, then bulk mode's Select all, Remove and Undo under it. Taken against a dev database seeded with placeholder printings. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Session-wrap for spec 037: the screenshot memory gains that headless Firefox prefers dark and Turbo keeps <html>'s data-theme, so light shots must set it too; a lesson records that a helper returning a sentence escapes its literal quotes, so copy that mixes them with user text goes in a partial. Ruling: written without a maintainer prompt, as the Orca brief asks the worker to run session-wrap and commit what it writes; limited to two candidates with direct evidence in this session. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The area doc's rules for the location filter came in with Phase 4 (0690b63); this adds its Distillation log row and lists spec 037 under the area in docs/architecture/README.md. The index row is Frozen, by collection and lots, with its plan's retirement owed; its supersessions were already recorded in both directions (specs 004, 006, 033). The FilterSelect note is the design system's (its component doc). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… (spec 027 D4) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Owner
Author
plainprogrammer
marked this pull request as ready for review
November 6, 2026 05:58
This was referenced Nov 6, 2026
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements spec 037 (0.2.2) per its plan. The collection's filter bar gets a Location select: All locations, No location, or one of the collector's locations. The grid, the table, paging, sorting and bulk mode all honour it, combined with the name search (AND).
What each phase did
ff995c1)CollectionFilter::Placeturnslocationinto its canonical form:"","none", or an id of at most 18 digits. Anything else counts as all. It is then applied as a plainlots.location_idpredicate.CollectionFilterreads the account's locations once (places?, the options, the chosen name) and checks the URL's value against them for display. Under a location filter the grid skips its place line.bulk_selections.location_filteris a new string column, default"",null: false, reversible.BulkSelection#context?,#restart!,#lotsand#record!use it, never re-resolved, so a removed or another account's location selects nothing (decision 7).1c57170)collection_listing_path(which leaves out all), the sort headers, Edit many and the bulk form all carrylocation.rendered_locationfor their context, pagers, sorts, actions and Done. Only Filter applies the select's value, and it keeps the page only when neither filter changed.BulkSelected's return path carries the stored location; Undo needed no change.2f4c2bd)go=filterbutton becomes visible beside it; it is still the first submit, so Enter still applies the filters.location.0690b63):timingrequest spec: 5,000 lots over 300 locations, plus two other accounts' 5,000 lots each. Every page is under 500 ms (largest: the unfiltered table at 163 ms; with a filter, 21–106 ms), so the reserve[account_id, location_id]index is not added.verification.md, the collection-and-lots area doc, the roadmap, the specs index and CLAUDE.md.afe0ce8): tests for findings 1–3 (below).96c3fbe).46f7ae5): screenshot memory, one lesson.1acece1,5b47f03,8628b13): the index row is Frozen by collection and lots, plan retirement owed.Rulings and deviations (each also in its commit body)
collections/_no_matchreplaces the plan'sno_match_messagehelper. A helper's String is escaped whole, which turned spec 004's literal quotes into"and broke three existing body assertions. The partial keeps them raw withouthtml_safe.downuses SQLite's nativeALTER TABLE … DROP COLUMN, so the table isn't copied and its marks aren't cascaded.SCANNER_TIMING=1and never gates.ff995c1and1c57170sayCo-Authored-By: Claude Sonnet 5.5by mistake. The work ran on Opus 5.5; later commits say so, and the pushed commits were not rewritten.Implementation review: SPEC-ALIGNED
An independent read-only
sdd-reviewMode B on Opus found nothing blocking or major. It reported five minor findings:selection_state_spec).verification.mdsections were missing. Fixed.Gemfile.lockplatform change. Kept out of every commit.The review also traced tenancy, the fail-closed paths and every caller; details are in
verification.md.Tests
place_spec(4),collection_location_filter_specrequests (21),collection_location_select_specmarkup (14), system spec (6).SCANNER_TIMING=1.bin/ciis green, also in the pre-push hook on8628b13.Upgrade::Harness(Flaky: Upgrade::Harness "removes its temporary directory" races other suites through the shared tmpdir #178), unrelated to this change. It passed on re-run.Screenshots
Taken with headless Firefox against a dev database seeded with placeholder printings (no card art): one collector, three locations, 14 lots.
Worth checking by hand
Closes #47
🤖 Generated with Claude Code