Add a fourth case where the symptom is misleading: the error surfaces in service A and the cause is a config change in service C. A model that "stays focused" and a model that anchors on the first plausible story are indistinguishable on easy bugs and completely different on that one. That case is the whole reason you are testing.
Petra Lindqvist
@petra_lindqvist
I do compensation benchmarking for a living. Salary bands are less scientific than you think and more negotiable than HR implies.
84 credit Contributor
- From answers
- 0
- From questions
- 84
Hold constant: same repo commit, same starting context, same prompt file read from disk rather than retyped, same tools available, same reasoning setting. Vary exactly one thing.
Run each task twice per model. Run-to-run variance on the same model is bigger than most people expect, and if you do not measure it you will attribute your own noise to the model.
Record per run: wall-clock, total tokens, number of tool calls, and one binary outcome, "did the diff pass the tests that existed before the run". The binary is what makes the whole thing comparable later. Everything else is diagnostic colour.
The specific danger in extraction pipelines is not wrong answers, it is emptier answers. A cheaper model tends to leave optional fields null rather than infer them, on some small percentage of rows, and every row still validates.
So before you switch, add two per-batch metrics: null rate per field, and schema-validity rate. Record a fortnight of baseline on your current tier. Then a downgrade that costs you 3% of a field shows up as a number the day it happens rather than as a support ticket in six weeks. Cheap to build, and it pays for itself the first time a model changes underneath you without a version bump.
The genuinely different option is self-hosting. Free, open source, envelope-style, runs on a cheap box or just locally, and you're not exposed to a shutdown or a price rise ever again. The cost is that you are now the sysadmin, and if that doesn't appeal it's a terrible trade.
For next time - turbo run build --verbosity=2 prints the hash for each task as it computes it, so you can see which task diverges first. If the global hash is stable and only one package misses, the answer is in that package's inputs rather than the environment.
So the acrylamide half isn't about the appliance at all. That reframes the video considerably.
Our split for what it's worth, ~2,900 failed invoices over a year: insufficient_funds 41%, do_not_honor 23%, expired_card 19%, lost/stolen 6%, everything else the rest. The do_not_honor bucket was the one where a different card actually solved it about a third of the time.
Video walkaround, narrated, including the roof and the windscreen. Takes ninety seconds and saved me a windscreen charge in Italy.
Worth noting the failure mode differs between the two systems in a way that matters. The old one over-invalidated - you got redraws you did not need, so the bug was performance. The new one under-invalidates if you get it wrong, so the bug is stale UI. Stale UI is much harder to notice in testing and much worse when a user finds it.
No - @Published belongs to the Combine ObservableObject world and does nothing here. It requires conformance to ObservableObject, and mixing that with the macro is exactly the halfway state that produces the bug in the post. The two systems are alternatives, not layers.
Second rule that catches people right after the first one: the read has to happen inside body.
Tracking is registered at the moment the property is accessed during the body evaluation. So:
- reading it in
initand storing it in alet- not tracked, you captured a value once - computing it in a helper method called from body - tracked, because the access still happens during body
- reading it inside a closure that runs later, like a button action - not tracked, it runs outside the evaluation
That last one is fine and correct, but people get confused when a value they "use" in the view does not cause updates. Using it in a callback is not reading it in body.
One thing that is genuinely normal and rarely said: some products are legitimately seasonal or project-shaped. If your tool helps with a thing people do for six weeks and then stop, churn is not a defect, it is the shape of the demand, and the fix is pricing that matches it rather than a monthly subscription that pretends otherwise.
"Codable from day one" is exactly the kind of thing I would have skipped and paid for. Ids only makes obvious sense once you say it out loud.
"Biome for format immediately, decide about lint separately" is a much better framing than the all-or-nothing one I had in my head. The format change alone is a no-brainer.
Go today, and not via a pricing page: an individual message to each of them. Pricing page is for strangers, later.
It hadn't occurred to me to actually plot it. Doing that this weekend.
Useful at work too. 'I will be at reduced capacity tomorrow' lands much better than disappearing for two days with no framing.
Realistically five to ten years of decent storage for a meaningful change, and a young sheng you dislike now is not guaranteed to become one you like later. Age changes character, it does not fix material.
That said, a lot of what you describe is brewing. Young sheng punishes long steeps and full boiling water far more than shou does. Try 5g in 120ml, water rested a minute off the boil, flash steeps of about five seconds. It is a completely different tea brewed gently.
The hollow feeling before lunch is worth taking seriously - young sheng on an empty stomach does that to a lot of people, including me. Eat something first. If it still does it afterwards, this is not your category and there is no shame in that.
60x60 on screen is not 60x60 in memory. That is the whole problem.
AsyncImage does no caching beyond the URL loading system's default behaviour, which means as rows recycle it re-requests, re-decodes and re-downsamples the same images repeatedly. A 1200x1200 JPEG decoded to a bitmap is somewhere around 5.7MB of memory regardless of the frame you draw it in, and the decode itself is the expensive part - it happens on a scroll frame, and it blows your budget.
What to do:
- Downsample at decode time, not with
.resizable(). Use ImageIO withkCGImageSourceThumbnailMaxPixelSizeset to your display size in pixels, andkCGImageSourceCreateThumbnailFromImageAlways. You get a small bitmap out and never materialise the full one. - Cache the decoded result, keyed by url plus target size, in an NSCache. The second appearance of a row should be a dictionary lookup.
- Do it off the main thread and hand the finished image back.
Either adopt a library that does all three or write about 60 lines. Both are fine. What is not fine is AsyncImage in a long scrolling list - it is a convenience for a detail screen, not a feed component.
2,000 rows is not your problem. 2,000 full-size decodes is.
List already is a reusing collection view underneath. The OP's problem was image decoding, which a UIKit rewrite does not solve either - you would be writing the same downsampling code, just with more boilerplate around it. Bridging is a real tool for genuinely custom layouts, not a general answer to "this scrolls badly".
Shuffle the order once and see what happens. If your accuracy drops from 92 to 60 when the cards are not in lecture order, you have your answer for free.
Whatever else you do, do not drive. Obvious, but the temptation to get home first is real and the visual field is genuinely compromised.
Also worth budgeting for the fact that a Swift-weak dev writing SwiftUI for four months is a Swift-competent dev at the end of it. If the company survives, that capability compounds. Shared UI defers that learning indefinitely, and there is a version of this where that is fine and a version where it quietly becomes a risk.
Contrarian take on the constraint itself: with four months and two people, consider shipping one platform.
Pick whichever has your users, ship it properly, get paying customers, and then decide about the second with revenue and real feedback instead of a guess. Half of the second platform's design decisions will change once you have watched people use the first one.
Two mediocre apps in four months is a worse outcome than one good one, and the cross-platform question resolves itself once you know what you are actually building.
Subdecks are fine organisationally, they just do not do what you think. Use tags instead - same filtering power, no scheduling weirdness, and you can tag a card two ways.