jonah's recent activity

  1. Comment on AI usage patterns in software teams in ~tech

    jonah
    Link
    We've been doing this for a while at my current job. Importantly, we are reading and editing our cards before marking them as "Ready" though I see the time spent on this to be decreasing. I think...

    Two years ago, fewer than one issue in a thousand was created by AI. Teams now use AI to write just under half of everything created in Linear, and at the current pace it will soon author more than people and integrations combined.

    We've been doing this for a while at my current job. Importantly, we are reading and editing our cards before marking them as "Ready" though I see the time spent on this to be decreasing. I think something Sean Goedecke mentioned recently is playing a part here.

    It does occasionally worry me that more and more of the "card lifetime" is being handled by LLMs. For us, it seems like there's a great deal of care that goes into triaging an issue or a feature (still LLM-assisted). I mentioned this a few months ago in another thread. That still holds true. Since then, the bias towards the LLM almost owning the process of development and review (and these days, significantly assisting me in my testing, usually through harnesses and I/O validation) has continued to dominate. There's not a single part of my workflow where I'm not using an LLM to do something. I think I still have mixed feelings about that.

    On one hand, it's nice that LLM models are getting to the point where a trivial, bit-sized piece of work is almost entirely automated where my role is essentially guiding it to completion. I have personally found it to be an excellent and efficient tool for performing a guided task. On the other hand, I used to spend a lot more time actually writing code. Sometimes I would even enjoy the process. Other times, if I didn't, I would at least feel like I had ownership of it. That is less so the case these days.

    For my personal projects, I get to enjoy the best of both worlds. At work, the cost-benefit of using LLM models is that we're able to move quickly. I can slow down for my personal projects and actually write the code that is enjoyable to write. I can let an LLM do the parts I would usually anguish over with very little gained at the end. I have much more fun coding on personal projects these days than I did pre-LLM. I can basically set my own difficulty level now.

    Just got to the end of writing this and realized it was more than I expected to write, so if you made it this far, thank you for participating in my train of thought. Every so often I like to hear how others in the industry feel about the current state of their jobs with respect to LLMs. My feeling as of writing this is... bittersweet. Usually I'm a little more excited about it LOL

    8 votes
  2. Comment on Why your Amazon order confirmation emails have become so unhelpful in ~tech

    jonah
    Link Parent
    Even with LLM assisted coding, I would hate having to waste usage or tokens (and time) every week just trying to fix a scraping script. Not to mention what you already did, which is the...

    Even with LLM assisted coding, I would hate having to waste usage or tokens (and time) every week just trying to fix a scraping script. Not to mention what you already did, which is the anti-scraping tools out there.

  3. Comment on Why your Amazon order confirmation emails have become so unhelpful in ~tech

    jonah
    Link Parent
    I don't think there is such an API, or at least one that's generally available. I would love to be wrong

    I don't think there is such an API, or at least one that's generally available. I would love to be wrong

    8 votes
  4. Comment on Why your Amazon order confirmation emails have become so unhelpful in ~tech

    jonah
    Link
    This has been particularly frustrating for me because I just wrote a nightly script to help me identify Amazon charges in YNAB and I was using the order confirmation emails to do that. I swear...

    This has been particularly frustrating for me because I just wrote a nightly script to help me identify Amazon charges in YNAB and I was using the order confirmation emails to do that. I swear like two days into the script working perfectly they stopped including product details.

    30 votes
  5. Comment on Firefox for iOS now has a native adblocker in ~tech

    jonah
    Link
    Unfortunately it appears as though the feature has not rolled out to my device yet but to see if I had it, I downloaded Firefox and I’m pretty impressed with how pleasant the experience is. I...

    Unfortunately it appears as though the feature has not rolled out to my device yet but to see if I had it, I downloaded Firefox and I’m pretty impressed with how pleasant the experience is. I don’t recall the reason for just going back to Safari on my phone but I think I’ll stick with Firefox going forward. Native search engine customization means I can use Kagi without a weird extension. And upcoming built-in ad-block will let me get rid of another one.

    I’m a big Firefox guy on all my computers. I really wish I remembered the reason I switched. Probably to try Orion and then ended up back on Safari.

    Thanks for the reminder to try Firefox again!

    3 votes
  6. Comment on I'm not ready to let this place go in ~tildes

    jonah
    Link
    Not to be a downer, and I’m mostly a lurker, but I didn’t get the impression at all that Tildes is anywhere near closing its doors. I don’t understand everyone else speaking about the most recent...

    Not to be a downer, and I’m mostly a lurker, but I didn’t get the impression at all that Tildes is anywhere near closing its doors. I don’t understand everyone else speaking about the most recent meta-conversations as foreshadowing the site shutting down. As far as I can tell, some folks are frustrated with some of the discourse recently (or maybe more than recently) and are publicly announcing their leaving because some aspects of the site are not to their liking in terms of moderation style. That’s certainly within their right. But it’s been a little more than topical, and I think Deimos just wanted to go on record and say nothing's going to change. It didn’t feel like he was announcing the end of the site. Yeah, if this place ends up going under I’ll miss it. I’m certainly not as involved as many of you, so it’s not the same for me, I acknowledge that. But I don’t personally understand these existential responses.

    26 votes
  7. Comment on Actually useful MCPs in ~comp

    jonah
    Link
    For anyone out there using Linear for project management, me and my team have found their MCP integration incredibly useful. When tasks are small and well defined, Claude can generally do a B+...

    For anyone out there using Linear for project management, me and my team have found their MCP integration incredibly useful. When tasks are small and well defined, Claude can generally do a B+ implementation with no other context than “read this linear issue and get to work.” Of course, YMMV, and I’d imagine it depends a lot on how heavily your team uses Linear day-to-day.

    1 vote
  8. Comment on Megathread: April Fools' Day 2026 on the internet in ~talk

    jonah
    Link Parent
    They've included a query parameter for those who would like to disable it, so maybe they'll leave that in for those who would like to keep it around after today... Maybe try kagi.com?fun=yes tomorrow!

    They've included a query parameter for those who would like to disable it, so maybe they'll leave that in for those who would like to keep it around after today... Maybe try kagi.com?fun=yes tomorrow!

    4 votes
  9. Comment on Megathread: April Fools' Day 2026 on the internet in ~talk

    jonah
    Link
    The Kagi search page has a fun retro look to it. My favorite is the viewer count at the bottom!

    The Kagi search page has a fun retro look to it. My favorite is the viewer count at the bottom!

    12 votes
  10. Comment on YouTube is awful. Please use YouTube, though. in ~tech

    jonah
    Link Parent
    That’s not really how music streaming works with respect to the hosting / delivery. Each service both hosts and delivers the content. It’s just that most people will have their content uploaded to...

    That’s not really how music streaming works with respect to the hosting / delivery. Each service both hosts and delivers the content. It’s just that most people will have their content uploaded to each of those services because those services are already popular and it would be bad for the artist not to upload their music there. And to my knowledge, most artists aren’t uploading to streaming services for monetary reasons, rather for discovery and conversions to concerts and merchandise. To make it analogous to music streaming, you could (and some already) do this by just uploading all your same content across various video hosting platforms. The reason I don’t think a lot of people do this is because it’s largely pointless in that Vimeo, Floatplane, etc have so little of the video content market share. There’s also a large difference in audience interaction between these platforms as most video platforms are social in some way whereas most music platforms are not. You’ve also got the problem of video being exponentially more challenging to host and deliver as opposed to audio.

    I get what you’re saying in terms of your ideal situation for how video platforms should function, but music absolutely does not function like this already. And if it did, I still don’t think these platforms are nearly similar enough to compare them with respect to feasibility.

    3 votes
  11. Comment on Five browser extensions to make every website more useful in ~tech

    jonah
    Link Parent
    Because Kagi requires login, you’d have to log in each time you want to use it in a private window. Not having to do that is very convenient. Kagi also doesn’t maintain your search history, so...

    Because Kagi requires login, you’d have to log in each time you want to use it in a private window. Not having to do that is very convenient. Kagi also doesn’t maintain your search history, so it’s not like my “private window” searches will appear in my account, because none of my searches do.

    5 votes
  12. Comment on Day 4: Printing Department in ~comp.advent_of_code

    jonah
    Link
    Python Standard brute-force method of solving both of these and didn't take too long on my machine (sub 1s for both) so I'm happy enough to share my solution. I'm used to there being some kind of...

    Python

    Standard brute-force method of solving both of these and didn't take too long on my machine (sub 1s for both) so I'm happy enough to share my solution. I'm used to there being some kind of edge case that my test input didn't capture, but it was pretty straight forward today and I didn't end up running into any of those problems.

    I'm also going to remove my utility grid_at method because... well you can imagine how that's implemented and it's just noise in the code (and I did not save any grid utilities from last year...)

    Part 1
    from common import load_input
    input = load_input()
    
    # def grid_at(grid, x, y)
    
    relative = [
        (-1, -1), (0, -1), (1, -1),
        (-1, 0),           (1, 0),
        (-1, 1),  (0, 1),  (1, 1),
    ]
    
    grid = list(map(lambda x: list(x), input.splitlines()))
    w, h = len(grid[0]), len(grid)
    
    total = 0
    for y in range(h):
        for x in range(w):
            if grid_at(grid, x, y) != '@':
                continue
            res = list(map(lambda d: grid_at(grid, x + d[0], y + d[1]), relative))
            if res.count('@') < 4:
                total += 1
    
    print(total)
    
    Part 2
    from common import load_input
    input = load_input()
    
    # def grid_at(grid, x, y)
    
    relative = [
        (-1, -1), (0, -1), (1, -1),
        (-1, 0),           (1, 0),
        (-1, 1),  (0, 1),  (1, 1),
    ]
    
    grid = list(map(lambda x: list(x), input.splitlines()))
    w, h = len(grid[0]), len(grid)
    
    total = 0
    
    while True:
        to_remove = []
        local_total = 0
        for y in range(h):
            for x in range(w):
                if grid_at(grid, x, y) != '@':
                    continue
                res = list(map(lambda d: grid_at(grid, x + d[0], y + d[1]), relative))
                if res.count('@') < 4:
                    to_remove.append((x, y))
                    local_total += 1
        if local_total == 0:
            break
        total += local_total
        for (x, y) in to_remove:
            grid[y][x] = '.'
    
    print(total)
    
    1 vote
  13. Comment on Day 3: Lobby in ~comp.advent_of_code

    jonah
    Link
    Python I almost gave up. I did not write my part 1 to be generalized for the second part, but when I figured out how to generalize it, I was able to keep the same efficiency as part 1. On my...

    Python

    I almost gave up. I did not write my part 1 to be generalized for the second part, but when I figured out how to generalize it, I was able to keep the same efficiency as part 1. On my machine, my benchmark times (thank you hyperfine) were 8.4ms and 9.4ms respectively.

    Part 1
    from common import load_input
    input = load_input()
    
    def find_largest(batteries: [int], start_index: int, chop: int) -> int:
        largest = -1
        largest_index = -1
        for i in range(start_index, len(batteries) - chop):
            if batteries[i] > largest:
                largest = batteries[i]
                largest_index = i
        return largest_index
    
    total = 0
    banks = input.split('\n')
    for bank in banks:
        batteries = list(map(int, list(bank)))
        a = find_largest(batteries, 0, 1)
        b = find_largest(batteries, a + 1, 0)
        total += (batteries[a] * 10) + batteries[b]
    
    print(total)
    
    Part 2
    from common import load_input
    input = load_input()
    
    def find_largest(batteries: [int], start_index: int, chop: int) -> int:
        largest = -1
        largest_index = -1
        for i in range(start_index, len(batteries) - chop):
            if batteries[i] > largest:
                largest = batteries[i]
                largest_index = i
        return largest_index
    
    total = 0
    banks = input.split('\n')
    for bank in banks:
        batteries = list(map(int, list(bank)))
    
        allowed = 12
        last_index = 0
        for i in range(allowed):
            n = find_largest(batteries, last_index, (allowed - i - 1))
            power = pow(10, (allowed - i - 1))
            total += batteries[n] * (1 if power == 0 else power)
            last_index = n + 1
    
    print(total)
    
    1 vote
  14. Comment on Day 2: Gift Shop in ~comp.advent_of_code

    jonah
    Link Parent
    You're welcome! good luck and have fun

    You're welcome! good luck and have fun

    1 vote
  15. Comment on Day 2: Gift Shop in ~comp.advent_of_code

    jonah
    Link Parent
    Because in those numbers, the repeated digits are repeated more than twice

    Because in those numbers, the repeated digits are repeated more than twice

    2 votes
  16. Comment on Day 2: Gift Shop in ~comp.advent_of_code

    jonah
    Link
    I didn't post yesterday because I was annoyed at how long it took me. I was much happier today. My part 1 took very little time to write and executed pretty quickly, but part 2 took a little...

    I didn't post yesterday because I was annoyed at how long it took me. I was much happier today. My part 1 took very little time to write and executed pretty quickly, but part 2 took a little longer. On my machine I averaged about 1.2s. I decided to plug in some threading (not included here) to see if I could get it faster, and got it down to ~230ms. That was a cool win for today!

    Part 1
    from common import load_input
    input = load_input()
    
    # There's gotta be a better way to do this
    def id_is_invalid(prod_id: int) -> bool:
        str_id = str(prod_id)
        if len(str_id) % 2 != 0:
            return False
        mid = int(len(str_id) / 2)
        first, last = str_id[:mid], str_id[mid:]
        return first == last
    
    # Gross, but it works
    ranges = list(map(lambda x: list(map(lambda y: int(y), x.split('-'))), input.split(',')))
    counter = 0
    
    # Dumb solution but it works
    for r in ranges:
        for prod_id in range(r[0], r[1] + 1):
            if id_is_invalid(prod_id):
                counter += prod_id
    
    print(counter)
    
    Part 2
    from common import load_input
    input = load_input()
    
    def has_pattern_count(s, m, k):
        if s.count(s[:m]) >= k:
            return True
        return False
    
    def id_is_invalid(prod_id: int) -> bool:
        # Single digit IDs can't possibly match the criteria
        # And yes, this got me
        if prod_id < 10:
            return False
    
        str_id = str(prod_id)
        str_len = len(str_id)
    
        # m -> pattern length
        # k -> number of repetitions
        # m * k should always equal str_len
        # i.e., str_len / m should always be a whole number, and the result is k
    
        m = 1
        while m < (str_len / 2) + 1:
            if str_len % m == 0:
                k = str_len / m
                if has_pattern_count(str_id, m, k):
                    return True
            m += 1
    
        return False
    
    # Gross, but it works
    ranges = list(map(lambda x: list(map(lambda y: int(y), x.split('-'))), input.split(',')))
    counter = 0
    
    # Dumb solution but it works
    for r in ranges:
        print("Processing range:", r)
        for prod_id in range(r[0], r[1] + 1):
            if id_is_invalid(prod_id):
                counter += prod_id
    
    print(counter)
    
    2 votes
  17. Comment on Netflix kills casting from phones in ~tech

    jonah
    (edited )
    Link Parent
    If you have an old-ish PC lying around, you can get a cheaper NAS without all the bells and whistles. I have an older desktop powering my Jellyfin setup and it works pretty well. I got a Ubiquiti...

    If you have an old-ish PC lying around, you can get a cheaper NAS without all the bells and whistles. I have an older desktop powering my Jellyfin setup and it works pretty well. I got a Ubiquiti NAS and I’ve been thrilled with it. I wanted something that was actually… network attached storage and not another fully fledged computer setup built for media transcoding and all that. If you already have some hardware lying around it doesn’t have to be super expensive to self host.

    Edit: I also missed your point about fixing stuff that doesn’t work. That used to be me too, so I get it. Once I dockerized everything, the time I’ve spent managing my stuff has approached zero. Managing that stuff is not for everyone. Sometimes it’s easier to have someone else worry about it

    7 votes
  18. Comment on I think nobody wants AI in Firefox, Mozilla in ~tech

    jonah
    Link Parent
    Quick answers are enabled by default insofar as your search will prompt a quick answer if it ends in a question mark. Given that most people do not literally type questions into their search...

    Quick answers are enabled by default insofar as your search will prompt a quick answer if it ends in a question mark. Given that most people do not literally type questions into their search engine (and also ending it in a question mark) I would not consider this to be an AI feature that is enabled by default the same way that Google’s quick answers is. It’s also very easy to disable if you would in fact like to write your search query in the form of a question.

    I read your other comment about wanting to use products that are 100% AI free, so I’ll just concede that Kagi does in fact develop many AI features and if that’s a problem for you then I won’t try and convince you otherwise. I was instead trying to argue against the implied characterization of Kagi that they are chasing trends which I think is obviously false based on their history and their AI philosophy. Perhaps you disagree! Either way I appreciate the discussion.

    4 votes
  19. Comment on I think nobody wants AI in Firefox, Mozilla in ~tech

    jonah
    Link Parent
    Kagi started out focused on AI technology in 2018. Their AI philosophy is also to create integrations that are opt-in and ostensibly provide some value. I don’t personally feel as though they are...

    Kagi started out focused on AI technology in 2018. Their AI philosophy is also to create integrations that are opt-in and ostensibly provide some value. I don’t personally feel as though they are “shoving AI features everywhere” and I think to say as much implies they are chasing trends or adding AI for the sake of having AI in their product. You may not find any value in their AI features which is understandable. I don’t really find much value in them either. But I’ve also never had the feeling that they’ve been shoving them into their main product.

    4 votes
  20. Comment on Experiences with united healthcare in ~health

    jonah
    (edited )
    Link
    We’re on a PPO plan and In my experience they’ve been good. We had a baby while covered by UHC and my wife has a health concern that would be very expensive to treat without coverage. Granted, we...

    We’re on a PPO plan and In my experience they’ve been good. We had a baby while covered by UHC and my wife has a health concern that would be very expensive to treat without coverage. Granted, we live in an area with a lot of health care options, but we’ve basically been able to go wherever we want, be in network, and have not yet had to fight any claims.

    The only issue we had was them not wanting to give us a non-standard refill window on new-ish name brand speciality medication. And I’m not convinced another insurance provider would’ve done so either. They also barely paid anything for our medications before our deductible was hit. You mentioned not being worried about prescriptions, but wanted to mention for others reading the thread.

    In any case, it’s been pretty much the same compared to my last job with insurance through BCBS.

    YMMV

    6 votes