Change control — Friday 7 August
v2.1.0Live on the store since Friday 7 August. Everything below went out together; where a line says "candidate" it means the copy this was written against on Thursday, which is now the store.
Search & catalog — 6
A wrong-manufacturer redirect closes for BRIGGS and 19 other vendor codes Vova on dev fix front#3422
What it is Last Wednesday's emergency fix stopped the site sending a shopper to a different manufacturer's part for codes it could read. It couldn't read every code — six-letter codes like BRIGGS, and any code with an underscore, fell through the same guard it had just closed. This closes it for those too: an unresolvable branded code now says the part was not found instead of guessing.
How we test it An asserted-but-unresolvable branded URL 404s instead of redirecting to a different manufacturer's part; a bare part number and a resolvable branded code are unaffected.
Evidence
Measured today, same method as last week — -A crop-audit, reading the served
title, not just the status code.
| URL | prod today | crop-dev.app |
|---|---|---|
/parts/CT-HARVEST_TEC-004-650033-SS |
308 → CT-NHL-SS → 200 "GENERAL · SS · New Holland" |
404 "Part Not Found" |
/parts/CT-FIA-5103868 (heritage control) |
308 → CT-NHL-5103868 |
308 → CT-NHL-5103868 — unchanged |
Scope, from Tuesday's production measurement: 1,012 URLs across 20 vendor codes — 679 exact part-number collisions, 333 truncated to a wrong maker and a wrong part like the row above. BRIGGS alone is 355.
Roll back or fail forward Fail forward. Only the fail-open branch of the redirect guard changed; 58 of 58 tests pass, four independent people tried to break it and could not. Revert the merge commit if a code that should resolve starts 404ing instead.
The parts catalog now shows a part on a phone without scrolling Vova on dev fix front#3405
What it is On a phone, the parts page and every brand page loaded to an empty blue banner. The first product card sat one pixel below the visible screen — not a slow load, the layout itself pushed every part out of view until you scrolled.
How we test it At the exact screen size Google's mobile index renders at (390×844), a product card — image, price, Add to Cart — is visible without scrolling.
Evidence Same URL, same viewport, before and after:

/parts
Roll back or fail forward Roll back — layout only, nothing stored.
Some vendor parts stopped showing a bare number as the item you'd buy Vova on dev fix search#858
What it is For vendor codes the search index couldn't recognise (BRIGGS, AGCO and others), the part a shopper would actually add to cart carried a bare number instead of the branded one — the inverse of the redirect bug above, on the search side rather than the page side.
How we test it Search a number that collides across manufacturers; every card carries its own manufacturer's branded number, none falls back to a bare part number.
Evidence
Confirmed live on the dev backend after deploy, not just on green CI — revision
search-nest-00268-pev, latestReady == latestCreated, 100% traffic,
image tag matching the merge commit exactly.
Search 5103868 | prod today | crop-dev.app |
|---|---|---|
| Part pages the cards link to | CT-NHL-5103868, CT-FER-5103868, CT-BRIGGS-5103868 |
CT-NHL-5103868, CT-FER-5103868 |
| Where the BRIGGS card leads | 308 → /parts/CT-NHL-5103868 — a different maker's part |
card not offered |
Roll back or fail forward Roll back — one deploy to the previous revision, no data changed.
Deep pages of the parts catalog no longer come back empty while pretending everything is fine Vova on dev fix search#861
What it is The catalog offers 1,000 pages of parts. Past roughly page 900 the page sometimes came back completely blank — no parts, no message, and the page still reported itself to Google as a good page. It happened when the parts list took longer than five seconds to build: the count of results still arrived, the results themselves did not, and only page one was set up to notice that and say so. Now any page at any depth that cannot be built says "busy, try again" instead of showing an empty shelf, and Google is told not to keep the blank version.
How we test it A deep catalog page must either come back with a full grid of parts or come back as a busy page — never as a normal page with zero parts on it beside a results count in the hundreds of thousands.
Evidence We loaded a deep catalog page on both sites and counted the product cards in the page that came back, then repeated the load six times against each search service. The blank state is a timing race, so it did not reproduce during this measurement — that is recorded literally below rather than claimed as proof it is gone.
| URL | prod today | crop-dev.app |
|---|---|---|
/parts?page=960 | 200, 40 product cards | 200, 40 product cards |
/parts?page=40 | 200, 40 product cards | 200, 40 product cards |
| deep page loaded 6 times in a row | 200, 40 cards on 6 of 6 — blank state not reproduced today | 200, 40 cards on 6 of 6 — blank state not reproduced today |
| page far past the end of the catalog | 400, refused | 400, refused |
Roll back or fail forward Rolling back is a single swap on the search service and restores the previous behaviour, which is the blank page. There is no front-end change to undo.
Brand filter counts now match the number of parts you actually get, and the stock filter no longer shows the same option twice Vova on dev fix search#860
What it is The brand filter in the search sidebar counted parts that are not for sale on the site, so the number on the button promised far more than clicking it delivered — on a search for FASTENERS the Ford button said 22,466 and the results said 6,268. The stock filter had a second problem: several internal stock codes all mean "out of stock" to a customer, and each one was drawn as its own separate button, so the same option appeared several times over. Now the brand count is built from the same set of parts the results grid uses, and the stock options are combined into one button each.
How we test it For one search, the number on a brand button must equal the number of results you get after clicking it, and no stock option may appear more than once.
Evidence
We asked both search services for the filter panel and the result count for the same search, FASTENERS, and read the numbers back literally.
| What we counted | prod today | crop-dev.app |
|---|---|---|
Ford (FRD) button, search FASTENERS | 22,466 | 6,268 |
| Results you actually get for Ford | 6,268 | 6,268 |
| New Holland (NHL) button | 114,897 | 64,057 |
| Fiat (FIA) button | 6,414 | 2,386 |
| Times "out of stock" appears in the stock filter | 5 separate buttons | 1 button |
Roll back or fail forward Rolling back is a single swap on the search service and brings the inflated brand numbers back. Two other filter numbers — the category buttons and the overall total — are still overstated because they come from the database side, which is a separate piece of work already filed.
Sorting search results by best sellers no longer shows the same part twice across pages — once the database side is applied Vova on dev change search#854
What it is When a shopper sorts search results by best sellers, page two can repeat a part that was already on page one, and a different part is never shown at all. The cause was that the set of parts we picked from grew larger the deeper the shopper paged, so each page was really a different ordering rather than a continuation. The change makes that set depend only on what was typed, so every page is drawn from the same ordering. Nothing changes for a customer yet: this is the code half only. The matching database change is Alex's to apply, and until Alex applies it the site behaves exactly as it does today.
How we test it Ask for page one and page two of the same best-sellers search and check that no part number appears on both.
Evidence We asked both the live site's search service and the candidate one for pages one and two of "oil filter" sorted by best sellers, and compared the part numbers returned; today they are identical, which is the proof that nothing has changed for shoppers yet.
| What we counted | prod today | crop-dev.app |
|---|---|---|
| Page 1 parts, "oil filter", best sellers | 47943212, 47617638, 51441620, 51575943, 31RF-10550 | 47943212, 47617638, 51441620, 51575943, 31RF-10550 |
| Page 2 parts, same search | D8NNM903EB, 31RF-10550, 84475969, 48145957, 31RF-10050 | D8NNM903EB, 31RF-10550, 84475969, 48145957, 31RF-10050 |
| Parts repeated on both pages | 1 (31RF-10550) | 1 (31RF-10550) |
| Database change applied | not applied | not applied |
Roll back or fail forward There is nothing to roll back today, because no shopper-visible behaviour has changed. Once Alex applies the database change, the previous version of that one database routine can be put back on its own, without touching anything else on the site.
Breadcrumbs — 2
Every breadcrumb trail now comes from one list, and starts with Home Vova on dev fix front epic #3407
What it is A sitewide audit on Monday found the breadcrumb trail (the "Home > Parts > …" strip, and the matching data Google reads) was hand-built per page in most places, so the visible trail and what Google sees could disagree. Four specific defects it found are fixed: a diagrams page that told Google it had a parent it never linked to; a mid-trail entry missing on the not-found page; two rendering engines for the same breadcrumb; and the "Parts" page named two different things on the same page. One policy change rides with it: trails now always start with "Home". That reverses a narrower decision made in June (issue #1201) that had removed Home from six page types on purpose — worth saying plainly rather than letting whoever reads the old decision next re-revert this by mistake.
How we test it A new automated check reads every page's own visible trail and demands the machine-readable version say the same thing, computed fresh rather than compared against a fixed list — so a new page with no trail at all fails the build instead of shipping unchecked.
Evidence Three of five defects shown below, each re-measured today:
| Page | prod today | crop-dev.app |
|---|---|---|
| Equipment detail (e.g. Workmaster-95) | Equipment > New Holland > … | Home > Equipment > New Holland > … |
Brand diagrams tab (/parts/brand/mchale/diagrams) |
schema: Home > Parts Diagrams > McHale > Fixed Chamber Round Balers | schema: Home > Brands > McHale |
| Parts page name | "Parts Store" in the data, "Parts" on screen | "Parts" in both |
The guard itself is green on this branch (CI job pr-localhost-crawl).
Roll back or fail forward Fail forward preferred — reverting brings back a real, if smaller, defect (the borrowed-trail bug is a genuine Google violation); a clean revert is available if the Home-first change needs to be undone on its own.
An unknown diagram type stopped returning a fake "page found" Denis on dev fix front#3374
What it is
Any made-up word after /diagrams/type/ on a brand page loaded as a normal page —
an unbounded number of fake pages Google could have tried to index.
How we test it A type that does not exist answers "not found", not "found".
Evidence
/parts/brand/mchale/diagrams/type/<made-up> | prod | dev |
|---|---|---|
| Status | 200 | 404 |
Roll back or fail forward Roll back — one route file, nothing stored.
Brand pages — 3
A brand's banner stops changing height depending on how long its blurb is Vova on dev fix front#3419
What it is A brand's banner was as tall as its intro paragraph happened to be, so it varied by up to 23 pixels brand to brand for no reason a shopper would notice a reason for, and the two components that render it disagreed on heading size and spacing besides.
How we test it Two brands using the same layout render the same banner height regardless of blurb length.
Evidence Banner height measured today on both sites at phone width (390 × 844), read off the rendered page:
| Brand banner height at 390px | prod today | crop-dev.app |
|---|---|---|
| New Holland Agriculture | 256px | 214px |
| Kress | 233px | 214px |
| Difference between the two brands | 23px | 0px |
Same two brands, same phone size, before (still varies) and after (fix on dev):




Roll back or fail forward Roll back — styling only, nothing stored.
The brand page's first pictures now load straight away, and the site logo keeps the same address between releases so returning visitors reuse the copy they already have Vova on dev fix front#3421
What it is On the brands page the first row of brand pictures was marked as "can wait", even though it is the first thing a visitor sees, so the browser held those pictures back before starting to fetch them. They are now fetched immediately, and the browser is told about them at the very start of the page. Separately, the Clinton Tractor logo that appears on every page had a web address that changed with every release, so a returning visitor downloaded it again each time instead of reusing the copy already on their machine; the address is now fixed. Both changes are about how quickly the page appears, not about what it says.
How we test it Fetch the brands page as a visitor and count how many of the first-screen pictures are still marked "can wait", and read the logo's address to confirm it carries no release stamp.
Evidence We requested https://crop.clintontractor.net/brands and https://crop-dev.app/brands on 2026-08-06 with our audit identifier and counted the markings in the page we were served.
| What we counted | prod today | crop-dev.app |
|---|---|---|
First-screen brand tiles marked "can wait" on /brands | 2 of 2 | 0 of 2 |
| Pictures marked "can wait" on the whole page | 23 | 21 |
| Pictures the browser is told to fetch first | 1 (the banner only) | 3 (banner plus the two first-row tiles) |
| Logo address | /images/clinton-tractor-logo-sm.webp?dpl=dpl_Gu7sTvVtYeka2mzsoFRZNRFmf6PY | /images/clinton-tractor-logo-sm.webp |
| Page returned | 200 | 200 |
Roll back or fail forward Both parts are small and independent, so either can be put back on its own without affecting the rest of the page. The wording, prices and links on the brands page are untouched, so a reversal would only make the first pictures slower again.
Our own pictures are finally being shrunk before they are sent Vova on dev fix front#3459
What it is The site has a step that shrinks a picture to the size the visitor's screen actually needs. For the last 35 days that step quietly skipped two whole groups of pictures — the ones stored with the site itself, and the ones in our own four Google storage buckets, which is most of the brand and equipment photography. Those were sent at full size to every visitor, on every device. They now go through the shrinking step like everything else.
How we test it On the brands page, our own pictures are requested through the resizing address instead of straight from the storage bucket.
Evidence
Measured today with -A crop-audit on /brands, counting distinct
picture addresses in the page the server sends:
| What we counted | prod today | crop-dev.app |
|---|---|---|
| Pictures routed through the resizing step | 0 | 13 |
| Page returned | 200 | 200 |
The change's own accountability record measured the effect on the same page at 5.03 MB and 18.5 seconds to the main picture on prod, against 1.61 MB and 9.8 seconds on dev. That is a page-speed measurement, not a status code, so it is quoted from the change rather than re-measured here.
Roll back or fail forward Roll back — it is one routing rule, and reversing it only makes pictures large again. Nothing is stored and no address a customer can bookmark changes.
Pages we removed — 1
The two site-wide diagram directories are removed, and their addresses now report the page as gone Vova on dev removal front#3346
What it is
We used to have two general "all brands" diagram directories sitting outside the brand and equipment pages. On the live site those addresses still open, and some of them quietly forward somewhere else. On the candidate site they are retired: anyone opening one is told plainly that the page is gone, and nothing forwards anywhere. A saved or shared link to any of those addresses now says the page is gone and does not forward, so the visitor has to start again from the brand or equipment page. Diagrams themselves are not going away: they stay on the brand page at /parts/brand/{brand}/diagrams and on the equipment page at /equipment/{machine}/parts-diagrams.
How we test it Every retired address must answer "gone" with no forwarding address, and the two surviving diagram addresses must still open normally.
Evidence We asked each address directly on both sites today, one request per address, and wrote down exactly what came back.
| URL | prod today | crop-dev.app |
|---|---|---|
/parts-diagrams | 200 OK | 410 Gone |
/parts-diagrams/categories | 200 OK | 410 Gone |
/parts-diagrams/category/tractors-power | 200 OK | 410 Gone |
/parts-diagrams/type/tractors | 200 OK | 410 Gone |
/parts-diagrams/new-holland | 308 -> /parts/brand/new-holland-agriculture/diagrams | 410 Gone |
/parts/diagrams | 200 OK | 410 Gone |
/parts-schematics | 308 -> /parts-diagrams | 410 Gone |
/parts-schematics/new-holland | 308 -> /parts-diagrams | 410 Gone |
/parts/brand/new-holland-agriculture/diagrams | 200 OK | 200 OK |
/equipment/attachments-rotary-broom-aad86496ef/parts-diagrams | 200 OK | 200 OK |
Roll back or fail forward Undoing this means putting the directories and their forwarding rules back, which is a larger change than switching a setting. If a retired address turns out to matter, the faster answer is to add a single forwarding rule for that one address to the brand or equipment page that replaced it.
What Google reads — the part page rewrite and three sitewide changes, 7
Nothing a customer sees changes. This does not lift us in search by itself — it removes a reason to be lower, and it is what a result like a fitment table shown inside Google is built on. Google still decides whether to show one.
The change — the four things, as always Vova on dev change front#3426
- What it is
- The fitment list on every part page is now a real table, with a caption and proper column and row headings. Frequently-asked questions are written as questions and answers. The supersession chain — the older part numbers that lead to the current one — is written as an ordered sequence rather than three boxes in a row. Every section of every page now has a name, and the heading levels run in order without skipping. Five separate changes, merged over two days. Tracked as front#3426, seven commits.
- How we test it
- The page is fetched as Google fetches it and the labelled pieces are counted, before and after, on the same addresses with the same instrument. Alongside that, every page that changed is photographed at desktop and phone width, before and after, and the two are compared — because the whole point is that nothing a customer sees should move.
- The evidence
- Part page
/parts/CT-NHL-219758: 0 fitment tables before, 1 after; 12 unnamed sections before, 0 after. Full counts in the next row, photographs in the one after it. - Roll back or fail forward
- Roll back, in one button. The storefront alone changed; no data was touched, so going back restores exactly the previous page and nothing else.
The evidence — counted, not asserted Vova on dev evidence
The same part page, fetched from the live store and from the staging copy within the same minute. Every number below is a count of labelled pieces the page hands to a search engine.
| What is counted | Live store now | After the release (crop-dev.app) |
|---|---|---|
| Fitment written as a table | 0 | 1 |
| …with a caption naming it | 0 | 1 |
| …column and row headings | 0 | 6 |
| Sections with no name | 12 | 0 |
| Headings that skip a level | 8 | 0 |
| Items written as list items | 35 | 113 |
| Questions written as questions | 7 | 11 |
The six headings are worth one sentence, because it is the number that shows the table is real rather than merely present: two of them name the columns and four name the rows, against four ordinary cells — four machines, one fact each. The two remaining columns, the years a machine was built and its circuit, are left out rather than shown blank, because we do not have that data. That gap is written up separately and it is Alex's.
The same pattern holds on the other pages that changed. The store's opening hours and the figures on the About page are now written as terms and their values rather than as text; the catalogue results are a list; the diagram index is a list. Across every page checked, eight headings that skipped a level became none.
Nothing moved — which is the whole point Vova on dev evidence
Each pair is the same page: the live store on the left, the same page after the change on the right. Full length, not a crop.
Three more pages were photographed the same way, at both widths. The home page (after) and the machine page (after) are unchanged to the pixel. The About page (after) is 43 pixels taller, and that is the breadcrumb trail described further down this page, not this change — the figures band above it is identical.
The machine page is the one that nearly went unmeasured. Its specification rows are now written as terms and values rather than as text — the live store has none of those on that page, the candidate has five — and it was not in the first round of photographs at all. It was found by re-reading the list of what changed against the list of what was checked, which is the only reason it is here.
One page dropped out of this comparison entirely: the general diagram directory at
/parts-diagrams. It was photographed at 200 OK on both copies in the afternoon and was
retired to 410 Gone on the candidate an hour later, by the change described further down this page.
There is no after to compare it against, so it is not shown.
Checked by hand — the parts no test covers Vova on dev evidence
- The fitment search box
- The box that filters the fitment table by machine reaches into the page by name and had no
automated test at all. Driven by hand on both copies today, on
/parts/CT-NHL-219758:Fitment box prod today crop-dev.app Models listed, no filter 4 models 4 models Type 82C1 model, "Confirmed fit — 1 matching model below" 1 model, "Confirmed fit — 1 matching model below" Type zzzz0 models, "No match in this list. Check your serial number or ask our parts desk." 0 models, "No match in this list. Check your serial number or ask our parts desk." - The phone layout of the supersession chain
- Below a certain width the chain of older part numbers has to stack downwards and its arrow has to turn to match. That is the one piece of the rewrite that could have broken silently. It is the second pair of photographs above.
- What was not checked by an independent person
- The author of the change is also the person who verified it. For a change with no visible effect that is a smaller risk than usual, but it is worth stating rather than leaving implied.
Reproduce it: bun run scripts/semantic-census.ts — fetches both copies of the site
as a search engine would and prints the table above for every page. Has to run before Friday's
release; after that both copies are the same and there is no longer a "before" to compare against.
The site menu now arrives with the page instead of appearing a moment later Vova on dev fix front#3347
What it is Until now the page the server sent contained the logo and an empty bar where the menu should be, and the menu only filled in once the browser had finished running the page. Anyone who could not run that code — Google's crawler on a bad day, a slow phone, a visitor with scripts off — saw a header with nothing in it and no way to reach the brand pages. The server now sends the menu itself, and the search box works as a plain form even with nothing running. Weekend work.
How we test it We ask the server for a page as a robot would and count the menu links it actually contains, without letting any code run.
Evidence Fetched the same page from both sites as the crawler, and counted the links inside the header of the raw text the server returned.
| What we counted | prod today | crop-dev.app |
|---|---|---|
Links in the header of /return-policy as sent by the server | 0 links | 28 links |
| Of those, links inside the menu itself | 0 links | 19 links |
Roll back or fail forward It is a self-contained change to the header, so it can be lifted back out on its own and the site returns to today's behaviour. Nothing else depends on it.
Each page now declares one main content area instead of two Vova on dev fix front#3359
What it is Every page tells a search engine and a screen reader which part of it is the main content. Fifteen places in the site were each declaring their own, so on a number of pages two blocks both claimed to be the main one and nothing could tell which to trust. Screen reader users landed in an ambiguous page and Google had to guess what the page was about. Now there is exactly one on each page.
How we test it We count how many times a page claims a main content area in the text the server sends; the answer must be one.
Evidence Fetched each page from both sites as the crawler and counted the main-content markers literally.
| URL | prod today | crop-dev.app |
|---|---|---|
/parts | 2 main areas | 1 main area |
/contact | 2 main areas | 1 main area |
/track | 2 main areas | 1 main area |
Roll back or fail forward Nothing a customer can see changes, so removing it is safe at any time. Two automatic checks now fail if a second main area ever comes back.
The full model list moves to a clearer address and weighs half as much Vova on dev change front#3445
What it is
The page listing every machine model lived at /equipment/all and was a 4.7 MB page that Google crawled once in June, never indexed, and that earned no clicks. It now lives at /equipment/models, is half the size, is grouped by brand instead of by a letter axis that put 96% of models under two letters, and opens with its sections expanded rather than all collapsed. Every one of the model links survived the move. The old address is gone rather than redirected, because it had no traffic and nothing links to it.
How we test it The new address answers, the old one is gone, and the new page still carries the same number of model links.
Evidence Fetched both addresses on both sites as the crawler, and counted the distinct model links and the page size in the raw text returned.
| URL | prod today | crop-dev.app |
|---|---|---|
/equipment/all | 200, 8,151 model links | 404 Not Found |
/equipment/models | 404 Not Found | 200, 8,151 model links |
| Page size of the live model list | about 4.74 MB | about 2.40 MB |
Roll back or fail forward Rolling back restores the old address and the old page whole. If the smaller page still does not get indexed, the next step is splitting it into one page per brand, which the new address can host and the old one could not.
Still open, named rather than dropped: fitment years and circuit are empty on every part (two of six columns have no data behind them — Alex); the page header and footer are sent to a crawler twice (harmless to a customer, wasteful to a crawler — Mine); three automated tests on the part page pass without checking anything, because they look for pieces of the page that were renamed and, finding nothing, pass (Denis).
New — pending QA — 1
DIS charge-account checkout — bill a web order to the customer's account instead of a card Vova pending QA feature ps#559 front#3406
What it is A customer with a DIS charge account can check out against that account instead of a card. The storefront half of this landed too, so the checkout review page can offer paying on the Clinton account, but it stays completely hidden until the feature is switched on, which is John's call and has not happened anywhere. With the switch off both copies of the site read identically, which is the measurement below.
| What we counted | prod today | crop-dev.app |
|---|---|---|
| Charge-account checkout route with the flag off | 404 | 404 |
| "Clinton account" occurrences in the checkout review page | 0 | 0 |
| Denis QA walkthrough | not run | not run |
How we test it A mapped DIS customer completes checkout with the account option; an unmapped customer never sees it; the route 404s while the flag is off.
Evidence Not yet walked by anyone other than the author. This is a new customer-facing payment path — it needs Denis's QA before Thursday's call, not a claim from this page.
Roll back or fail forward To be stated once QA'd. Do not ship this row without it.
Internal — no customer-visible behavior — cherry-picks + housekeeping
Five changes are already their own fully-evidenced PRs against main, queued for
Friday ahead of the rest of this list. The fifth is the wrong-manufacturer redirect fix
(front#3422), which has its own row
at the top of this page rather than a line here. The other four:
- front#3455 — catches
main's CI baseline up with eight fixes already proven ondev; one real runtime change in the set, a checkout shipping-address field that used to lose its validation error when a customer went back to correct it. - ps#565, ps#563, ps#564 — a test-fixture date fix, then stop `payment-service`/`user-service` from silently re-creating seven MongoDB collections the PG exodus is dropping (hub#203). No customer-facing behavior.
Riding the ordinary stage→main train, no independent QA needed —
tests, CI wiring, docs and dependency bumps only:
- Two more security-advisory allowlist/bump commits (same shape as last week's).
- CI: e2e-deep harness rewrite (manifest by subtraction, sharded 4 ways), cache scoping fix, lint-on-warnings, brand-content gate error visibility, dependency-cruiser warnings to zero.
- Eleven test-spec corrections following product changes already shipped (assembly pages, brand-type page, quantity-ceiling smoke, view-in-diagram-button timeout, pickup/footer assertion, variants-route contract, e2e-stage deploy-queue wait, 5103868 fixture row count).
- Docs: env-var rotation target correction, agent provenance-block instructions, brand eager-photo comment correction.
- Governance: adopt the org AI-provenance PR/commit-trailer policy (front#3397) — separate decision, tracked at task #31, not a store-facing change.
- SEO: sitemap gate now reads live backend counts instead of fixed floors.
- Cart: the several places that counted the pieces in a cart now call one shared counter, and an insert log line that reported a number it had not checked now reports the real one (front#3338). Same numbers on screen — one place to be wrong instead of four.
- Four front collections' remaining Mongo reads finish moving onto PG (#2471) — data-layer only, no behavior change at the read path.
Everything in this release — 75 changes: 71 pull requests and 4 pushed straight to the shared branch
This is the complete list of everything that went into this release, one line per change, in three tables by the part of the site it touched. The sections above expand the ones a customer or a search engine would notice; here a change with nothing observable to show says so in its own row rather than dressing itself up as an improvement.
The storefront 51 changes 23 a customer or Google can notice
| Change | What it is | Before | After | Built by |
|---|---|---|---|---|
| front#3346 | Removes the two old cross-brand diagram directory sections and tells search engines those addresses are permanently gone. | old diagram directory addresses answered 200 or redirected | all of them answer 410 Gone | Vova |
| front#3359 | Each page now marks exactly one block as its main content instead of two. | seven pages declared two main content areas | every page declares one | Vova |
| front#3347 | The header menu and search now arrive with the page itself instead of being drawn later by the browser. | header offered 0 links without JavaScript | header offers 28 links, 20 distinct addresses | Vova |
| front#3327 | When a saved address is filled in at checkout, the missing-email warning now stays instead of disappearing. | email warning vanished from an empty email field | email warning stays until filled | Denis |
| front#3374 | Made-up addresses under a brand's diagrams tab now return not-found instead of a convincing fake page. | invented address rendered a real-looking brand page | invented address returns not found | Denis |
| front#3405 | Trims the banner and toolbar so a phone shows a product without scrolling. | first product card 848 pixels down, none visible | first card 663 pixels down, one visible | Vova |
| front#3417 | A typed address carrying another maker's part code no longer sends the shopper to a New Holland part at a different price. | another maker's address opened a New Holland part | same address returns not found | Vova |
| front#3421 | The first brand pictures load straight away, and the logo keeps one address instead of a new one every release. | 1 picture loaded early; logo address changed each release | 3 pictures load early; logo address stays fixed | Vova |
| front#3419 | All ten brand banners are now the same height on phones and on desktop. | banner height varied between 211 and 234 pixels | 214 pixels on all ten brands | Vova |
| front#3418 | The trail of links showing where a page sits now starts at Home on every page family, built from one shared source. | six page families started their trail at Parts | every trail starts at Home | Vova |
| front#3433 | Each section of a part page is now tied to its own heading, so screen readers and search engines know what it is. | 12 of 21 part-page sections had no name | every section named by its heading | Vova |
| front#3435 | The list of machines a part fits is now a real table with column headings instead of loose text. | zero tables on the part page | fitment is a table with column headings | Vova |
| front#3436 | Seven groups of repeated cards on a part page are now proper lists, so their count is announced. | seven card groups were unlabelled blocks | seven card groups are counted lists | Vova |
| front#3441 | Footer heading levels put back in order, six site-wide grids turned into lists, and one wrong attribute on the filter chips corrected. | footer skipped a heading level; grids unlabelled | heading levels in order; grids are lists | Vova |
| front#3445 | The full list of equipment models is half the size, grouped by brand instead of by letter, and lives at a new address. | 4.7 MB page at /equipment/all, letter groups | 2.40 MB at /equipment/models, brand groups | Vova |
| front#3446 | Label-and-value blocks are now paired properly, and the opening hours given to Google were corrected to match the page. | Google told Saturday opens 07:30, page said 08:00 | both say 08:00 | Vova |
| front#3427 | Each address now carries a single name and a single parent in its trail, instead of two different stories. | parts page had two names, brands page two parents | one name and one parent per address | Vova |
| front#3437 | Ten pages that built their own trail now use the shared one, so separators are no longer read aloud as "slash". | ten pages hand-built trails, four different qualities | all ten use the shared trail | Vova |
| front#3449 | Trail steps that have no page of their own stay on screen but are removed from the data handed to Google. | trail data included steps with no address | those steps removed, numbering closed up | Vova |
| front#3453 | The brand diagrams tab now reports to Google the same trail it shows on screen. | shown trail and reported trail disagreed | both read Home, Brands, brand | Vova |
| front#3456 | Eight information pages gained a trail, and two list pages stopped linking their last step to themselves. | 8 indexed pages showed no trail at all | all 8 show Home then the page name | Vova |
| front#3459 | Our own pictures are now resized and compressed before delivery instead of being sent at full size. | brands page 6,616 KB, main image at 13.5 seconds | 3,165 KB, main image at 7.6 seconds | Vova |
| front#3470 | Not-found pages no longer tell Google they occupy a place in the site structure. | 10 error pages sent a trail to Google | none do | Vova |
Nothing a customer or a search engine can see 28
| Change | What it is | Before | After | Built by |
|---|---|---|---|---|
| front#3338 | Tidy-up of the shared-cart code after review, with no change to what a shopper sees. | same item-count sum copied in three places | one shared helper, 20 fewer lines | Vova |
| front#3365 | Records and accepts two security warnings that have no fix available yet, so the build check stops blocking everyone. | security check failed on every branch | security check passes, two warnings recorded | Vova |
| front#3362 | Corrects which build machines are allowed to save and reuse their working files. | machines picked by operating system, one wrong | machines picked by name, all correct | Vova |
| front#3375 | The deepest automated test run now runs only the tests it owns, split four ways to finish in time. | lane ran 106 tests, never once succeeded | lane runs 51 tests, split four ways | Vova |
| front#3386 | Code-style warnings now stop a change from merging instead of being ignored. | style warnings passed the check | style warnings fail the check | Vova |
| front#3387 | Copies the last four leftover sets of records from the old database into the new one. | four record sets missing from the new database | 36 records copied across | Vova |
| front#3319 | A pickup-promise test was reading the store-hours widget, so it passed or failed by the time of day. | test result changed with store opening hours | test reads only the page content | Denis |
| front#3320 | Gives one test step the same waiting time as the steps after it, so it stops failing at random. | step allowed 1000 milliseconds, failed randomly | step allowed 1500 milliseconds, five green runs | Denis |
| front#3377 | Updates three outdated test expectations on the brand equipment-type page; no customer defect was involved. | 3 tests failing, 9 failures a night | 3 passed, 2 skipped | Denis |
| front#3357 | Adds a test proving an order above the allowed quantity never reaches payment. | no test covered the order quantity limit | one test proves over-limit orders are refused | Denis |
| front#3355 | A nightly check that finds broken brand pages can now report them, and prints every failure rather than the first ten. | 15 failures found, 10 printed, nobody told | all failures printed, a ticket is filed | Denis |
| front#3382 | Updates diagram-page tests to match today's product and leaves one genuine defect visible on purpose. | 8 passed, 5 failed | 12 passed, 1 failed | Denis |
| front#3391 | A test file now runs in one place so its safety check stops raising a false alarm. | test failed depending on how work was split | test runs in order, check still intact | Vova |
| front#3383 | Fixes five stale test expectations on the model-variants page and closes a mismatch that no live page could reach. | 3 passed, 5 failed on the variants page | 8 passed | Denis |
| front#3315 | The staging test run now waits long enough for its own build to get its turn in the queue. | gave up after 15 minutes, ran no tests | waits up to 40 minutes | Vova |
| front#3393 | A search test now checks for at least the expected results instead of an exact count that the live catalog keeps changing. | test demanded exactly 2 results, catalog returned 3 | test demands at least 2 | Vova |
| front#3415 | Corrects a note that named the wrong service for a shared setting. | note named the retired search service | note names the live search service | Vova |
| front#3406 | Builds the customer side of paying by charging a Clinton account, switched off everywhere for now. | no charge-to-account option existed | option built, switched off, page unchanged | Vova |
| front#3398 | Every change must now name which assistant was used and which person is answerable for it. | no responsible name required on a change | change blocked until both names are filled | John |
| front#3425 | Adds the instruction so assistant-opened changes fill in the newly required names. | assistant changes opened without the required names | the written flow spells the two lines out | Vova |
| front#3440 | The nightly broken-link sweep now sees genuine not-found pages and no longer throws away filtered addresses. | sweep saw 200 on real not-found pages | sweep sees 404 and keeps filtered addresses | Vova |
| front#3454 | Clears the last eight warnings about how files reference each other. | 8 warnings | 0 warnings | Vova |
| front#3457 | Every code change must now state what it was, what it became, how to check it, and show the proof. | evidence optional unless bound for production | evidence required on every code change | Vova |
| front#3458 | The trail checker now covers every page template automatically and runs on every change instead of nowhere. | checker covered 6 listed pages, ran nowhere | covers 37 templates, runs on every change | Vova |
| front#2994 no pull request, pushed straight to the shared branch | The morning sitemap check now compares the published address count against the live backend count instead of two fixed numbers that could no longer be reached. | check failed every morning, 16 repeat reports | 2,694 against 2,694, zero drift | Vova |
| front#2992 no pull request, pushed straight to the shared branch | Deletes a test that could never fail and stops other tests calling the retired search backend when no address is set. | retired backend took about 20 requests each morning | no scheduled run calls it | Vova |
| front#2992 no pull request, pushed straight to the shared branch | Removes the retired search backend from the tracing list and two helper scripts. | three places still named the retired backend | none do | Vova |
| front#3420 no pull request, pushed straight to the shared branch | Corrects a note in the brand tile code that stated the opposite of what was measured about early image loading. | note said early loading adds no preload | note says it does add one | Vova |
The order and payment services 16 changes none a customer or Google can notice
| Change | What it is | Before | After | Built by |
|---|---|---|---|---|
| ps#528 | Deleted twenty-two internal write-ups that described setups we no longer run. | 22 out-of-date internal documents kept on file | 0 out-of-date internal documents kept on file | Vova |
| ps#536 | Anything going to production must now answer John's four questions in writing first. | no written detail, testing, evidence or rollback required | all four required before a production change | Vova |
| ps#535 | The test copy of checkout now looks up parts from the current parts service instead of a retired one. | test checkout asked a retired parts service | test checkout asks the current parts service | Vova |
| ps#538 | Denis and Vova become eligible to open the staff order screens on the test site, so Denis can do his sign-off. | 1 of 8 test accounts could open staff screens | 2 more eligible; the switch-on step still unrun | Vova |
| ps#544 | Corrected three internal notes that claimed the test data sat on its own separate server when it does not. | three notes described a setup that does not exist | three notes match the real setup | Vova |
| ps#539 | The shipping-quote service can now run on a test copy, so fixes can be checked before customers see them. | shipping quotes ran only in production | shipping quotes also run on a test copy | Vova |
| ps#551 | An automated check held a fixed calendar date that went out of date, turning the whole test run red; it now uses today's date. | 233 checks pass, 1 fails | 234 checks pass, 0 fail | Vova |
| ps#549 | Payment stopped rebuilding seven old storage areas we are retiring, so deleting them will actually stick. | seven retired storage areas returned on every restart | none return on restart, on the test line | Vova |
| ps#552 | The accounts service stopped rebuilding one more retired storage area on every restart. | one retired storage area returned on every restart | it stays gone on restart, on the test line | Vova |
| ps#554 | Code-tidiness warnings now stop the automated checks instead of passing quietly. | warnings passed the check silently | warnings fail the check; zero warnings today | Vova |
| ps#557 | Builds ordering with no card for customers who hold a Clinton charge account; it is inert because the switch is off in production. | no card-free ordering existed anywhere | built and switched off in production | Vova |
| ps#558 | With the switch off, the card-free ordering address gave away that it existed and what it wanted; now it simply says not found. | replies with an error listing required fields | replies not found | Vova |
| ps#559 | Card-free orders now empty the basket, and clicking order twice returns the first order instead of placing a second; still inert behind the off switch. | basket stayed full; a second click made a second order | basket empties; a second click returns the first order | Vova |
| ps#565 | Carries the out-of-date test fix onto the production line; queued for Friday and must land before the other two. | 233 checks pass, 1 fails on the production line | 234 pass, 0 fail once Friday's release lands | Vova |
| ps#563 | Carries the payment fix onto the production line so the seven retired storage areas stop coming back; queued for Friday. | seven retired storage areas return on each production restart | none return, once Friday's release lands | Vova |
| ps#564 | Carries the accounts-service fix onto the production line for the last retired storage area; queued for Friday. | one retired storage area returns on each production restart | it stays gone, once Friday's release lands | Vova |
The search service 8 changes 4 a customer or Google can notice
| Change | What it is | Before | After | Built by |
|---|---|---|---|---|
| search#861 | When the parts list is too slow to load a deep page, that page used to come back empty while still claiming everything was fine; now it reports that it is temporarily unavailable so it can be retried. The matching storefront change is still to come. | Deep list page showed no parts, reported success | Deep list page reports temporary unavailability instead | Vova |
| search#860 | The maker filters on the parts list promised far more parts than clicking them delivered, and the out-of-stock filter appeared twice; both now match what the list actually shows. | One maker filter said 22,466 parts, list showed 6,268 | Same filter says 6,268, matching the list exactly | Vova |
| search#858 | Search results for many makers linked to a page that did not exist, or worse, to a different maker's part at a different price; five of those makers now link correctly and the rest are kept out of results entirely. | 47 of 66 makers linked nowhere or wrong part | Five makers link correctly, the rest hidden from search | Vova |
| search#843 | Every search on the storefront was only one page deep, so page two came back as not found even though page one advertised dozens of pages; already reported on the 2026-07-31 release page. | Page two of any search returned not found | Page two onward returns results, all pages reachable | Vova |
Nothing a customer or a search engine can see 4
| Change | What it is | Before | After | Built by |
|---|---|---|---|---|
| search#857 | A shared security key had a weaker length requirement on the search side than on the website side, so a key that looked accepted could still stop the website from starting; both sides now demand the same length. | Short key accepted by search, crashed the website | Short key rejected by both, same minimum length | Vova |
| search#854 | Sorting search results by best sellers repeated some parts across pages and hid others; the correction is written down but only takes effect once Alex applies the matching database change, which has not happened. | No change until Alex applies the database change | No change until Alex applies the database change | Vova |
| search#853 | The automatic checks that guard every release were failing on out-of-date expectations rather than real problems, and the clean-up step meant to remove a rejected build had never once worked, leaving old builds publicly reachable. | Release checks stuck; rejected builds stayed publicly reachable | Checks pass; a rejected build is now deleted | Vova |
| search#849 | The code-quality check was reporting warnings but still passing, so nine of them sat unnoticed, including one that made a test pass when it should not have; the warnings are cleared and the check now stops on any new one. | Nine warnings present, quality check passed anyway | Zero warnings, check now fails on any warning | Vova |
What v2.1.0 is — the exact thing to go back to
Read off the live systems on Saturday 8 August, after the release went out, not copied from the plan. The storefront and search both moved; services moved later the same day for a separate fix.
| Storefront | 703a02de | Changed from ebd97bee. The
promote merge, built and serving crop.clintontractor.net. Vercel keeps the previous
build, so going back is one button. |
|---|---|---|
| Search | search-api-00015-vcm | Changed from
search-api-00017-zuy. Deployed 7 August, carrying 100% of traffic. The number is
lower than the one it replaced because these are rebuilt rather than counted up — it is the
newer of the two. |
| Services | 58a42db9 | Changed from 4b96c314. Live
three minutes after it was merged, on the evening of 7 August — a payment fix, not part of this
release. |
| Database | 20260805213545 | The last migration recorded in the backend change list of 6 August. Unlike the three rows above, this one was not re-read from the live database — it is Alex's lane and the record is his. |