Showing posts with label HumansAndTechnology. Show all posts
Showing posts with label HumansAndTechnology. Show all posts

2026-10-11

Maybe you should think before you do that...

I asked an LLM1 a coding question the other day and it told me it would be a "best practice" to design my C++ API to expose undefined behavior.

Just let that sink in for a minute if you're a C or C++ programmer. If you're not such a programmer just take my word that it is hard to image less sensible or responsible advice.2

Statement of principle:

Anyone who lets an "AI" system make substantive decisions that affect their own future in 2026 is putting themselves as risk and is fully responsible for the consequences of following those decisions. Anyone who lets an "AI" system make decisions that affect other people's futures in 2026 is both committing a sin and acting negligently, and should be held responsible for the outcomes.

Let me emphasize: the people who make the decision to use the computer that way should be held responsible for the outcomes.

Powerful forces are trying to insulate themselves from those consequences and it's important to work against them. Call you political representatives, make public statements, hold them responsible in your head and heart and act on that opinion.


There's an interesting subtlety here, insofar as bureaucracies are already opaque decision making machines that have no soul or sense of their own (and that's been the case for millennia!). People who run (or profit from) big organizational decision making will see a move to LLMs as just more of the same and will want you to agree with them. But the thing is that we know from bitter experience that those big organizations sometimes make morally repugnant decisions3 and convince most of their participants to not only go along with it but that have no shame about it. Think (to choose two examples that came to light during my lifetime) of the tobacco industry manipulation of health data related to smoking or the Catholic church's handling of sex offenders, along with many more at all kinds of scales.

In "modern, western" societies our main protections against organizational malfeasance are government oversight,4 investigative journalism, and whistle blowers. And the first two often don't kick in until someone on the inside speaks up.

There will be no whistle blowers inside the LLM's decision loop, so we can't count of the existing structure for protection. We need to focus the attention of the decision makers.


1 Whatever version of Gemini Google uses to front their web searches this month. And, by the way, a search engine is a subscription free portal to substantial models...

2 I have intentionally written C++ code that exposes routes to undefined behavior in the past (and probably will again in the future), but it is never a "best practice". It's always something you do reluctantly to preserve some other property of the code (generally performance related) and in a business setting only after consulting with you colleagues and getting their buy-in on the necessity.

3 Also sometimes genuinely stupid decisions from a defensible moral position, which also needs addressing but which piss me marginally less.

4 The importance of governmental oversight is a problem when it is the government that's in the wrong. The Unites States have developed such an encrustation of protections for officials that the most common outcome for vast federal abuse is ... a promise not to do it again and promotions for the people involved. Sigh. It's enough to text my faith in justice as an achievable ideal.

2026-09-18

Hang on now...

...is it, just maybe, possible that the industry with the largest fractional job losses1 to LLMs to far could be troll farms?2

I mean, I'm not sure how we would tell. Even if a few countries have some employment data that covers the case, there's no way the big players are putting it out there. But it seems like a really good use case: take a small model that produces good output in the few to few-dozen words range, post train it for your ideological bent and let it loose. If you need to, you can use something a little smarter as the agentic driver. The task is requesting web pages, parsing out threads, and posting or replying (more HTML events). This is stuff there are skills for all over the places.

It's not like it's good news even if it's true: it makes a bad problem and the people in charge aren't the ones getting hurt.


1 Real job losses: not dog-and-pony-show we "cut" jobs we wanted to get rid for stock-price manipulation purposes, say it's AI, than hire as many roles back again as soon as we vest or get the bonuses. As a side note: if you've offered one of those "oops, AI isn't ready just yet" positions you should drive a very hard, very expensive bargain.

2 You know, the people that rouge states, criminal organizations, or political parties that you don't like and so on pay to spam opinionated, wrong, and non-constructive comments on social media.

2026-08-27

If you use social media...

...follow real people.

Right now my social media feeds are full of superficial AI generated or supported slop. Much of it obvious chosen in hopes that it will appeal to me and almost all of it presented it multiple variations on a theme. The last couple of weeks it's been all "Gen-X people are great" all the time for me. Jeeze, people! Subtle much? Somebody is A/B testing like crazy.1

To be sure, superficially appealing slop was a staple of social media before generative AI burst forth from the lab, but this feels different to me. Previously we had artisanal slop—2each title hand-crafted (albeit often poorly) by people with idiosyncratic views and genuine pockets of expertise and ignorance. Even the ones that were just a voice track overlayed on some photos or animations had character. Now we're getting smooth, undifferentiated pap with really good production values but no soul.

And really, there are two things you can do in response if this bother you. The first is just don't do social media at all. That's probably best. But if you must, be mindful about the the content you tell the algorithm you want. For me that means content generated by a single person or a small team, with human sensibilities in the driver's seat.3 And if I don't feel confident about it I assume it's too much AI and nope out early.


1 Do you remember when congress called the tech bros to testify. The biggest travesty of the whole dog-n-pony show was that no one asked them how many tuneable dials "the algorithm" had and how often they tweaked them. It doesn't matter what company we're talking about, the answers are "a lot" and "we have whole teams of salaried professions who work on that continuously". The algorithm is not a thing apart for company policy (which was the crafted message of the testimony), rather it is an expression of the policy.

2 Do you see what I did there?

3 And of course, keeping up your intake of content that engages deeply with difficult topics (which means long-form and wrestling with uncertainty, ambiguity, and doubt), is the cognitive equivalent of making sure you get enough vitamins, minerals, and fiber in your diet.

2026-08-07

Missing feature

Me
Hey CVA,1 navigate to my Super Secret Lair.2
CVA
Okay. ::brings up a map::
Me, going bug-eyed
Dang CVA, why that way?

At this point CVA says nothing and you either follow it or not, which is not how you would interact with a human navigator. What we need is support for closing the loop on that question:

CVA
There are heavy delays on your usual routes.3

1 Creepy Voice Assistant

2 For the traffic-aware routing. I know where the SSL is.

3 Knowing my "usual routes" would be just another creepy thing about the voice assistant but, oh, so useful. I'm gestating another post on the tension there.

2026-07-25

How many featured guests does it take to change the "band" of an album?

Let's say, you're writing a music app. Something like Apple Music, Amazon Music, Spotify, or whatever. You will, of course, want to offer your users multiple ways to find music. A flexible search interface, a list of songs, a list of albums and so on. The fun comes if you decide to offer a list of artists. When should an album show up under a particular artist? How do you handle ensembles that aren't publishing as a named entity (i.e. it's by a bunch of people and not "by a band")? Worse still, how do you deal with tracks that include a featured guest artists on an album that is otherwise by a single person or band?

As a programmer who cares about users, my vote would be to accept some duplicate presentations due to fuzzy matching rather than risk disappointing a user who disagrees with my way of answering those questions. But that doesn't seem to be what Apple picked. Indeed, I simply can't deduce the logic (if any?) underlying how Apple Music handles these questions. In the album list one album can show up more than once, partitioned according to the performance credit for each song. An album by a band that has one song with a featured guest performer isn't enough to make that band show up in the list of artists.1 WTF, Apple? What are you thinking? Just ... WHY?!?


1 I've ripped the True Love Never Dies from CD, but Otherwise doesn't show up in my artists list, because I only have that one album at it has one track featuring Ash Costello. Grrr...

2026-05-28

A modest UI proposal

Not-good-at-tech mode

I begin to suspect that certain apps could use a new, over-arching control. One that (a) increases the size and weight of all text elements, (b) forces the facility into the lowest-common-denominator do-what-it-says-on-the-tin mode, and (c) hides all the complex controls. It should be easy to find and disable, of course, as we're not trying to take options away from anyone: just give them an easy button.

Though perhaps I should reconsider my proposed name for the feature...


Full disclosure: I asked Gemma4:31b to write the CSS and HTML for the sample.

2026-05-12

Sometimes one facepalm is just not enough

Still working on my little JavaScript side-project as a way of learning AI workflows. Still not using AI for a lot of code-gen but instead for friction reduction. It's going fine, thanks. I mean, the last few weeks haven't seem many new features, but instead a couple of re-factoring passes intended to enable big things in the future, but I count that as progress.

Anyway, while thinking about the evolution I had a question. I was fairly sure the language would do things the "right" way, but felt the need to test, nonetheless. And being an old guy, I wrote the test code by hand:

const primes = [2, 3, 4, 5, 7, 11, 13, 17];
const fibonacci = [0, 1, 1, 2, 3, 5, 8, 13];
let combined = [...primes, ...fibonacci];
combined.sort();
console.log(`primes: ${primes}`);
console.log(`fibonacci: ${fibonacci}`);
console.log(`combined: ${combined}`);

the point of which was just to assure myself that sorting the combined array would not scramble the source arrays. I would have been very surprised if it had, but I had to check.

That said, the results were not what I expected:

primes: 2,3,4,5,7,11,13,17
fibonacci: 0,1,1,2,3,5,8,13
combined: 0,1,1,11,13,13,17,2,2,3,3,4,5,5,7,8

Wat?

An array filled entirely with numbers has been sorted lexically according to their naive string values.

And on reflection, that's not terribly surprising in a language, like JavaScript, that is both dynamically typed and quite compact because it is the prescription most likely to work in most situations. But it sure came as a surprise to a guy used to strongly typed systems intended for systems and scientific work.

2026-04-02

Side Quest: Server Fetch

I mentioned in a recent post that I embarked on a lengthy side-quest while configuring a JavaScript environment in Emacs for a hobby project. It might be time to explain what that was about.

Getting the quest

I picked up the quest when I went looking for a JavaScript LSP, and found that almost all the options require installation via npm. I do have a couple of npm based things installed, but I've been feeling sour about it after some recent supply chain attacks against the packaging system and have tried to work around needing it. I hasten to say that my worries weren't focused around a notion of npm as more of a security risk than other supply chains I use, but around the desultory and inexpert way I interact with it. In the case of my other supply chains, I update regularly and follow sources of on-line news that are relevant to the ecosystems in play. Not so with npm. I worried that I would be late to the party on knowing that I had a problem and taking steps to fix it.

The task at hand

I wanted to install a JavaScript language server without using npm.

To start with, it's not in the least surprising that most JavaScript language servers are distributed via npm. I mean the protocol specifies JSON, so there is every reason to write them (in whole or in part) in JavaScript, and in that case npm is the default distribution mechanism. But, as I indicated above, I was hoping to avoid adding that window of vulnerability to my systems.

If at first you don't succeed...

So, LSP being a microsoft controlled protocol, one of the few central locations that which a list of available servers is maintained by microsoft, but there are others. In any case, I found only a few currently maintained options:

  • typescript-language-server
  • flow
  • quick-lint-js
  • biome-lsp (a part of the greater biome project)
The installation instructions for the first two both start npm install. The third is available from my distribution's package repository and works, but there is a lot that it doesn't implement: it really is a linter than knows the language server protocol (and I don't want to diss that—being a server gives it flexibility in interaction modes—but it isn't all that I hoped for). That leaves biome, and actually, it's installation instructions also start by calling npm, but further down the README.md it says "Biome doesn't require Node.js to function.", and you can find build-from-source instructions on the project homepage. Frankly, they're not very good as they seem to assume that if you're asking that question you can guess your way through it, but I got it done.

Being my own worst enemy

The last hurdle on my quest was largely of my own making. You see, to run biome as a server you have to pass it the lsp-proxy command, which is emphatically not the spelling I would have chosen for that option if I'd been writing the tool. And for some reason, when I was configuring Emacs, I kept spelling it differently. I spent an increasingly frustrating half and hour making variations on the same mistake before noticing what I had been doing all along. Use the right spelling and it just works.

2026-03-23

A DeCSS shirt for the late 2020s

So, I see a lot of wittering and gnashing of teeth about online age verification laws. Both in general and specifically as the apply to Linux, BSD, and other open source operating environments. I want to talk about some practical issues around what technology will have to emerge to make them "work" and how easily even moderately technologically aware people can, to be blunt, screw the laws over.

And I want to propose a new fashion that might, just, catch on in the next few years.

What is going on

A few juristictions (including Brazil and California) have passed legislation pertaining to online age reporting and many other jurisdiction seem to be following suit.

Allegedly these are intended—as so many, many bad ideas have been in the past—to Protect The Childred (tm).

They're not going to work any better than content labeling of music, the v-chip, or video game content rating (just to name a few) did1. I recall a time when every stand-up comedian seemed to have a bit about how parents would have to get their seven-year-olds to program the v-chip just like the kid was the one who set up the VCR. But hey, we have to do something and this is something so obviously we have to do this. Not that I'm depressed by how predicatable all this is or anything.

Why it's weird for open source

There are a few of things going on here. One is structural, one is philosophical, and under all that is brute technological fact.

Structural

While Windows, MacOS, IOS, ChromeOS, and Android2 are controlled by large coorporate entities that decide what their customers get to install, Linux, BSD, and other open source operating system are, in principle, fully under control of the individual installing them. The weasle words are in there because few people build out their system from raw parts: they mostly use a distribution, which does have a central point of control (though many offer much more customization that the you get from Apple or MicroSoft).

This is not a funcdametal issue; the kernel and or the encrustation of supporting code could feasibly (I won't say "easily" because I'm not the one programming it) be altered to support the requirements of the laws. And those changes could be incorporated in upcoming distribution releases and make their way out to the mass of users.

But it's not like there is one place to go to try to enforce this decision. Or even ten places. Keep in mind that even if some major distribution (perhaps Ubuntu) were to comply nothing stops a downstream re-packager (say Elementary) from removing, disabling or defanging that support. More on that later.

By the way, there are litteraly scores of distributions originating on all the inhabited continents and from various points in Oceana.

Philosophical

As a generic term "open source" covers a lot of ground, but central to the that nebulous mass broadly known as the open-source/free-software movement we find Creative Common, the Open Source Iniitive, and the Free Software Foundation all of which of are organizations with some money, rather more precisely specified definitions, and some very strong opinions on matters of software control and human flourishing. And they're not the only ones. In fact the space is just crawling with various NGOs that provide legal support, lobbying services, publicity, and (obviously) software packaging.

The whole "the government is telling you how to build your software" thing isn't going down well. You may expect resistance at many levels. Anyone else own a DeCSS shirt?

The foundational reality of Open Source

Programmers program. In one sense that's a tautology, but it has profound implications.

Before delving into what it means for this issue, let's just talk about what it means for organizational cyber security. My employer has recently gone through a series of IT security exercises in an effort to lock down all the possible cyber threats. And they have a problem: what programers do on a day to day basis is indistinguishable from a large class of threats. We create new executables not known to the system and run them. Often dozens of times a day. And that is unavoidable: you can't have the benefits of what programmers do without having the relative chaos of programmers at work.

Similarly, you can't have open source and still be confident that everyone is running the nannyware you insist on. Remember that I said a downstream distributor could strip-out or neuter a reporting facility installed by an upstream provider? Well, in principle every single user is a downstream provider with that same capability. Worse, capable programers can provide tools to enable less capable people to perform the necessary modifications. Indeed, Ageless Linux is already pushing back against early complinace efforts on the part of systemd (the dominant, but often derided, init system on major Linux distros).

Legal aside

I think the intent is that anyone modifying the softawre is the "Provider" that the government enforcers can go after, but if that's just a couple of techy parents who don't want their machine identifying their minor childern to the wider internet, there is a "parent's rights" argument to hang a political and legal challange on.

But ... talk to an actual lawyer in your actual jurisdiction with actual expertese on the legal system you actually might be picked on by before counting on that kind of thing. K?

Speculation on implementation and countermeasures

From ten kilometer altitude, communication between a user's machine and a software store or other endpoint that might want to use a age signal can take one of two forms, and one of them is harder than the other for actual installed systems. You see, one machine has to initiate the conversation, and if that's the store's server, then many home and corporate firewalls will drop the packets on the floor.3 For that reason I suspect the industry will settle on a strategy where the user machine asks the server for a one-off token, hands that to a local age-reporting API which cryptographically mixes it with the answer, and the mixed data is then relayed back to the server for decoding. There are other things they could try, but they're all pretty fragile.

Anyway, on Linux the bit that builds the reply would either be built into the kernel itself or in a kernel module, but either way a savy user will be able to disable them. Then they just substitute a dummy system that respects the protocol, but always returns a least-interesting answer to every query (Yeah, this user is of age. Trust me.).

What Ageless does is more than that: it removes the infrastructure and storage that could be used to respond, which is a good thing, but the above is enough to stop making meaningful responses. And I'll bet a bottle of scotch that the dummy responder can be constructed with code that will fit on a t-shirt.

Intent

I'll write the thing as soon as the spec is available (or grab someone else's if it's avilable, because I'm not stuck about this sort of thing). And then I'll be printing shirts. And maybe hoodies, too. You never know.


1 Which is to say that (a) the kinds of parents who take the trouble to monitor their kids' media consumption will have another tool while other kinds will completely ignore it and (b) the kids will not only find ways around the tech, they'll use the system to advise them where the "good" content is.

2 Android is a little weird, because while Google (whatever name they're going by now) controls the system, many devices ship with manufacture customized versions. But it is still the case that there is a corporate entity for the government to go after.

3 And maybe report them to an intrusion detection system, but that's not really relevant here.

2026-03-22

JavaScript, PEBKAC, and LLMs

A couple of months ago there were, at last, some promising smoke signals from corporate suggesting that IT is getting around to really thinking about, just maybe, supplying us with something by way of security-minded LLM support.

Okay, so it was a little more than that. They actually bought licenses for a commercial product (something that comes with security guarantees backed by performance penalties) for supplying that kind of thing. For the managers.1 That was a bit disappointing because I couldn't explore that space on my employer's dime.

But it got me to start thinking seriously about trying out LLM supported programming workflows, and I decided to apply it to some aspects of my hobby projects. After some thought I concluded that the models I was likely to run were going to be uninspiring on C++ projects. To maximize the utility of the tool, I needed a project where (a) the model would have seen a lot appropriate of training data and (b) I was not already highly conversant with either the domain or the tooling.

I decided to start writing some little games for the browser in JavaScript.

And, brimming over with excitement for my new project I ... spent about four weeks of spare time mucking about with tooling. Yeah.

I did eventually gets Emacs configured to know about JavaScript (including an LSP, a major side-quest what with some self-imposed limitations, but that's another post) and chose one of the multiple LLM interfaces for the editor. There were a few hiccups along the way, but a I got some advice from a couple of LLMs which really helped. Oddly all the configuration work was making me feel optimistic about the project: the models weren't really handling much tedious boilerplate, but they were getting me past some ignorance-driven friction and probably (at least maybe) saving me time. So really yeah!

Then I watched a couple of on-line tutorial videos on JavaScript animation and game-dev, created a new project repository and started random hacking about while asking the models a bunch of questions and having them try their hands at writing bits of code. In about a-week-and-a-half of spare time I had a canvas with four distinct objects moving around it, each under their own set of rules for speed, gravity, wrapping around edges and bouncing. The code quality was awful, but not because the models wrote it. The parts I wrote were just as bad because this was a "just get something working" exercise. Almost everything was in global scope and free functions poked into the depths of the object collections to manipulate internal state. Classic.

The next thing to do, of course, was impose some order on the chaos. To channel interconnectedness through designed mechanism, and achieve a degree of uniformity in implementation.

I broke everything that worked to separate some concerns here, name elements of the modeling there and so on. And after burning another week of spare time on it, this afternoon I had all the same data in the program in a much more orderly manner and the first frame drawing as expected. But nothing was changing even though it looked like I had all the plumbing back in place. The application of some judicious console.log calls2 proved that the animate function was getting called, it was iterating through the object and telling them to update themselves, and they were iterating through their update action list and calling them. But the display was not updating.

And also, I hadn't asked the LLM anything for days of real-time and hours of coding time despite (if you believe Mrs. NoSwampCoolers) a steady stream of swearing at the code. I've been "a programmer" since sometime between 1982 and 1992, depending on what you want to credit with the title (1982 was first typing the classic 2-line "hello" infinite-loop in basic; 1992 was my first production code). I have deeply ingrained habits for both learning new things and tackling problems with code-bases. And "ask the AI" does not, currently, feature in those habits. Which is a me problem to the extent that "ask the AI" is better than my other approaches, but is still a thing to be overcome if a transition is to occur.

Anyway, I did eventually think to "ask the AI". I used my LLM interaction tool to pick four (quite short) files out of the project directory and asked why the actions called by Obj2d.update were failing to update the positions.

After telling me many thing about the code that I knew (because I had designed them in), and complaining about the bits of context I hadn't show it because they did matter, noticing (out loud) that they didn't matter, and deciding (out loud) to move on, it first proclaimed that there wasn't anything reason for issue and then said, "but wait". Turns out the joker who wrote this code didn't provide setters for some concepts he's trying to set in the bowels of the Vec2d class. Which was the correct resolution of the issue.3 Facepalm. Score one for the model.


1 Whose main day-to-day complaint (at least in my unit) is that they don't get enough time to do technical work what with all the people, contracts, and paper work they're saddled with.

2 Yes, there is a debugger in the browser, and yes I've largely figured out how to use it. But my "just hack on things" machine has a small display which (added to the unfamiliarity of the language and debugger) made print-debugging feel more comfortable. Presumably I'll get over it as I go.

3 I don't think I've mentioned on the blog before, but I really hate environments that silently fail. And Firefox will let you write v.x = new_value; when v has neither a public data member nor a setting named "x". Really. So the f'ing environment gets some of the blame here.

2026-02-02

Hey, ya wanna help?

Here's the thing about smart phones: you cannot reasonably prop them between your shoulder and you ear. Not only will you get an instant muscle cramp (and probably scoliosis within minutes if you persisted), but the thing won't actually stay there. In that respect they really, deeply suck.

But whatever. Price you pay for the benefits of the form factor. Or whatever.

That said, this has a consequence: if someone calls and (a) you don't feel you can skip it, (b) you still need to have both hands for something (anything) other than the phone, and (c) you don't currently have your buds in then you must, in short order:

  1. answer the call
  2. switch to speaker
  3. prop the phone somewhere

Presumably the people who write the UI for these things have this experience, too.

But recently with my phone, when I tap to answer, the UI goes through some flashy, battery-draining, nonsensical animation which results in the hang-up control landing right where the change-the-audio-button was a moment before. I have no words.

Random musings

If you found yourself in the same room as whatever self-satisfied twit is responsible for foisting "liquid glass" on us and asked the two nearest other iPhone users if they wanted to help administer a swirly, what do you think the odds would be?

I put them over 2/3, personally.

2025-12-27

Having your "Smart" and your "Open", too

This is the third of a group of of posts on "Smart" appliance. You don't strictly need the first and second entries one to read this, but they're meant to be building up a common context. In this episode I talk about a mechanism that would relieve most of my worries about these devices while allowing manufactures to maintain control of their trade secretes and the presentation of their interfaces.


My complaints in the first post aren't intrinsic. Instead they are complaints about a particular implementation of the smart model where the physical device requires a specific (rather than generic) piece of paired software; in that implementation our intellectual property regime around software puts the manufacturer in control your ability to have that software, and consequently puts the manufacture in control of your ability to use an physical device that you bought. That is totally unacceptable.

Out strategic goals are

  • Possession of the physical device grants access to its functionality1 because the requisite software is generic enough to be re-implemented on any suitable platform.
  • The manufacture gets to keep their trade secrets to themselves.2

That's an interesting pair, because the first requires that the trade secrets be physically embodied in the machine (otherwise you can't guarantee that the functionality moves with the physical object). But that seems to be in tension with the second requirement, because how can the manufacturer control trade secrets if they're trading freely around the economy?

The thing is that the control software (which is already on board) also encodes the trade secrets. Anyone with the right tools and knowledge can already can extract the firmware, decompile it, and sus out the meaning of resulting code. It's just that that's a pretty hard trick (those boards don't need debug ports and I'd be unsurprised to find that many don't have them) and consequently time consuming and expensive. Then, as always, the legal regime puts up further barriers to someone trying to compete using that approach.

And we deal with systems that have those properties all the time. I'm describing a client-server architecture. The appliance is the server, your phone or tablet is the client, and the manufacturer can hide as much detail as they want server-side. By using open protocols for interchange and open standards to present the interface consumers get a extortion-free way to talk to the appliance, and in return manufacturers get reduced software development costs and all-platform3 functionality for free. It's that easy.

My hot-take, off-the-cuff, proposal for the whole thing:
HTML5.

Literally put a little web-server inside every appliance. They already have non-trivial computers and at least one of WiFI or Bluetooth, so this is not a stretch. In the worst case users can use a plain web-browser to access it.4 With HTML5, manufacturers can control every aspect of their interface (I mean their pages can just be a canvas if they're that hung up on controlling the appearance), control how much functionality is pushed to the client-side, and so on.

What's not to like?5


1 All of it. If you own the thing, you own it. This is non-negotiable.

2 Within reason. There is no way to guarantee this absolutely, and (importantly) never has been. Anyone with the tools and expertise has always been able to reverse engineer a product, and it was only ever the high cost of reverse engineering and IP law that prevented them from taking that route to develop a competing product. We're looking for a regime where the level of difficulty in obtaining and profiting from the trade secrets remains similarly high.

3 And not just iOS and Android, either. Everything, everywhere, all at once. As it were.

4 I imagine the ecosystem will rapidly spawn a genre of specialized appliance control apps with a HTML renderer at the core, and featuring convenience functions for organization and access, but a plain web-browser provides a fallback position.

5 Okay, so there is the addressing problem for devices that use WiFI. Some kind of discovery mechanism will be needed, and I don't know— off the top of my head—what the options for that are. But it's not like this is a new problem: printers and scanners, especially, already handle this in a variety of ways. Similarly bluetooth has a pairing problem to solve, but that's an issue for existing bluetooth devices as well.

2025-12-20

Why "Smart" appliances might make sense

This is the second of three related articles. If you haven't seen it already, perhaps you should read the first installment.


Some devices have very simple interfaces: they're either running or not, so they need a switch. But then, maybe there is a thing you make stronger a weaker, so you add a dial or a slider. And maybe it can run a couple of ways, so you add a selector dial. Maybe the user needs some progress feedback, which means some kind of clock.1 And so on.

In my youth, a typical washing machine, dryer, or dish washer had a handful of controls supporting as many as a dozen modes of operation, and that felt like progress compared to the kit my parents grew up with. Yeah! Living in the future!

This is the control panel from the dryer at Casa NoSwampCoolers. There is a power button and a separate start button (because power means the controls are active and start means the machine is running), a mode-select dial with fourteen options, four categories of adjustable parameters (some of which only apply to some modes), six additional Boolean settings (again, applicability varies), and a time-display-and-control group. I'm not sure if that reaches a thousand front-panel accessible combinations but it is certainly hundreds. And there are extended features only available with an app.2

Okay, so we've established that (at least some) modern appliances require complex interfaces. But we've also established that you can build the interface into the device. So, how does that justify connecting it to your carry-around-computer-thingy?

Well, we're in engineering trade-offs land. We get to compare costs, convenience, maintainability, utility, and user preferences between alternatives. And how we rate some of those depend on how the machine works. If you have to physically load and unload a device for it to be useful (as in clothes washers, clothes dryers, and dish washers) then remote start is less helpful compared to remote access to your car's defroster.

Settable defaults are nice
In principle, to know that my dryer is doing what I want I have to memorize the desired state of approximately a dozen controls, and check each of them on the control panel. In practice I memorize the smaller number of things it takes to get from "just booted" to the state I want: switch the mode to "Speed dry", set the temperature to low, increase the time, then go. Wouldn't it be nice if I could set the default state or name several default states? If there is a win here it's for "smart"
Control panels cost money and represent additional points of failure
Controls are a pain. They have to be robust, when the options are discrete they should be unambiguously in one state or another, they should give clear feedback, and in the physical realm all of that takes engineering. The cheapest switches and dials general lack something. I'm not in this business, but over the years I've talked to people who are. Controls often represents a surprising portion of the cost. To be sure, digital interface can fail too. If the magic smoke gets out of the computer on the device, your done with either kind of controls.3 If your phone smokes, you need a different interface device. At least partly in favor of "smart"
You're right there anyway
As mentioned above, some devices require your presence. For those I really want a on-device control set for the primary features. Because otherwise they require the presence of you and your phone or tablet. But I'm pretty happy with our machine that presents the big easy stuff on the panel and leaves the fiddly choices for a computerized interface. Definitely favors some physical controls on machines you have to attend in person
Translation
Did you notice that the controls on my washer are labeled in English? That's built into the physical medium, so a French-speaking, would-be user can't just change it. Now the company could (and presumably does) provide that part in multiple language variants, but that becomes a logistical headache and thus a cost and you can't easily switch back and forth. Adding translation to a software interface is not free, but (with some support from your OS or framework) it can be relatively painless, and users can change the language on demand. That's cool. A reason for pixelated UI, where ever the display is mounted
Maintainability
Once a physical control panel is engineered, manufactured, and sent into the wild changes are hard and expensive. In principle, software changes are easier, though if the software in question resides on the machine, you'll need to provide a firmware-update facility of some kind.4 If there is a win here it's for "smart"
"Just give it a proper display" is a good idea, but you already have a display...
There is nothing magical about using your phone or your tablet that enables digital UI. You could put a display (probably a touch display) on the device and then have a programmed interface. Yeah!. But ... how many pixels are you willing to pay for? And on every appliance in your house? what about physically small devices like my espresso machine? And those question lead to the idea of sharing a single interface device. Your potential customers almost all have a phone or tablet already,5 why not just borrow that display? Favors "smart"
Human stuff
This is hard for me. I'm not trained in UI/UX. I haven't done any surveys. Basically this whole essay has been me ranting about how I feel. But people sometimes care about appearance, and sometime don't like to learn new things. And so on. I'm not going to guess how this breaks for smart versus not smart.

Anyway, the next article presents what I think might be a viable approach that everyone can live with.


1 In some instances the dial that the user used to set the run-time was a mechanical clock and would wind back down also serving as the time-remaining indicator. Parsimonious design, that.

2 This is the sort of situation that prompted the third Smart Appliance rule. That dryer is very useful even without the app. Indeed, we've never used the app. Mrs. NoSwampCoolers tells me she has used the app for the matching washer (with a very similar control panel) once in the fourish years we've owned these things. Once.

3 Yeah. I'm just assuming there is a computer in there. My sense of it is that no one is designing these machines with end-to-end analog circuits anymore. I once did a few hours of analog diagnostics on a Kenmore model 40, but I'd expect to find a MCU behind any reasonably modern control panel.

4 My car's entertainment center has a SD card slot hidden behind a pop-up panel.

5 If they don't we're talking an additional up-front cost for them, but if they can afford the appliance, ... well Walmart's website lists tablets starting from under US$50 as I'm writing this..

2025-12-19

Little surprises #10: iterators, half-open intervals, and git range selections

Let's talk about for loops. That's not actually the subject of the post, but we have to start there, hit a couple of stops along the way, and only then complain about git.1

Back in the misty depths of time, there were programming languages that indexed their arrays starting with one. If you write that in a c-like syntax you end up with something like

int array[ARRAY_SIZE];
// fill it somehow
for (size_t i=1; i<= ARRAY_SIZE; i++)
	print(array[i]);
where the end condition is controlled by <=. That has never really gone away—despite the efforts of some influential people—but I want to direct your attention briefly to the same for-loop in a language that uses zero-indexed arrays. Now idomatic code uses a strict less-than comparison:
int array[ARRAY_SIZE];
// fill it somehow
for (size_t i=0; i<ARRAY_SIZE; i++)
	print(array[i]);
but you could also use a not-euqal-to (!=) because the upper limit of the loop no longer represents a cell of the array that is accessed. Instead it represents where a cell would be if it were one-past-the-current-end.

Pointer and Iterator loops

Of course, you don't have to use an index for a loop counter. K&R is full of examples where they use a pointer for processing a (null terminated) string:

const char *s = "Yellow whirled!";
for (char *p=s; *p != '\0'; p++)
	print(*p);
or a linked list:
LIST_NODE *list;
// fill it somehow
for (LIST_NODE *p=list; p != NULL; p=p->next)
	print(p->payload);
In those cases the termination condition is a not-equal comparison to something that is (again) not processed.

And that is the pattern than many languages (especially the ones I use regularly) use for iterating a (possible subset of a) collection. The beginning iterator designates something that is to be processed and the ending iterator either signals the lack of further data or designates data to not process. In C++ this is the pattern for the algorithms library (where you hand the routines explicit iterator pairs), and by ranged-for loops where the syntactic sugar calls std::begin and std::end on the object to be iterated. The end-marker does not represent data to be processed.

On to git

Some git operation let you interact with groups of prior commits. To inspect a sub-set of the history, run a partially automated bisection process for finding where an issue was introduced, or (as I was doing when I discovered2 this behavior) to select a set of commits to "cherry-pick" to another branch. Unsurprisingly the command line syntax needs you to say what commits you want, and listing more than a few hashes explicitly is a pain. Luckily there is a "range" notation: [Early commit reference]..[later commit reference].

Now, if you use this notation with cherry-pick it will apply your selected commits to the new branch in time order: starting with the earliest selected commit and working it's way steadily toward the latest. Which is exactly what you would expect.

What you probably wouldn't expect (unless you, ya'know, actually read the documentation), is that it will exclude the earliest commit you entered and included the latest. This was so surprising to me that I actually did it wrong a second time before I started scouring the manual for an explanation.

That is a half-open range like we find in the discussion of iterator for-loop above. But instead of being [start, end) it is (start, end]. What. The. Absolute. Heck?!?

That said...

Interestingly, if you look a little deeper, there is a reason. Or at least a way in which this behavior arguably conforms to my description above.

Start by understanding how a git repository is structured. Each commit contains a record (effectively a pointer-to) all the commits that act as its parent(s) (there might be zero, one, two...). But commits are immutable once created, so they can't be amended with pointers to their descendants. The effect is that (assuming your range selection represents a branchless part of the graph3) you're looking at a linked list with the last commit as the head and the earliest commit at the end (of the range you care about, anyway).

So, even though commits are applied in time-order, they are found starting from the last event and working back in time. The docs make this clear: the selection is all the nodes reachable from the final commit, but not reachable from the first commit.4

And in that view, this is exactly like the linked list example I wrote above.


1 A little like eating your vegetables before dessert.

2 The mere fact that it is clearly documented if you bother to read doesn't affect my right to use that word. Does it?

3 I haven't actually tried it yet, but I imagine that selecting a span with this syntax that has a merge in it would include a large historical sub-tree you don't want.

4 And a commit is reachable from itself, naturally.

2025-12-14

The "Smart" appliance policy at Casa NoSwampCoolers

By way of introduction to some follow up posts: appliances that require a external computer to make them go are a kind of cyber vulnerability. The utility of the device is dependent on the availability of a working interface and thus on the whims of a third party. If they drop support; if they decide to lock some features behind a paywall;1 if they don't support the app on the platform you use, your device is worthless.

While someone could, in principle, program a new interface there are a number of problems:

  • Access to information about the device side of the interface. This stuff is trade secrets, and the holders rarely see it as profitable to share it, even if they are no longer supporting the affected devices.
  • Good engineering practce may suggest using a a common code base, but manufacturers are also willing to switch hardaware platfomrs to minimize costs. The result is a lot of diversity even within single product lines, as witnessed by the long running struggle to support various peripheries in the linux kernel.
  • Finally there are legal barriers to the "just hack it scheme". In the US, for instance, the DMCA, means that the most trival effort by the manufacture to "protect" their kit makes the hacking job a felenoy. Until the right to repair is legally recognized,2 this multiplies the difficulties improsed by the others.

So here in Casa NoSwampCoolers we have a three part policy:

  • No device which requies an account registered with the manufacturer.
  • No device which requies an app provided by the manufacture to access it's core function.
  • Any device which requires an app to access special features or functions must be explicitly discussed by the grownups prior to purchase.

The second part of this series will address the engineering reasons in favor of "use you device to control it", and the third will look at a solution that lets us have the upsides without the downsides.


1 No names, BMW.

2 I consider that a cause worth my political dollars. Would you care to join me?

2025-11-29

Has "AI" just made that experience worse?

Courtesy of my father's lengthy service in the Navy, I've been able to use USAA1 for insurance for my whole adult life. A small but comfortable privilege. Now, I bring this up because of USAA has had a ready-for-prime-time, flexible, responsive, automated-voice-interface answering their phones since (at least) the mid nineties (it informed my comments on an earlier post about this category of convenience). It's been my preferred interface for paying bills since I got my first policy with them.

Anyway. I paid a bill recently, and the voice interaction on the phone felt laggy—compared to a system that's been working since before the turn of the millennium—and I formed a suspicion that someone has replaced the gut of the existing system with a big machine learning model.

Now, there is a sense in which that is a very good idea. The existing system presumably had trouble with some accents and a large model can learn to overcome that. But it still felt like a worse experience.


1 A mutual insurance corporation in the United States. Originally for US Army officers, they've expanded their membership criteria over the years but the idea appears to be to select a highly responsible membership base.

2025-09-20

I don't want a framework, but I do want the convenience

Programming frameworks can be a huge boon in terms of simplifying the provision on desirable features and behavior that aren't the core of your project.1 But they evolve toward someone's ideal of an all-singing, all-dancing, universal tool and that makes them huge and complicated. For a lot of the things I write at home, I don't need most of those facilities and I don't want huge or complicated. But I also don't want to be writing thousands of lines of code just to make my tool ergonomic.

Thankfully the open source community provides hundreds of high quality utility libraries covering all kinds of tasks you might want to do. Usually a handful or more for every feature you might want. Which means you have to choose.

This week, I decided that I wanted a command-line argument processor for a tool I"m dinking on. I've used gengetopt in the past when simple ad hoceries were insufficient, but it needs a two stage build and has a clunky, pure-C interface. Surely I can do better than that!

How to decide?

Well, I have a partial answer: The build system I use for home projects is Meson, which uses a facility it calls "wraps" to support fetching and building projects you depend on.2 Moreover, the tool has a facility to fetching wrap files from a centralized database which makes adding a provisioning library to your project nearly transparent.

So I'm going to restrict my consideration to tools that appear on Awesome C++ and are available from Meson's Wrap DB. There might be other good options out there, but these have had some level of peer review and (critically) are easy for me to get. That gets me down to:

After a cursory reading of the github READMEs it's clear that they all provide the features I need and have a version of the same kind of interface that QT uses.3

But that doesn't mean they're equivalent. One (argparse) uses a Method Chaining (AKA Fluent) interface for the "tell the parse what arguments to expect" step,4 and another (cxxopts) uses method chaining with statically polymorphic calls to operator() which makes a slightly weird syntax that I suspect clang-format is going to balk on. Neither of those is a deal breaker, but they are a little odd. Alas, the third option (CLI11) is a little clunky: requiring you to create two objects and relying on a try-catch for detecting errors (though it provides a c-preprocessor macro to hide the exception handling if you prefer).

Anyone have any relevant experience here?


1They also provide consistency across a set of tools for both users and developers, and you should not neglect that value in that. At work we use Qt, which has all the faults I list above and a swath of legacy issues as well. But the bit where my manager can say "Hey, we like that command line feature you added on your project, put it in Jane's too." And even though I've never worked in Jane's project before I can still dive right in because I know how command-line interactions work in QT. Programming at scale is a team sport and that changes the trade-offs.

2 I already use the doctest wrap in several projects, so I know how this goes.

3 You create a parser object, tell it what arguments you expect, pass it the command line, and then ask it what it found. With convenience facilities for detecting violated expectations, issuing help messages, and so on.

4 I've tried method chaining a few times in my own coding, and found that I only like it in cases where most of the uses of a class are going to be transient. Thankfully, if you declare a named object you don't have to use the fluent syntax if you don't want it.

2025-09-07

Wait, how many nodes?!?

My employer has been working through a IT security upgrade process, and recently performed a dry-run of an upcoming external audit. They report that they didn't find anything surprising or particularly worrying, but they took the opportunity to roll out new and updated employee agreements for just about everything computing related. Use of company network resources and email addresses, protection of company hardware, and so on. Including a new agreement for work-from-home.

That WFH agreement is the one that caught my eye. Buried in a lengthy bulleted list was a requirement to have anti-virus on "every other system on the network". We have—currently—one windows box, one antiquated mac, a networked Epson printer, a few linux systems, three phones, an e-book reader and a bushel (or at least a peck) of tablets. How does that mess fit in?

I run Clam AV on all the Linux devices (I have reason to think that will be considered sufficient). My wife's windows system has Windows defender, and I'm told that's okay. But what about the antique Mac (even if I only boot it occasionally), and those tablets, phones, and readers? And what about guests: we have a bunch of people who come to visit bringing phones, computers and tablets with them, and common hospitality requires that we offer them connectivity.

Then, as I started to think about it, I realized that this list was incomplete. Like, seriously, incomplete. I mean, the PlayStation 4 is just the beginning. Despite an disinterest in "Smart Home" stuff, we have a number of things that could reasonably be characterized as IoT devices.

So I launched into the hardware identification stage of a network security audit this morning.

We have two smart TVs; two other WiFI equipped appliances (though we have not configured their WiFi connections), and at least ten other WiFi connected nodes providing minor but useful services. That's circa thirty devices sharing a single network segment. And it got that way one, little choice at a time, without us really noticing.

My current thinking is that I need to segment the network to isolate guest and IoT devices from our primary computing resources and run at least some basic intrusion detection. Fun, eh?

2025-06-17

An orange ring for git submodules

At work we have a common library, call it libThing, that underlies several of the products we produce for one of our big customers. We bring it into the projects that use it with git submodules. And that's a bit of a problem.

Let me explain.

You see, the design of the submodules facility is clearly predicated on an understanding that the submodule is a separate thing, and is not edited in situ by a programmer working on the super-project. If the sub-project needs updating, it is assumed, you will send the maintainer a well defined change request, wait for it to happen, point your super-project at the updated version, and go about your business.

Which is what you would expect if the sub-project belongs to someone else.

And some of our changes look like that: "Folks, we have a note from the customer. There's a new file format for specifying widgets. Someone needs to update the WidgetLoader in libThing to handle it. Joe, you've worked in that module recently, can you get to it this week?". Fine. Joe updates libThing, pushes to the reference repository and the next release of each of our project can manage the new Widget files. Nice. And exactly as Linus envisioned it.

On the other hand a lot of times we find out that libThing needs updates because we're in the course of making changes to one of the project that use it. By working both side together we can work through the trade offs dynamically. Its more natural, and probably faster, to just work on them together. Even though submodules doesn't encourage it.

Buuuut ... if you're not careful, you'll make one or more commits to the sub-project in a detached head state.1

The rest of this post is a recipe getting safely back to a happy state after you make this mistake.

Advancing the branch you aren't on

If you had done this right, you'd have put the subproject on the branch before you started editing and the branch would have advanced as you made commits. We want to get the repository into the state it would have had.

  1. Determine the name of the branch you're suppose to be on by looking in the .gitmodules file of the super-project. Remember that for later.
  2. Give the current state of your work in the submodule a temporary name with git checkout -b life-preserver2
  3. Get on the right branch with a git checkout to the branch you found in step 1.
  4. Fast-forward with git merge life-preserver (and it should be a fast-forward merge; if not you should probably take stock at this point.)
  5. Check that nothing is missing by examining the commit tree. I like gitk --all.
  6. Assuming all is well, dispose of the evidence with git branch --delete life-preserver.
  7. Detach the head again (at least if you're done) git checkout --detach HEAD.
  8. Pretend you're the kind of coder who never misses the little details.

1 If you don't work with git, then this post probably isn't much use to you, but short-short version:

  • In git a "branch" is a name that refers to some remembered state of the project. A project can have a lot of branches, and you can start with one state and make different changes to the project and have both of the remembered as different branches. That is, they can split off like the, well, branches of a tree.* They can also join up which is called a "merge".
  • You can tell git to remember a new state of the project. That's called a making a "commit" and each commit knows about the one(s) it came from, so the software can navigate back in time.
  • A commit can be the target of zero, one, or more branches.
  • You can be "on a branch" meaning that (a) you are working on the state of the project remembered by that branch name and (b) git has a record of which branch you're "on".
  • When you're on a branch and you make a commit, git changes the association of branch name to the new commit. Remember that commits know what came before, so you can still go back, but the name now refers to the new state of the project.
  • If you're not on a branch you are in a "detached head state" which means git knows which version of the project you start with but doesn't know a branch. Any commits you make in this state are nameless because there is no branch name to move forward.
  • * In computerese it's actually a directed acyclic graph (DAG), but that's neither here nor there.

2 Yes, I have a name I use for this. Not that it happens often or anything.

2025-05-13

Maybe another example of my favorite weakness of LLMs?

We've flown out to stay with my in-laws for the best part of a week. Because reasons.

I brought my work computer in case I need to respond to some crises or just find some time to do useful work rather than burning PTO (which is always in short supply). Unfortunately, my work computer is currently an eight-pound, desktop-replacement beast. For which I really want to bring a spare display (and I have fifteen-inch, USB HD panel for that purpose). With all the weight and volume devoted to work computing I opted for the barest minimum of person hardware: my Raspberry Pi 400, its mouse and, associated cabling to talk to that same panel.

Now, the 400 is a surprisingly good computer for what I paid for it, but it's also quite limited. In particular it has only 4GB of RAM, and while the CPU supports NEON SIMD there is no dedicated graphics processor. It's completely unsuited to running LLMs without add-on hardware. But I got bored, so I decided to try anyway.

I was looking for relatively modern models that will fit in RAM and found Llama3.2:1b (7 months old) and codegemma:2B (9 months old). One conversation and one code support. Nice.

I've been speculating about down-quantizing some slightly bigger models, but in the mean time I started playing around with the baby llama. I didn't want to challenge it with my usual questions for probing the weakness of larger and more powerful models, so I started by just asking it to tell me about the band Rush.

As models do, it then produced a bunch of plausible sounding text. Some of it was incomplete and some was simply wrong. For some reason it thinks Rush won more major award than they did. It seems to have selected exclusively praising text to reproduce (which is fine by me: I like the band and don't find most complaints directed at them to be at all convincing), but there is a non-trivial amount of criticism and none of it is represented or even acknowledged by the answer.

Now, let's be frank: there is a limit to how much factual detail you can expect to be encoded in what is, after all, a somewhat niche cultural subject when you have only two billion parameters available to try to represent a full cross section of English language knowledge. No general purpose model of this size is going to get everything right on a query of that kind. So, I'm not saying that the fact of errors is surprising or even interesting. But I am wondering what we can learn from the nature of the errors.

So let's look more closely at some of the errors. In its "Discography" section the model lists

  • Start with School Days (1974)
  • Caress of Steel (1975)
  • Fly by Night (1975)
  • 2112 (1976)
  • Two-Side Streets (1978)
  • Permanent Waves (1980)
  • Moving Pictures (1981)
  • Hold Your Fire (1987)
  • Presto (1997)
  • Test for Echo (2004)
  • Snakes & Arrows (2007)
  • Clockwork Angels (2012)

which has both omissions and errors.

I haven't the faintest clue what to make of the title mistake for the first album (which was 1974 but was self-titled). It's not the title of any Rush song or album that I'm aware of and a casual search of the web doesn't turn up any song or album by that name at all. The search does turn up a reasonable number of hits on Stanley Clarke's 1976 album School Days and a number of suggestions that people just beginning to explore Mr. Clarke's music should "Start with" that very same album. Interesting, but not terribly enlightening.

Nor do I have any theories concerning which albums are omitted. It doesn't look to me like the list is either the commercial hits or the fan favorites, and beyond that I don't know what patterns to look for.

But I do want to talk about the 1978 entry in the model's list. The proper album title for that year is Hemispheres.The thing that strikes me here is proper title and the substitute text share a conceptual relationship to the number two (two halves; two ways). My (admittedly wild) guess is that we're seeing a side affect of the model's attention system identifying "two" as an important concept to use when trying to infer tokens.

If true that would be interesting, because the attention system is one of the significant ways in which LLMs differ from Markov Chain generators. But it may also be responsible for the models difficulty in know what is a quotation and what is commentary which I've already discussed in the context of scientific papers.