Congratulations!

[Valid Atom 1.0] This is a valid Atom 1.0 feed.

Recommendations

This feed is valid, but interoperability with the widest range of feed readers could be improved by implementing the following recommendations.

Source: http://www.tbray.org/ongoing/ongoing.atom

  1. <?xml version='1.0' encoding='UTF-8'?>
  2. <feed xmlns='http://www.w3.org/2005/Atom'
  3.      xmlns:thr='http://purl.org/syndication/thread/1.0'
  4.      xml:lang='en-us'>
  5. <title>ongoing by Tim Bray</title>
  6. <link rel='hub' href='http://pubsubhubbub.appspot.com/' />
  7. <id>https://www.tbray.org/ongoing/</id>
  8. <link href='https://www.tbray.org/ongoing/' />
  9. <link rel='self' href='https://www.tbray.org/ongoing/ongoing.atom' />
  10. <link rel='replies'       thr:count='101'       href='https://www.tbray.org/ongoing/comments.atom' />
  11. <logo>rsslogo.jpg</logo>
  12. <icon>/favicon.ico</icon>
  13. <updated>2025-07-09T19:41:06-07:00</updated>
  14. <author><name>Tim Bray</name></author>
  15. <subtitle>ongoing fragmented essay by Tim Bray</subtitle>
  16. <rights>All content written by Tim Bray and photos by Tim Bray Copyright Tim Bray, some rights reserved, see /ongoing/misc/Copyright</rights>
  17. <generator uri='/misc/Colophon'>Generated from XML source code using Perl, Expat, Emacs, Mysql, Ruby, Java, and ImageMagick.  Industrial-strength technology, baby.</generator>
  18.  
  19. <entry>
  20. <title>QRS: Epsilon Wrangling</title>
  21. <link href='https://www.tbray.org/ongoing/When/202x/2025/07/07/Epsilon-Wrangling' />
  22. <link rel='replies'        thr:count='0'        type='application/xhtml+xml'        href='/ongoing/When/202x/2025/07/07/Epsilon-Wrangling#comments' />
  23. <id>https://www.tbray.org/ongoing/When/202x/2025/07/07/Epsilon-Wrangling</id>
  24. <published>2025-07-07T12:00:00-07:00</published>
  25. <updated>2025-07-09T19:41:00-07:00</updated>
  26. <category scheme='https://www.tbray.org/ongoing/What/' term='Technology/Quamina Diary' />
  27. <category scheme='https://www.tbray.org/ongoing/What/' term='Technology' />
  28. <category scheme='https://www.tbray.org/ongoing/What/' term='Quamina Diary' />
  29. <category scheme='https://www.tbray.org/ongoing/What/' term='Technology/Software' />
  30. <category scheme='https://www.tbray.org/ongoing/What/' term='Software' />
  31. <summary type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>I haven’t shipped any new features for     <a href='https://github.com/timbray/quamina'>Quamina</a> in many months, partly due to a flow of real-life distractions, but     also I’m up against tough performance problems in implementing     <a href='/ongoing/When/202x/2024/12/12/Quamina-Regular-Expression-Series'>Regular Expressions at massive scale</a>.     I’m still looking for a breakthrough, but have learned things about building and executing finite automata     that I think are worth sharing. This piece has to do with     <a href='https://en.wikipedia.org/wiki/Nondeterministic_finite_automaton#NFA_with_ε-moves'>epsilons</a>; anyone who has studied     finite automata will know about them already, but I’ll offer background for those people to skip</div></summary>
  32. <content type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>
  33.    <p>I haven’t shipped any new features for
  34.    <a href="https://github.com/timbray/quamina">Quamina</a> in many months, partly due to a flow of real-life distractions, but
  35.    also I’m up against tough performance problems in implementing
  36.    <a href="/ongoing/When/202x/2024/12/12/Quamina-Regular-Expression-Series">Regular Expressions at massive scale</a>.
  37.    I’m still looking for a breakthrough, but have learned things about building and executing finite automata
  38.    that I think are worth sharing. This piece has to do with
  39.    <a href="https://en.wikipedia.org/wiki/Nondeterministic_finite_automaton#NFA_with_ε-moves">epsilons</a>; anyone who has studied
  40.    finite automata will know about them already, but I’ll offer background for those people to skip.</p>
  41.    <p>I’ve written about this before in
  42.    <a href="/ongoing/When/202x/2024/06/17/Epsilon-Love">Epsilon Love</a>. A commenter pointed out that the definition of “epsilon”
  43.    in that piece is not quite right per standard finite-automata theory, but it’s still a useful in that it describes how
  44.    epsilons support constructs like the shell-style “<code>*</code>”.</p>
  45.    <h2 id='p-2'>Background</h2>
  46.    <p>Finite automata come in two flavors: Deterministic (DFA) and Nondeterministic (NFA).  DFAs move from state to state one input
  47.    symbol at a time: it’s simple and easy to understand and to implement.
  48.    NFAs have two distinguishing characteristics: First, when you’re in a
  49.    state and an input symbol arrives, you can transfer to more than one other state. Second, a state can have “epsilon transitions”
  50.    (let’s say “ε” for epsilon), which can happen any time at all while you’re in that state, input or no input.</p>
  51.    <p>NFAs are more complicated to traverse (will discuss below) but you need them if you want to
  52.    implement regular expressions with <code>.</code> and <code>?</code> and <code>*</code> and so on. You can turn any NFA into a
  53.    DFA, and I’ll come back to that subject in a future piece.</p>
  54.    <p>For implementing NFAs, I’ve been using
  55.    <a href="https://en.wikipedia.org/wiki/Thompson%27s_construction">Thompson's construction</a>, where
  56.    “Thompson” is
  57.    <a href="https://en.wikipedia.org/wiki/Ken_Thompson">Ken Thompson</a>, co-parent of Unix. This technique is also nicely
  58.    described by Russ Cox in
  59.    <a href="https://swtch.com/~rsc/regexp/regexp1.html">Regular Expression Matching Can Be Simple And Fast</a>. You don’t need to
  60.    learn it to understand this piece, but I’ll justify design
  61.    choices by saying “per Thompson”.</p>
  62.    <p>I’m going to discuss two specific issues today, ε-closures and a simpler NFA definition.</p>
  63.    <h2 id='p-3'>ε-closures</h2>
  64.    <p>To set the stage, consider this regexp: <nobr><code>A?B?C?X</code></nobr></p>
  65.    <p>It should match “X” and “BX” and “ACX” and so on, but not “CAX” or “XX”.
  66.    Thompson says that you implement <code>A?</code> with a
  67.    transition to the next state on “A” and another ε-transition to that next state; because if you see an “A” you should transition,
  68.    but then you can transition anyhow even if you don’t.</p>
  69.    <p>The resulting NFA looks like this:</p>
  70.    <img src="https://www.tbray.org/ongoing/When/202x/2025/07/07/AcmBcmCcmX.png" alt="NFA matching A?B?C?X" />
  71.    <p> In finite-automaton
  72.    math, states are usually represented by the letter “q” followed by a number (usually italicized and subscripted, like
  73.    <i>q<sub>0</sub></i>, but not here, sorry). Note <code>q4</code>’s double circle which means it’s
  74.    a goal state, i.e. if we get here we’ve matched the regexp.
  75.    I should add that this was produced with
  76.    <a href="https://draw.io">draw.io</a>, which seems to make this sort of thing easy.
  77.    </p>
  78.    <h2 id='p-5'>Back to that NFA</h2>
  79.    <p>So, here’s a challenge: Sketch out the traversal code in your head. Think about the input strings “AX” and “BCX” and just “X”
  80.    and how you’d get through the NFA to the Q4 goal state.</p>
  81.    <p>The trick is what’s called the ε-closure. When you get to a state, before you look at the next input symbol, you have to set
  82.    up to process it. In this case, you need to be able to transition on an A or B or C. So what you do is pull together the
  83.    start state <code>q0</code> and also any other states you can reach from there through ε-transitions. In this case, the ε-closure
  84.    for the start state is <code>{q0, q1, q2, q3}</code>.</p>
  85.    <p>Suppose, then, that you see a “B” input symbol. You apply it to all the states in the ε-closure. Only <code>q1</code> matches,
  86.    transitioning you to
  87.    <code>q2</code>. Before you look at the next input symbol, you compute the ε-closure for <code>q2</code>, which turns
  88.    out to be <code>{q2, q3}</code>. With this ε-closure, you can match “C” or “X”. If you get a “C”, you”ll step to
  89.    <code>q3</code>, whose ε-closure is just itself, because “X” is the only path forward.</p>
  90.    <p>So your NFA-traversal algorithm for one step becomes something like:</p>
  91.    <ol>
  92.      <li><p>Start with a list of states.</p></li>
  93.      <li><p>Compute the ε-closure of that list.</p></li>
  94.      <li><p>Read an input symbol.</p></li>
  95.      <li><p>For each state in the ε-closure, see if you can traverse to another state.</p></li>
  96.      <li><p>If so, add it to your output list of states.</p></li>
  97.      <li><p>When you’re done, your output list of states is the input to this algorithm for the next step.</p></li>
  98.    </ol>
  99.    <h2 id='p-6'>Computation issues</h2>
  100.    <p>Suppose your regular expression is <code>(A+BC?)+</code>. I’m not going to sketch out the NFA, but just looking at it tells
  101.    you that it has to have loopbacks; once you’ve matched the parenthetized chunk you need to go back to a state where you can
  102.    recognize another occurrence.
  103.    For this regexp’s NFA, computing the ε-closures can lead you into an infinite loop. (Should be obvious, but I didn’t realize it until
  104.    after the first time it happened.)</p>
  105.    <p>You can have loops and you can also have dupes. In practice, it’s not that uncommon for a state to have more than one
  106.    ε-transition, and for the targets of these transitions to overlap.</p>
  107.    <p>So you need to watch for loops and to dedupe your output. I think the only way to avoid this is with a cookie-crumbs
  108.    “where I’ve been” trail, either as a list or a hash table.</p>
  109.    <p>Both of these are problematic because they require allocating memory, and that’s something you really don’t want to do when
  110.    you’re trying to match patterns to events at Quamina’s historic rate of millions per second.</p>
  111.    <p>I’ll dig into this problem in a future Quamina-Diary outing, but obviously, caching computed
  112.    epsilon closures would avoid re-doing this computation.</p>
  113.    <p>Anyhow, bear ε-closures in mind, because they’ll keep coming up as this series goes on.</p>
  114.    <h2 id='p-7'>And finally, simplifying “NFA”</h2>
  115.    <p>At the top of this piece, I offered the standard definition of NFAs: First, when you’re in a
  116.    state and an input symbol arrives, you can transfer to more than one other state. Second, you can have ε-transitions.
  117.    Based on my recent work, I think this definition is redundant. Because if you need to transfer to two different states on some
  118.    input symbol, you can do that with ε-transitions.</p>
  119.    <p>Here’s a mini-NFA that transfers from state <code>q0</code> on “A” to both <code>q1</code> and <code>q2</code>.</p>
  120.    <img src="https://www.tbray.org/ongoing/When/202x/2025/07/07/Splice-1.png" alt="An NFA transferring to two different states on an input symbol" />
  121.    <p>And here’s how you can achieve the same effect with ε-transitions:</p>
  122.    <img src="https://www.tbray.org/ongoing/When/202x/2025/07/07/Splice-2.png" alt="Transferring to two destinations using ε-transitions" />
  123.    <p>In that NFA, in <code>qS</code> the “S” stands for “splice”, because it’s a state that exists to connect
  124.    two threads of finite-automaton traversal.</p>
  125.    <p>I’m pretty sure that this is more than just a mathematical equivalence. In my regexp implementation, so far at least,
  126.    I’ve never encountered a need to do that first kind of dual transition. Furthermore, the “splice” structure is how Thompson
  127.    implements the regular-expression “<code>|</code>” operator.</p>
  128.    <p>So if you’re building an NFA, all the traversal stuff you need in a state is a simple map from input symbol to next state,
  129.    and a list of ε-transitions.</p>
  130.    <h2 id='p-8'>Next up</h2>
  131.    <p>How my own implementation of NFA traversal collided head-on into the Benchmark From Hell and still hasn’t recovered.</p>
  132. </div></content></entry>
  133.  
  134. <entry>
  135. <title>The Real GenAI Issue</title>
  136. <link href='https://www.tbray.org/ongoing/When/202x/2025/07/06/AI-Manifesto' />
  137. <link rel='replies'        thr:count='8'        type='application/xhtml+xml'        href='/ongoing/When/202x/2025/07/06/AI-Manifesto#comments' />
  138. <id>https://www.tbray.org/ongoing/When/202x/2025/07/06/AI-Manifesto</id>
  139. <published>2025-07-06T12:00:00-07:00</published>
  140. <updated>2025-07-06T12:06:43-07:00</updated>
  141. <category scheme='https://www.tbray.org/ongoing/What/' term='Technology/AI' />
  142. <category scheme='https://www.tbray.org/ongoing/What/' term='Technology' />
  143. <category scheme='https://www.tbray.org/ongoing/What/' term='AI' />
  144. <summary type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>Last week I published a     <a href='/ongoing/When/202x/2025/07/01/First-AI-Code'>featherweight narrative</a> about applying GenAI in a real-world context, to     a tiny programming problem.  Now I’m regretting that piece because I totally ignored the two central issues with     AI: What it’s meant to do, and how much it really costs</div></summary>
  145. <content type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>
  146.    <p>Last week I published a
  147.    <a href="/ongoing/When/202x/2025/07/01/First-AI-Code">featherweight narrative</a> about applying GenAI in a real-world context, to
  148.    a tiny programming problem.  Now I’m regretting that piece because I totally ignored the two central issues with
  149.    AI: What it’s meant to do, and how much it really costs.</p>
  150.    <h2 id='p-1'>What genAI is for</h2>
  151.    <p>The most important fact about genAI in the real world is that there’ve been literally
  152.    <a href="https://finance.yahoo.com/news/how-nvidia-played-a-central-role-in-the-306-billion-ai-startup-boom-195741749.html?guccounter=1">hundreds
  153.    of billions</a> of dollars invested in it; that link is just startups, and ignores a comparable torrent of cash pouring out of Big
  154.    Tech.</p>
  155.    <p>The business leaders pumping all this money of course don’t understand the technology. They’re doing this for exactly one
  156.    reason: They think they can discard armies of employees and replace them with LLM services, at the cost of
  157.    shipping shittier products.  Do you think your management would spend that kind of money to help you with a quicker first draft or
  158.    a summarized inbox?</p>
  159.    <p>Adobe said the quiet part out loud:
  160.    <a href="https://petapixel.com/2024/05/03/adobe-throws-photographers-under-the-bus-again-skip-the-photoshoot/">Skip the
  161.    Photoshoot</a>. </p>
  162.    <p>At this point someone will point out that previous technology waves have generated as much employment as they’ve eliminated.
  163.    Maybe so, but that’s not what business leaders think they’re buying. They think they’re buying smaller payrolls.</p>
  164.    <p>Maybe I’m overly sensitive, but thinking about these truths leads to a mental stench that makes me want to stay away from
  165.    it.</p>
  166.    <h2 id='p-2'>How much does genAI cost?</h2>
  167.    <p>Well, I already mentioned all those hundreds of billions. But that’s pocket change. The investment community in general and
  168.    Venture Capital in particular will whine and moan, but the people who are losing the money are people who can afford to.</p>
  169.    <p>The first real cost is hypothetical: What if those business leaders are correct and they can gleefully dispose of millions of
  170.    employees? If you think we’re already suffering from egregious levels of inequality, what happens when a big chunk of the
  171.    middle class suddenly becomes professionally superfluous?  I’m no economist so I’ll stop there, but you don’t have to be a
  172.    rocket scientist to predict severe economic pain.</p>
  173.    <p>Then there’s the other thing that nobody talks about, the massive greenhouse-gas load that all those data centers are going
  174.    to be pumping out. This at a time when we we blow past one atmospheric-carbon metric after another and David Suzuki says
  175.    <a href="https://www.ipolitics.ca/2025/07/02/its-too-late-david-suzuki-says-the-fight-against-climate-change-is-lost/">the
  176.    fight against climate change is lost</a>, that we need to hunker down and work on survival at the local level.</p>
  177.    <h2 id='p-3'>The real problem</h2>
  178.    <p>It’s the people who are pushing it.  Their business goals are quite likely, as a side-effect, to make
  179.    the world a worse place, and they don’t give a fuck.  Their technology will inevitably worsen the onrushing climate catastrophe,
  180.    and they don’t give a fuck.</p>
  181.    <p>It’s probably not as simple as “They’re just shitty people”<span class='dashes'> —</span> it’s not exactly easy to escape the
  182.    exigencies of modern capitalism. But they are people who are doing shitty things.</p>
  183.    <h2 id='p-4'>Is genAI useful?</h2>
  184.    <p>Sorry, I’m having trouble even thinking about that now.</p>
  185. </div></content></entry>
  186.  
  187. <entry>
  188. <title>My First GenAI Code</title>
  189. <link href='https://www.tbray.org/ongoing/When/202x/2025/07/01/First-AI-Code' />
  190. <link rel='replies'        thr:count='3'        type='application/xhtml+xml'        href='/ongoing/When/202x/2025/07/01/First-AI-Code#comments' />
  191. <id>https://www.tbray.org/ongoing/When/202x/2025/07/01/First-AI-Code</id>
  192. <published>2025-07-01T12:00:00-07:00</published>
  193. <updated>2025-07-01T11:38:00-07:00</updated>
  194. <category scheme='https://www.tbray.org/ongoing/What/' term='Technology/AI' />
  195. <category scheme='https://www.tbray.org/ongoing/What/' term='Technology' />
  196. <category scheme='https://www.tbray.org/ongoing/What/' term='AI' />
  197. <category scheme='https://www.tbray.org/ongoing/What/' term='Technology/Software' />
  198. <category scheme='https://www.tbray.org/ongoing/What/' term='Software' />
  199. <summary type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>At the moment, we have no idea what the impact of genAI on software development is going to be. The impact of     <em>anything</em> on coding     is hard to measure systematically, so we rely on anecdata and the community’s eventual consensus.     So, here’s my anecdata. Tl;dr: The AI was not useless</div></summary>
  200. <content type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>
  201.    <p>At the moment, we have no idea what the impact of genAI on software development is going to be. The impact of
  202.    <em>anything</em> on coding
  203.    is hard to measure systematically, so we rely on anecdata and the community’s eventual consensus.
  204.    So, here’s my anecdata. Tl;dr: The AI was not useless.</p>
  205.    <h2 id='p-1'>The problem</h2>
  206.    <p>My current work on
  207.    <a href="/ongoing/What/Technology/Quamina%20Diary/">Quamina</a> involves dealing with collections of finite-automata states,
  208.    which, in the Go programming language, are represented as slices of pointers to state instances:</p>
  209.    <blockquote><p><code>[]*faState</code></p></blockquote>
  210.    <p>The problem I was facing was deduping them, so that there would be only one instance corresponding to any particular
  211.    collection. This is what, in Java, the <code>intern()</code> call does with strings.</p>
  212.    <p>The algorithm isn’t rocket science:</p>
  213.    <ol>
  214.      <li><p>Dedupe the states, i.e. turn the collection into a set.</p></li>
  215.      <li><p>For each set of states, generate a key.</p></li>
  216.      <li><p>Keep a hash table of sets around, and use the key to see whether you’ve already got such a set, and if so return
  217.      it. Otherwise, make a new entry in the hash table and return that.</p></li>
  218.    </ol>
  219.    <p>I’m out of touch with the undergrad CS curriculum, but this feels like a second-year assignment or thereabouts? Third?</p>
  220.    <h2 id='p-2'>Enter Claude</h2>
  221.    <p>So I prompted Claude thus:</p>
  222.    <blockquote><p>I need Go code to provide a "intern"-like function for lists of pointers. For example, if I have several
  223.    different []*int arrays, which may contain duplicates, I want to call intern() on each of them and get back a single canonical
  224.    pointer which is de-duplicated and thus a set.</p></blockquote>
  225.    <p>Claude did pretty well. It got the algorithm right, the code was idiomatic and usefully commented, and it also provided a
  226.    decent unit test (but in a <code>main()</code> stanza rather than a proper Go test file).
  227.    I didn’t try actually running it.</p>
  228.    <p>The interesting part was the key computation. I, being lazy, had just done a Go <code>fmt.Sprintf("%p")</code>
  229.    incantation to get a hex string representing each state’s address, sorted them, joined them, and that was the key.</p>
  230.    <p>Claude worked with the pointers more directly.</p>
  231.    <pre><code> // Sort by pointer address for consistent ordering
  232. sort.Slice(unique, func(i, j int) bool {
  233. return uintptr(unsafe.Pointer(unique[i])) &lt; uintptr(unsafe.Pointer(unique[j]))
  234. })</code></pre>
  235.    <p>Then it concatenated the raw bytes of the map addresses and lied to Go by claiming it was a string.</p>
  236.    <pre><code> // Create key from pointer addresses
  237. key := make([]byte, 0, len(slice)*8)
  238. for _, ptr := range slice {
  239. addr := uintptr(unsafe.Pointer(ptr))
  240. // Convert address to bytes
  241. for i := 0; i &lt; 8; i++ {
  242. key = append(key, byte(addr>>(i*8)))
  243. }
  244. }
  245. return string(key)</code></pre>
  246. <p>This is an improvement in that the keys will be half the size of my string version.
  247. I didn’t copy-paste Claude’s code wholesale, just replaced ten or so lines of key construction.</p>
  248.    <h2 id='p-3'>Take-away</h2>
  249.    <p>I dunno. I thought the quality of the code was fine, wouldn’t have decomposed the functions in the same way but wouldn’t have
  250.    objected on review. I was pleased with the algorithm, but then I would be since it was the same one I’d written, and, having
  251.    said that, quite possibly that’s the only algorithm that anyone has used. It will be <em>super</em> interesting if someone
  252.    responds to this write-up saying “You and Claude are fools, here’s a much better way.”</p>
  253.    <p>Was it worth fifteen minutes of my time to ask Claude and get a slightly better key computation?
  254.    Only if this ever turns out
  255.    to be a hot code path and I don’t think anybody’s smart enough to know that in advance.</p>
  256.    <p>Would I have saved time by asking Claude first? Tough to tell; Quamina’s data structures are a bit non-obvious and I would
  257.    have had to go to a lot of prompting work to get it to emit code I could use directly.
  258.    Also, since Quamina is low-level performance-critical infrastructure code, I’d be nervous about having any volume of code
  259.    that I didn’t really <em>really</em> understand.</p>
  260.    <p>I guess my take-away was that in this case, Claude knew the Go idioms and APIs better than I did; I’d never looked at the
  261.    <a href="https://pkg.go.dev/unsafe">unsafe</a> package.</p>
  262.    <p>Which reinforces my
  263.    suspicion that genAI is going to be especially useful at helping generate code to talk to big complicated
  264.    APIs that are hard to remember all of.  Here’s an example: Any moderately competent Android developer could add a feature to an
  265.    app where it strobes the flash and surges the vibration in sync with how fast you’re shaking the device back and forth,
  266.    probably in an afternoon. But it would require a couple of dozen calls into the dense forest of Android APIs, and I suspect a
  267.    genAI might get you there a lot faster by just filling the calls in as prompted.</p>
  268.    <p>Reminder: This is just anecdata.</p>
  269. </div></content></entry>
  270.  
  271. <entry>
  272. <title>Qobuz and Mac</title>
  273. <link href='https://www.tbray.org/ongoing/When/202x/2025/06/22/Qobuz-and-Others' />
  274. <link rel='replies'        thr:count='0'        type='application/xhtml+xml'        href='/ongoing/When/202x/2025/06/22/Qobuz-and-Others#comments' />
  275. <id>https://www.tbray.org/ongoing/When/202x/2025/06/22/Qobuz-and-Others</id>
  276. <published>2025-06-22T12:00:00-07:00</published>
  277. <updated>2025-06-26T13:13:08-07:00</updated>
  278. <category scheme='https://www.tbray.org/ongoing/What/' term='Arts/Music' />
  279. <category scheme='https://www.tbray.org/ongoing/What/' term='Arts' />
  280. <category scheme='https://www.tbray.org/ongoing/What/' term='Music' />
  281. <summary type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>Back in March I offered     <a href='/ongoing/When/202x/2025/03/27/Music-Plus-Qobuz'>Latest Music (feat. Qobuz)</a>, describing all the ways I listen to     music (Tl;dr: YouTube Music, Plex, Qobuz, record player). I stand by my opinions there but wanted to write more on two subjects:     First Qobuz, because it suddenly got a lot better. And a recommendation, for people with fancy A/V setups, that you include a cheap     Mac Mini</div></summary>
  282. <content type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>
  283.    <p>Back in March I offered
  284.    <a href="/ongoing/When/202x/2025/03/27/Music-Plus-Qobuz">Latest Music (feat. Qobuz)</a>, describing all the ways I listen to
  285.    music (Tl;dr: YouTube Music, Plex, Qobuz, record player). I stand by my opinions there but wanted to write more on two subjects:
  286.    First Qobuz, because it suddenly got a lot better. And a recommendation, for people with fancy A/V setups, that you include a cheap
  287.    Mac Mini.</p>
  288.    <h2 id='p-1'>Qobuz</h2>
  289.    <p>That other piece had a list of the reasons to use Qobuz, but times have changed, so let’s revise it:</p>
  290.    <ol>
  291.      <li><p>It pays artists more per stream than any other service, by a wide margin.</p></li>
  292.      <li><p>It seems to have as much music as anyone else.</p></li>
  293.      <li><p>It’s album-oriented, and I appreciate artists curating their own music.</p></li>
  294.      <li><p>Classical music is a first-class citizen.</p></li>
  295.      <li><p>It’s actively curated; they highlight new
  296.      music regularly, and pick a “record of the week”. To get a feel, check out
  297.      <a href="https://www.qobuz.com/ca-en/magazine">Qobuz Magazine</a>; you don’t have to be a subscriber.</p></li>
  298.      <li><p>It gives evidence of being built by people who love music.</p></li>
  299.      <li><p>They’re obsessive about sound quality, which is great, but only makes a difference if you’re listening through quality
  300.      speakers.</p></li>
  301.      <li><p>A few weeks ago, the mobile app quality switched from adequate to
  302.      excellent.</p></li>
  303.    </ol>
  304.    <h2 id='p-2'>That app</h2>
  305.    <p>I want to side-trip a bit here, starting with a question. How long has it been since an app you use has added a feature that
  306.    was genuinely excellent and let you do stuff you couldn’t before and didn’t get in your way and created no suspicion that it was
  307.    strip-mining your life for profit?  I’m here to tell you that this can still happen, and it’s a crushing criticism
  308.    of my profession that it so rarely does.</p>
  309.    <p>I’m talking about
  310.    <a href="https://www.qobuz.com/ca-en/connect">Qobuz Connect</a>. I believe there are other music apps that can do this sort of
  311.    stuff, but it feels like magic to me.</p>
  312.    <p>It’s like this. I listen to music at home on an audiophile system with big speakers, in
  313.    <a href="/ongoing/What/The%20World/Jaguar%20Diary/">our car</a>, and on
  314.    <a href="/ongoing/When/201x/2019/08/06/Jeanneau-795">our boat</a>.  The only app I touch is the
  315.    <a href="https://play.google.com/store/apps/details?id=com.qobuz.music">Qobuz Android app</a>. The only time it’s actually
  316.    receiving and playing the music itself is in the car, with the help of Android Auto.  In the other scenarios it’s talking to
  317.    Qobuz running on a Mac, which actually fetches the music and routes it to the audio system.
  318.    Usually it figures out what player I want it to control automatically, although there’ve been a couple
  319.    times when I drove away in the car and it got confused about where to send the music. Generally, it works great.</p>
  320.    <p>The app’s music experience is rich and involving.</p>
  321.    <img src="https://www.tbray.org/ongoing/When/202x/2025/06/22/Screenshot_20250622-230116.png" alt="Qobuz Android app screenshot" />
  322.    <p>It has New Releases and curated playlists and a personalized stream for
  323.    me and a competent search function for those times I absolutely must listen to Deep Purple or Hania Rani or
  324.    whoever.</p>
  325.    <p>I get a chatty not-too-long email from Qobuz every Friday, plugging a few of the week’s new releases, with sideways and
  326.    backward looks too. (This week: A Brian Wilson stream.) The app has so much stuff, especially among the themed streams, that I
  327.    sometimes get lost. But somehow it’s not irritating; what’s on the screen remains musically interesting and you can always hit
  328.    the app’s Home button.</p>
  329.    <p>Qobuz has its own musical tastes that guide its curation. They’re not always compatible with
  330.    mine<span class='dashes'> —</span> my tolerance for EDM and mainstream Hip-hop remains low. And I wish they were
  331.    stronger on Americana. But the intersection is broad enough to provide plenty of enjoyable new-artist experiences. Let me share
  332.    one with you:
  333.    <a href="https://kwashibu.bandcamp.com/album/love-warrior-s-anthem">Kwashibu Area Band</a>, from Ghana.</p>
  334.    <p>Oh, one complaint: Qobuz was eating my Pixel’s battery. So I poked around online and it’s a known problem; you have to use the
  335.    Android preferences to stop it from running in the background. Huh? What was it doing in the background anyhow?! But it seems to
  336.    work fine even when it’s not doing it.</p>
  337.    <h2 id='p-3'>A Mac, you say?</h2>
  338.    <p>The music you’re listening to is going to be stored on disk, or incoming from a streaming service. Maybe you want to serve
  339.    some of the stored music out to listen to it in the car or wherever. There are a variety of audio products in the
  340.    “Streamer” category that do some of these things in various combinations. A lot of them make fanciful claims about the
  341.    technology inside and are thus expensive, you can easily spend thousands.</p>
  342.    <p>But any reasonably modern computer can do all these things and more, plus it also can drive a big-screen display, plus it will
  343.    probably run the software behind whatever next year’s New Audio Hotness is.</p>
  344.    <p>At this point the harder-core geeks will adopt a superior tone of voice to say “I do all that stuff with FreeBSD and a bunch of
  345.    open-source packages running on a potato!”</p>
  346.    <p>More power to ’em. But I recommend a basic Apple Silicon based Mac Mini, M1 is fine, which you can get for like $300 used on
  347.    eBay. And if you own a lot of music and video you can plug in a 5T USB drive for a few more peanuts. This will run Plex and
  348.    Qobuz and almost any other imaginable streaming software. Plus you can plug it into your home-theater screen and it has a modern
  349.    Web browser so you can also play anything from anywhere on the Web.</p>
  350.    <p>I’ve been doing this for a while but I had one big gripe. When I wanted to stream music from the Mac, I needed to use a
  351.    keyboard and mouse, so I keep one of each, Bluetooth-flavored, nearby. But since I got Qobuz running that’s become a very rare
  352.    occurrence.</p>
  353.    <h2 id='p-4'>You’re forgetting something</h2>
  354.    <p>Oh, and yeah, there’s the record player. Playing it requires essentially no software at all, isn’t that great?</p>
  355. </div></content></entry>
  356.  
  357. <entry>
  358. <title>Long Links</title>
  359. <link href='https://www.tbray.org/ongoing/When/202x/2025/06/21/Long-Links' />
  360. <link rel='replies'        thr:count='6'        type='application/xhtml+xml'        href='/ongoing/When/202x/2025/06/21/Long-Links#comments' />
  361. <id>https://www.tbray.org/ongoing/When/202x/2025/06/21/Long-Links</id>
  362. <published>2025-06-21T12:00:00-07:00</published>
  363. <updated>2025-06-21T11:56:27-07:00</updated>
  364. <category scheme='https://www.tbray.org/ongoing/What/' term='The World' />
  365. <category scheme='https://www.tbray.org/ongoing/What/' term='The World' />
  366. <summary type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>“Wow, Tim, didn’t you do a      <a href='/ongoing/When/202x/2025/05/06/Long-Links'>Long Links</a> just last month? Been spending too much time doomscrolling,     have we?” Maybe. There sure are a lot of tabs jostling each other along the top of that browser. Many     are hosting works that are both long and good. So here they are; you probably don’t have time for all of ’em but my hope     is that one or two might reward your visit</div></summary>
  367. <content type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>
  368.    <p>“Wow, Tim, didn’t you do a
  369.    <a href="/ongoing/When/202x/2025/05/06/Long-Links">Long Links</a> just last month? Been spending too much time doomscrolling,
  370.    have we?” Maybe. There sure are a lot of tabs jostling each other along the top of that browser. Many
  371.    are hosting works that are both long and good. So here they are; you probably don’t have time for all of ’em but my hope
  372.    is that one or two might reward your visit.</p>
  373.    <p>Let’s start with a really important subject: Population growth oh actually these days it’s population shrinkage.
  374.    For a short-sharp-shock-flavored introduction I recommend
  375.    <a href="https://www.youtube.com/watch?v=Ufmu1WD2TSk">South Korea Is Over</a>
  376.    which explains the brick wall societies with fertility rates way below the replacement rate of 2.1 children per woman per
  377.    lifetime are hurtling toward. South Korea, of course, being the canonical example. But also Japan and Taiwan and Italy and Spain
  378.    and so on.</p>
  379.    <p>And, of course, the USA, where the numbers aren’t <em>that</em> much higher:
  380.    <a href="https://www.macrotrends.net/global-metrics/countries/usa/united-states/fertility-rate">U.S. Fertility Rate
  381.    (1950-2025)</a>. Even so, the population still grows (because of immigration), albeit at less than 1% per annum:
  382.    <a href="https://www.macrotrends.net/global-metrics/countries/usa/united-states/population-growth-rate">U.S. Population Growth
  383.    Rate</a>. If the MAGAs get their way and eventually stop all non-white immigration, the US will be in South Korea
  384.    territory within a generation or two. </p>    
  385.    <p>A reasonable person might ask why. It’s not really complicated, as you can read here:
  386.    <a href="https://www.nytimes.com/2025/06/15/opinion/birth-rate-parenting-natalism.html?unlocked_article_code=1.Pk8.OBam.dOi0UpP-8-DV&amp;smid=url-share">A Bold Idea to Raise the Birthrate: Make Parenting Less Torturous</a>.
  387.    From which I quote: “To date, no government policies have significantly improved their nation’s birthrates for a sustained
  388.    period.” The essay argues convincingly that it’s down to two problems: Capitalism and sexism. Neither of which offers an easy
  389.    fix. </p>
  390.    <p>Speaking of the travails of late capitalism, here’s how bad it’s getting:
  391.    <a href="https://www.nytimes.com/2025/03/01/opinion/crisis-working-homeless.html?unlocked_article_code=1.Qk8.jsTO.aUBSAMHw7Op2&amp;smid=url-share">America
  392.    Is Pushing Its Workers Into Homelessness</a>.</p>
  393.    <p>For a refreshingly different take on the business world, here’s Avery Pennarun, CEO of Tailscale:
  394.    <a href="https://apenwarr.ca/log/20250530">The evasive evitability of enshittification</a>. Not sure I buy what he’s saying, but
  395.    still worth reading.</p>
  396.    <p>Most people who visit these pages are geeks or geek-adjacent. If you’re one of those, and especially if you enjoy the small
  397.    but vibrant genre of Comical Tech War Stories, I recommend
  398.    <a href="https://yeet.cx/blog/lock-free-rust/">Lock-Free Rust: How to Build a Rollercoaster
  399.    While It’s on Fire</a></p>
  400.    <p>And here’s write-up on an AWS product which has one of the best explanations I’ve ever read of the different flavors modern
  401.    databases come in: <a href="https://www.redshift-observatory.ch/white_papers/downloads/introduction_to_the_fundamentals_of_amazon_redshift.html">Introduction to the Fundamentals of Amazon Redshift</a></p>
  402.    <p>Of course, the geek conversation these days is much taken up with the the impact of genAI as in “vibe coding”. To
  403.    summarize the conversation: A few people, not obviously fools,  are saying “This stuff seems to help me” and many others, also
  404.    apparently sensible, are shouting back “You’re lying to yourself, it can’t be helping!”  Here is some of the testimony:
  405.    Kellan on <a href="https://laughingmeme.org//2025/05/25/vibe-coding-for-teams.html">Vibe
  406.    coding for teams, thoughts to date</a>, Armin Ronacher on
  407.    <a href="https://lucumr.pocoo.org/2025/6/12/agentic-coding/">Agentic Coding Recommendations</a>,
  408.    Harper on <a href="https://harper.blog/2025/05/08/basic-claude-code/">Basic Claude Code</a>, and
  409.    Klabnik on
  410.    <a href="https://steveklabnik.com/writing/a-tale-of-two-claudes/">A tale of two Claudes</a></p>
  411.    <p>I lean to believing narratives of personal experience, but on the other hand the skeptics make good points. Another
  412.    random piece of evidence: Because I’m lazy, I tend to resist adopting technologies that have steep learning curves, which genAI
  413.    currently does. On many occasions, this has worked out well because those technologies have turned out not to pay off very
  414.    well. Am I a canary in the coal mine?</p>
  415.    <h2 id='p-2'>*cough*</h2>
  416.    <p>Since I introduced myself into the narrative, I’ll note that today is my 70th birthday. I am told that this means
  417.    that my wisdom has now been maximized, so you’re safe in believing whatever you read in this space.  I don’t have anything
  418.    special to say to commemorate the occasion,
  419.    so here’s a picture of my neighborhood’s network infrastructure, which outlines the form of a
  420.    cathedral’s nave. I’m sure there’s a powerful metaphor lurking in there.</p>
  421.    <img src="https://www.tbray.org/ongoing/When/202x/2025/06/21/TXT55659.png" alt="Many electrical and data wires festoon a back alley" />    
  422.    <p>Oh, and here’s a photography Long Link: <a href="https://www.lux.camera/what-is-hdr/">What is HDR, anyway?</a>
  423.    It’s actually a pitch for a nice-looking mobile camera app, but it offers real value on things that can
  424.    affect the quality of your pictures.</p>
  425.    <p>Regular readers will know that I’m fascinated by the many unsolved issues and open questions in cosmology, which are by
  426.    definition the largest problems facing human consciousness. The ΛCDM-vs-MOND controversy, i.e. “Is there really dark
  427.    matter or does gravity get weird starting at the outer edges of galaxies?”, offers great entertainment value. And, there is
  428.    news!</p>
  429.    <p>First of all, here’s a nice overview on the controversy:
  430.    <a href="https://arxiv.org/pdf/2505.21638v1">Modified Newtonian Dynamics: Observational Successes and Failures</a>.</p>
  431.    <p>Which points out that the behavior of “wide binary” star systems ought to help resolve the issue, but that people who
  432.    study it keep coming up with contradictory findings. Here’s the latest, from Korean researchers: Press release
  433.    <a href="http://www.sejongpr.ac.kr/sejongnewspaperview.do?currentPage=1&amp;searchField=&amp;searchValue=&amp;boardType=3&amp;pkid=73549&amp;utm_source=beehiiv&amp;utm_medium=newsletter&amp;utm_campaign=mediamobilize&amp;_bhlid=3e40dce99e536f4015a1dd2c6afd193a465d17ea">New method of measuring gravity with 3D velocities of wide binary stars is developed and confirms modified gravity</a>
  434.    and peer-reviewed paper:
  435.    <a href="https://iopscience.iop.org/article/10.3847/1538-4357/adce09">Low-acceleration Gravitational Anomaly
  436.    from Bayesian 3D Modeling of Wide Binary Orbits: Methodology and Results with Gaia Data Release 3</a>.
  437.    Spoiler: They think the gravity gets weird. I have a math degree but cosmology math is generally way over my head. Having said
  438.    that, I think those South Koreans may be a bit out over their skis; I generally distrust heroic statistical methods. We’ll
  439.    see.</p>
  440.    <p>Let’s do politics. It turns out that the barbaric junta which oppresses the people of China does not limit its barbarism
  441.    to its own geography:
  442.    <a href="https://www.cbc.ca/news/politics/china-targets-dissidents-canada-1.7543745?cmp=rss">Followed, threatened and smeared
  443.    — attacks by China against its critics in Canada are on the rise</a>.</p>
  444.    <p>More politics: The MAGAs are always railing against “elites”. Here are two discussions of what they mean:
  445.    <a href="https://www.theatlantic.com/ideas/archive/2025/04/class-money-finances/682301/">What the Comfort Class Doesn’t
  446.    Get</a> and <a href="https://siderea.dreamwidth.org/1865048.html">When They Say Elites, They Mean Us</a>.</p>
  447.    <p>The world’s biggest political issue <em>should</em> be the onrushing climate crisis. When Trump and his toadies
  448.    are justly condemned and ridiculed by future historians, it is their malevolent cluelessness on this subject that
  449.    may burn the hottest. Who knows, maybe they’ll pay attention to this:
  450.    <a href="https://www.bloomberg.com/news/newsletters/2025-06-18/insurers-want-businesses-to-wake-up-to-costs-of-extreme-heat">Insurers Want Businesses to Wake Up to Costs of Extreme Heat</a>.</p>
  451.    <h2 id='p-1'>The list of Long Links is too long</h2>
  452.    <p>So I’ll try to end cheerfully.</p>
  453.    <p>A graceful essay about an old camera and a dreamy picture:
  454.    <a href="https://petapixel.com/2025/05/27/a-bridge-across-time-for-sebastiao-salgado/">A Bridge Across Time: For
  455.    Sebastião Salgado</a></p>
  456.    <p>Latin Wikipedia has 140,000 articles; consider the delightful discussion of
  457.    <a href="https://la.wikipedia.org/wiki/Equus_asinus"><cite>Equus asinus</cite></a>.</p>
  458.    <img src="https://www.tbray.org/ongoing/When/202x/2025/06/21/equus-asinus.png" alt="Asinus in opere tesselato Byzantino" />
  459.    <div class='caption'><p>Asinus in opere tesselato Byzantino</p></div>
  460.    <p>Here’s a lovely little song from TORRES and Julien Baker:
  461.    <a href="https://www.youtube.com/watch?v=TurU_Jn-LEg">The Only Marble I’ve Got Left</a>.</p>
  462.    <p>Finally, a clear-eyed if lengthy essay on why and how to think:
  463.    <a href="https://www.newyorker.com/culture/open-questions/should-you-question-everything">Should You Question
  464.    Everything?</a></p>
  465. </div></content></entry>
  466.  
  467. <entry>
  468. <title>June 2025 C2PA News</title>
  469. <link href='https://www.tbray.org/ongoing/When/202x/2025/06/17/More-C2PA' />
  470. <link rel='replies'        thr:count='1'        type='application/xhtml+xml'        href='/ongoing/When/202x/2025/06/17/More-C2PA#comments' />
  471. <id>https://www.tbray.org/ongoing/When/202x/2025/06/17/More-C2PA</id>
  472. <published>2025-06-17T12:00:00-07:00</published>
  473. <updated>2025-06-19T09:20:16-07:00</updated>
  474. <category scheme='https://www.tbray.org/ongoing/What/' term='Technology/Identity' />
  475. <category scheme='https://www.tbray.org/ongoing/What/' term='Technology' />
  476. <category scheme='https://www.tbray.org/ongoing/What/' term='Identity' />
  477. <summary type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>Things are happening in the C2PA world; here are a couple of useful steps forward, plus cheers and boos for Adobe.     Plus a live working C2PA demo you can try out</div></summary>
  478. <content type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>
  479.    <p>Things are happening in the C2PA world; here are a couple of useful steps forward, plus cheers and boos for Adobe.
  480.    Plus a live working C2PA demo you can try out.</p>
  481.    <p>Refresher: The
  482.    <a href="https://c2pa.org/">C2PA</a> technology is driven by the
  483.    <a href="https://contentauthenticity.org/">Content Authenticity Initiative</a> and usually marketed as “Content Credentials”.
  484.    I’ve written before about it, an
  485.    <a href="/ongoing/When/202x/2023/10/28/C2PA-Workflows">introduction in 2023</a> and a
  486.    <a href="/ongoing/When/202x/2024/10/29/Lane-Provenance">progress report</a> last October.</p>
  487.    <p>Let’s start with a picture.</p>
  488.    <img src="https://www.tbray.org/ongoing/When/202x/2025/06/17/TXT55648.png" alt="A dark picture full of vague swirls and jiggly lights" />
  489.    <div class='caption'><p>I was standing with the camera by the ocean at dusk and accidentally left it in the “B” long-exposure
  490.    setting, so this isn’t really a picture <em>of</em> anything but I thought it was kinda pretty.</p></div>
  491.    <h2 id='p-1'>Validating Content Credentials</h2>
  492.    <p>As I write this, there are now at least two C2PA-validator Chrome extensions: the
  493.    <a href="https://chromewebstore.google.com/detail/contentlens-c2pa-validato/gdejpnjeepoffhkbcgnjdbkgpohdhmln?hl=en">ContentLens
  494.    C2PA Validator</a> from
  495.    <a href="https://www.contentlens.ai/">ContentLens</a> and
  496.    <a href="https://chromewebstore.google.com/detail/c2pa-content-credentials/mjkaocdlpjmphfkjndocehcdhbigaafp?hl=en">C2PA Content
  497.    Credentials</a> from
  498.    <a href="https://www.digimarc.com/">Digimarc</a>.</p>
  499.    <img src="https://www.tbray.org/ongoing/When/202x/2025/06/17/cc-readout.png" alt="C2PA verifier display" class="inline" />
  500.    <img src="https://www.tbray.org/ongoing/When/202x/2025/06/17/cc2-readout.png" alt="C2PA verifier display" class="inline" />
  501.    <p>If you install either of them, and then you click on that picture just above in Chrome to get the larger version, then you
  502.    right-click on the larger picture, the menu will offer Content-Credentials validation.</p>
  503.    <p>Doing this will produce a little
  504.    “CR” logo at the top right corner, meaning that the C2PA data has been
  505.    verified as being present and signed by a trusted certificate issuer, in this case Adobe.</p>
  506.    <p>Then there’s a popup; the two extensions’ are on the right. They’re different, in interesting ways. Let’s walk through the
  507.    second one.</p>
  508.    <p>The little thumbnail at the top of the popup is what the image looked like when the C2PA was added. Not provided by the other
  509.    verifier.</p>
  510.    <p>The paragraph beginning “Displaying credentials…” says that the C2PA manifest was embedded in the JPG as opposed to stored
  511.    out on the
  512.    cloud; The cloud works fine, and is perhaps a good idea because the C2PA manifest can be quite large. I’m not clear on what the
  513.    “watermark” is about.</p>
  514.    <p>“Issued by Adobe” means that the Chrome extension verified the embedded C2PA against Adobe’s public key and can be
  515.    confident that yes, this was really signed by them.</p>
  516.    <p>“<b>Produced by</b> Timothy Bray” is interesting. How can it know? Well, it turns out that it used LinkedIn’s API to verify
  517.    that I am
  518.    <a href="https://www.linkedin.com/in/timbraysoftwareguy/">timbraysoftwareguy</a> over on LinkedIn. But it goes further; LinkedIn
  519.    has an integration with
  520.    <a href="https://www.clearme.com">Clear</a>, the airport-oriented identity provider. To get a Clear account you have to upload
  521.    government-issued ID, it’s not trivial.</p>
  522.    <p>So this short sentence expands to (take a deep breath) “The validator extension verified that Adobe said that
  523.    LinkedIn said that Clear said that the government ID of the person who posted this says that he’s named Timothy Bray.”</p>
  524.    <p>Note that the first extension’s popup also tells you that Adobe has verified what my LinkedIn and Instagram accounts
  525.    are. This seems super-useful and I wonder why the other omits it.</p>
  526.    <p>“<b>App or device used</b>…” is simple enough, but I’m not actually sure how it works; I guess Adobe has embedded a keypair
  527.    in my Lightroom installation? If I’d taken the picture with a C2PA-equipped camera this is where that history would be
  528.    displayed.</p>
  529.    <p>“<b>AI tool used</b> None”. Interesting and useful, since Adobe provides plenty of genAI-powered tools. Of course, this
  530.    relies on Lightroom telling the truth, but still.</p>
  531.    <p>The “View More” button doesn’t currently work; it takes you to the interactive
  532.    <a href="https://contentcredentials.org/verify/">contentcredentials.org/verify</a> page,
  533.    which seems to fail in retrieving the JPG. If you download the picture then upload it into the verify page (go ahead, it’s
  534.    free)
  535.    that seems to work fine. In addition to the info on the popup, the verify page will tell you (nontechically i.e. vaguely) what I
  536.    did to the picture with Lightroom.</p>
  537.    <h2 id='p-3'>What’s good about this?</h2>
  538.    <p>Well, it’s here and it works! There’s all this hype about how cool it will be when the C2PA includes info about what model
  539.    of camera and lens it used and what the shutter speed was and so on, but eh, who cares really? What matters to me (and
  540.    should matter to the world) is <em>provenance</em>: Who posted this thing?</p>
  541.    <p>As I write this, supporters of Israel and Iran are
  542.    <a href="https://www.404media.co/the-ai-slop-fight-between-iran-and-israel/?ref=daily-stories-newsletter">having an AI Slop
  543.    Fight</a> with fake war photos and videos.
  544.    In a C2PA-rich world, you could check; If some clip doesn’t have Content Credentials you should
  545.    probably be suspicious, and if it does, it matters whether it was uploaded by someone at
  546.    <a href="https://www.idf.il/en/">IDF.il</a> versus
  547.    <a href="https://www.bbc.com">BBC.co.uk</a>.</p>
  548.    <h2 id='p-2'>What’s wrong with this?</h2>
  549.    <p>Look, I hate to nitpick. I’m overwhelmingly positive on this news, it’s an existence proof that C2PA can be made to work in
  550.    the wild.
  551.    My impression is that most of the money and muscle comes from Adobe; good on ’em.
  552.    But there are things that would make it more useful, and usable by more Web sites. These are not listed in
  553.    any particular order.</p>
  554.    <h2 id='p-7'>Identity!</h2>
  555.    <p>Adobe, it’s nice that you let me establish my identity with LinkedIn, Instagram, and Clear. But what I’d
  556.    <em>really</em> like is if you could also verify and sign my Fediverse and Bluesky handles. And, Fediverse and ATProto
  557.    developers, would you please, first of all, stop stripping C2PA manifests from uploaded photo EXIF, and secondly, add your own
  558.    link to the C2PA chain saying something like “Originally posted by @timbray@cosocial.ca.”</p>
  559.    <p>Because having verifiable media provenance in the world of social media would be a strong tool against disinformation
  560.    and slop.</p>
  561.    <p>Oh, and another note to Adobe: When I export a photo, the embed-manifest also offers me the opportunity, under the heading
  562.    “Web3”, to allow the image “be used for NFT creative attribution on supported marketplaces” where the supported marketplaces are
  563.    Phantom and MetaMask. Seriously, folks, in 2025? Please get this scammy cryptoslime out of my face.</p>
  564.    <h2 id='p-4'>Browsers please…</h2>
  565.    <p>This was done with Chrome extensions. There are people working on extensions for Firefox and
  566.    Safari, but they’re not here yet. Annoyingly, the extensions also don’t seem to work in mobile Chrome, which is where most
  567.    people look at most media.</p>
  568.    <p>I would love it if this were done directly and automatically by the browser.
  569.    The major browsers aren’t perfect, but their creators are known to take security seriously, and I’d be much happier trusting
  570.    one of them, rather than an extension from a company I’d never previously heard of.</p>
  571.    <h2 id='p-8'>… or maybe JavaScript?</h2>
  572.    <p>The next-best solution would be a nice JS package that just Does The Right
  573.    Thing. It should work like the way I do fonts: If you look in the source for the page you are now reading, the splodge of JS at
  574.    the top includes a couple of lines
  575.    that mention “typekit.com”. Typekit (since acquired by Adobe) offers access to a huge selection of excellent fonts.
  576.    Those JS invocations result in the text you are now reading being displayed in
  577.    <a href="/ongoing/When/201x/2011/07/17/Tisa">FF Tisa Web Pro</a>.</p>
  578.    <p>Which<span class='dashes'> —</span> this is important<span class='dashes'> —</span> is not free. And to be clear, I am
  579.    willing to pay to get Content Credentials for the pictures on this blog. It feels exactly like paying a small fee for access to
  580.    a professionally-managed font library.
  581.    Operating a Content-Credentials service wouldn’t be free, it’d require running a
  582.    server and wrangling certs. At scale, though, it should be pretty cheap.</p>
  583.    <p>So here’s an offer: If someone launches a service that allows me to straightforwardly include the
  584.    fact that this picture was sourced from tbray.org in my Content Credentials, my wallet is (modestly) open.</p>
  585.    <p>By the way, the core JavaScript code is already under construction; here’s
  586.    <a href="https://github.com/microsoft/c2pa-extension-validator">Microsoft</a> and the
  587.    <a href="https://opensource.contentauthenticity.org/docs/introduction">Content Authority Initiative</a> itself.
  588.    There’s also a Rust crate for server-side use, and a “c2patool” command-line utility based on it..</p>
  589.    <h2 id='p-6'>Open-Source issues</h2>
  590.    <p>You’ll notice that the right-click-for-Content-Credentials doesn’t work on the smaller version of the picture embedded in the
  591.    text you are now reading; just the larger one.  This is because the decades-old Perl-based <span class='o'>ongoing</span>
  592.    publishing software runs the main-page pictures through
  593.    <a href="https://imagemagick.org/index.php">ImageMagick</a>, which doesn’t do C2PA. I should find a way to route around this.</p>
  594.    <p>In fact, it wouldn’t be rocket science for ImageMagick (or open-source packages generally) to write C2PA manifests and insert
  595.    them in the media files they create.  But how should they sign them? As noted, that requires a server that provides cert-based
  596.    signatures, something that nobody would expect from even well-maintained open-source packages.</p>
  597.    <p>I dunno, maybe someone should provide a managed-ImageMagick service that (for a small fee) offers signed-C2PA-manifest
  598.    embedding?</p>
  599.    <h2 id='p-9'>What’s next?</h2>
  600.    <p>The work that needs to be done is nontrivial but, frankly, not that taxing. And the rewards would be high.
  601.    Because it feels like a no-brainer that knowing who posted something is a big deal. Also the inverse: Knowing that you
  602.    <em>don’t</em> know who posted it.</p>
  603.    <p>Where is it an especially big deal? On social media, obviously. It’s really time for those guys to start climbing on board.</p>
  604. </div></content></entry>
  605.  
  606. <entry>
  607. <title>AI Angst</title>
  608. <link href='https://www.tbray.org/ongoing/When/202x/2025/06/06/My-AI-Angst' />
  609. <link rel='replies'        thr:count='13'        type='application/xhtml+xml'        href='/ongoing/When/202x/2025/06/06/My-AI-Angst#comments' />
  610. <id>https://www.tbray.org/ongoing/When/202x/2025/06/06/My-AI-Angst</id>
  611. <published>2025-06-06T12:00:00-07:00</published>
  612. <updated>2025-06-08T15:39:49-07:00</updated>
  613. <category scheme='https://www.tbray.org/ongoing/What/' term='Technology/AI' />
  614. <category scheme='https://www.tbray.org/ongoing/What/' term='Technology' />
  615. <category scheme='https://www.tbray.org/ongoing/What/' term='AI' />
  616. <summary type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>My input stream is full of it: Fear and loathing and cheerleading and prognosticating on what generative AI means and whether     it’s Good or Bad and what we should be doing. All the channels: Blogs and peer-reviewed papers and social-media posts and     business-news stories. So there’s lots of AI angst out there, but this is mine.     I think the following is a bit unique because it focuses on cost, working backward from there. As for the     genAI tech itself, I guess I’m a moderate; there is a there there, it’s not all slop. But first…</div></summary>
  617. <content type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>
  618.    <p>My input stream is full of it: Fear and loathing and cheerleading and prognosticating on what generative AI means and whether
  619.    it’s Good or Bad and what we should be doing. All the channels: Blogs and peer-reviewed papers and social-media posts and
  620.    business-news stories. So there’s lots of AI angst out there, but this is mine.
  621.    I think the following is a bit unique because it focuses on cost, working backward from there. As for the
  622.    genAI tech itself, I guess I’m a moderate; there is a there there, it’s not all slop. But first…</p>
  623.    <h2 id='p-5'>The rent is too damn high</h2>
  624.    <p>I promise I’ll talk about genAI applications but let’s start with money. <em>Lots</em> of money, big numbers! For example,
  625.    venture-cap startup money pouring into AI, which as of now apparently adds up to
  626.    <a href="https://finance.yahoo.com/news/how-nvidia-played-a-central-role-in-the-306-billion-ai-startup-boom-195741749.html">$306
  627.    billion</a>. And that’s just startups; Among the giants, Google alone
  628.    <a href="https://www.ciodive.com/news/google-cloud-generative-ai-data-center-capacity-buildouts/739357/">apparently plans
  629.    $75B</a> in capital expenditure on AI
  630.    infrastructure, and they represent maybe a quarter at most of cloud capex. You think those are big numbers? McKinsey offers
  631.    <a href="https://www.mckinsey.com/industries/technology-media-and-telecommunications/our-insights/the-cost-of-compute-a-7-trillion-dollar-race-to-scale-data-centers">The cost of compute: A $7 trillion race to scale data centers</a>.</p>
  632.    <p>Obviously, lots of people are
  633.    wondering when and where the revenue will be to pay for it all. There’s one thing we know for sure:
  634.    The pro-genAI voices are fueled by hundreds of billions of dollars worth of fear and desire; fear that it’ll
  635.    never pay off and desire for a piece of the money. Can you begin to imagine the pressure for revenue that investors and
  636.    executives and middle managers are under?</p>
  637.    <p><a href="https://cosocial.ca/@timbray/114572118905328515">Here’s an example</a> of the kind of debate that ensues.</p>
  638.    <img src="https://www.tbray.org/ongoing/When/202x/2025/06/06/Anil-MCP.png" alt="Anil Dash on Mastodon, on MCP vs the Fediverse" />
  639.    <div class='caption'><p>“MCP” is
  640.    <a href="https://en.wikipedia.org/wiki/Model_Context_Protocol">Model Context Protocol</a>, used for communicating between LLM
  641.    software and other systems and services.<br/>I have no opinion as to its quality or utility.</p></div>
  642.    <p>I suggest that when you’re getting a pitch for genAI technology, you should have that greed and
  643.    fear in the back of your mind. Or maybe at the front.</p>
  644.    <h2 id='p-7'>And that’s just the money</h2>
  645.    <p>For some reason, I don’t hear much any more about the environmental cost of genAI, the gigatons of carbon pouring out of the
  646.    system, imperilling my children’s future. Let’s please not ignore that; let’s read things like
  647.    <a href="https://www.eesi.org/articles/view/data-center-energy-needs-are-upending-power-grids-and-threatening-the-climate">Data
  648.    Center Energy Needs Could Upend Power Grids and Threaten the Climate</a> and let’s make sure every freaking conversation about
  649.    genAI acknowledges this grievous cost.</p>
  650.    <p>Now let’s look at a few sectors where genAI is said to be a big deal: Coding, teaching, and professional
  651.    communication. To keep things balanced, I’ll start in a space where I have kind things to say.</p>
  652.    <h2 id='p-2'>Coding</h2>
  653.    <p>Wow, is my tribe ever melting down. The pro- and anti-genAI factions are hurling polemical thunderbolts at each
  654.    other, and I mean extra hot and pointy ones. For example, here are 5600 words entitled
  655.    <a href="https://blog.glyph.im/2025/06/i-think-im-done-thinking-about-genai-for-now.html">I Think I’m Done Thinking About genAI
  656.    For Now</a>. Well-written words, too.</p>
  657.    <p>But, while I have a lot of sympathy for the contras and am sickened by some of the promoters, at the moment
  658.    I’m mostly in tune with Thomas Ptacek’s
  659.    <a href="https://fly.io/blog/youre-all-nuts/">My AI Skeptic Friends Are All Nuts</a>. It’s long and (fortunately) well-written
  660.    and I (mostly) find it hard to disagree with.</p>
  661.    <p>it’s as simple as this: I keep hearing talented programmers
  662.    whose integrity I trust tell me “Yeah, LLMs are helping me get shit done.” The probability that they’re all lying or being
  663.    fooled seems very low.</p>
  664.    <p>Just to be clear, I note an absence of concern for cost and carbon in these conversations. Which is unacceptable. But let’s
  665.    move on.</p>
  666.    <p>It’s worth noting that I learned two useful things from Ptacek’s essay that I hadn’t really understood. First, the “agentic”
  667.    architecture of programming tools: You ask the agent to create code and it asks the LLM, which will sometimes
  668.    hallucinate; the agent will observe that it doesn’t compile or makes all the unit tests fail, discards it, and re-prompts. If
  669.    it takes the agent module 25 prompts to generate code that while imperfect is at least correct, who cares?</p>
  670.    <p>Second lesson, and to be fair this is just anecdata: It feels like the Go programming language is especially well-suited to
  671.    LLM-driven automation. It’s small, has a large standard library, and a culture that has strong shared idioms for doing almost
  672.    anything. Anyhow, we’ll find out if this early impression stands up to longer and wider industry experience.</p>
  673.    <p>Turning our attention back to cost, let’s assume that eventually all or most developers become somewhat LLM-assisted. Are
  674.    there enough of them, and will they pay enough, to cover all that investment?  Especially given that models that are both
  675.    open-source and excellent are certain to proliferate? Seems dubious.</p>
  676.    <p>Suppose that, as Ptacek suggests, LLMs/agents allow us to automate the tedious low-intellectual-effort parts of our
  677.    job. Should we be concerned about how junior developers learn to get past that “easy stuff” and on the way to senior skills?
  678.    That seems a very good question, so…</p>
  679.    <h2 id='p-10'>Learning</h2>
  680.    <p>Quite likely you’ve already seen Jason Koebler’s
  681.    <a href="https://www.404media.co/teachers-are-not-ok-ai-chatgpt/?ref=daily-stories-newsletter">Teachers Are Not OK</a>, a
  682.    frankly horrifying survey of genAI’s impact on secondary and tertiary education. It is a tale of unrelieved grief and pain
  683.    and wreckage. Since genAI isn’t going to go away and students aren’t going to stop being lazy,
  684.    it seems like we’re going to re-invent the way people teach and learn.</p>
  685.    <p>The stories of students furiously deploying genAI to avoid the effort of actually, you know,
  686.    learning, are sad. Even sadder  are those of genAI-crazed administrators leaning on faculty to become more efficient and
  687.    “businesslike” by using it.</p>
  688.    <p>I really don’t think there’s a coherent pro-genAI case to be made in the education context.</p>
  689.    <h2 id='p-11'>Professional communication</h2>
  690.    <p>If you want to use LLMs to automate communication with your family or friends or lovers, there’s nothing I can say that will
  691.    help you. So let’s restrict this to conversation and reporting around work and private projects and voluntarism and so on.</p>
  692.    <p>I’m
  693.    pretty sure this is where the people who think they’re going to make big money with AI think it’s going to come from.
  694.    If you’re interested in that thinking,
  695.    <a href="https://docs.google.com/presentation/d/1Der8WWGeVxdOWx37bMV_nj9N1tUAVcvSSRa6qxKx75g/edit?slide=id.p1#slide=id.p1">here’s
  696.    a sample</a>; a slide deck by a Keith Riegert for the book-publishing business which, granted, is a bit stagnant and a whole lot
  697.    overconcentrated these days. I suspect scrolling through it will produce a strong emotional reaction for quite a few readers here.
  698.    It’s also useful in that it talks specifically about costs.</p>
  699.    <p>That is for corporate-branded output. What about personal or internal professional communication; by which I mean emails and
  700.    sales reports and committee drafts and project pitches and so on? I’m pretty negative about this. If your email or pitch
  701.    doc or whatever needs to be summarized, or if it has the colorless affectless error-prone polish of 2025’s LLMs, I would
  702.    probably discard it unread.
  703.    I already found the switch to turn off Gmail’s attempts to summarize my emails.</p>
  704.    <p>What’s the genAI world’s equivalent of “Tl;dr”? I’m thinking “TA;dr” (A for AI)
  705.    or “Tg;dr” (g for genAI) or just “LLM:dr”.</p>
  706.    <p>And this vision of everyone using genAI to amplify their output and everyone else using it to summarize and filter
  707.    their input feels simply perverse.</p>
  708.    <p>Here’s what I think is
  709.    <a href="https://infosec.exchange/@codinghorror/114606355212363074">an important finding</a>, ably summarized by Jeff Atwood:</p>
  710.    <img src="https://www.tbray.org/ongoing/When/202x/2025/06/06/Dare-Jeff.png" alt="Dare Obasanjo and Jeff Atwood on how to survive AI" />
  711.    <p>Seriously, since LLMs by design emit streams that are optimized for plausibility and for harmony with the model’s
  712.    training base, in an AI-centric world there’s a powerful incentive to say things that are implausible, that are out of tune,
  713.    that are, bluntly, weird. So there’s one upside.</p>
  714.    <p>And let’s go back to cost. Are the prices in Riegert’s slide deck going to pay for trillions in capex?
  715.    Another example: My family has a Google workplace account, and the price just went up from $6/user/month to
  716.    $7. The announcement from Google emphasized that this was related to the added value provided by Gemini. Is $1/user/month gonna
  717.    make this tech make business sense?</p>
  718.    <h2 id='p-13'>What I can and can’t buy</h2>
  719.    <p>I can sorta buy the premise that there are genAI productivity boosts to be had in the code space and maybe some other
  720.    specialized domains.  I can’t buy for a second that genAI is anything but toxic for anything education-related.  On the
  721.    business-communications side, it’s damn well gonna be tried because billions of dollars and many management careers depend on
  722.    it paying off. We’ll see but I’m skeptical.</p>
  723.    <p>On the money side? I don’t see how the math and the capex work. And all the time, I think about the carbon that’s poisoning
  724.    the planet my children have to live on.</p>
  725.    <p>I think that the best we can hope for is the eventual financial meltdown leaving a few useful islands of things that
  726.    are actually useful at prices that make sense.</p>
  727.    <p>And in a decade or so, I can see business-section stories about all the big data center shells that were never filled in,
  728.    standing there empty, looking for another use. It’s gonna be tough, what can you do with buildings that have no windows?</p>
  729. </div></content></entry>
  730.  
  731. <entry>
  732. <title>Union of Finite Automata</title>
  733. <link href='https://www.tbray.org/ongoing/When/202x/2024/07/28/Union-of-Finite-Automata' />
  734. <link rel='replies'        thr:count='0'        type='application/xhtml+xml'        href='/ongoing/When/202x/2024/07/28/Union-of-Finite-Automata#comments' />
  735. <id>https://www.tbray.org/ongoing/When/202x/2024/07/28/Union-of-Finite-Automata</id>
  736. <published>2024-07-28T12:00:00-07:00</published>
  737. <updated>2025-06-02T11:49:20-07:00</updated>
  738. <category scheme='https://www.tbray.org/ongoing/What/' term='Technology/Quamina Diary' />
  739. <category scheme='https://www.tbray.org/ongoing/What/' term='Technology' />
  740. <category scheme='https://www.tbray.org/ongoing/What/' term='Quamina Diary' />
  741. <summary type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>In building Quamina, I needed to compute the union of two finite automata (FAs). I remembered from some university course 100 years     ago that this was possible in theory, so I went looking for the algorithm, but was left unhappy.     The descriptions I found tended to be hyper-academic, loaded with mathematical notation that I found unhelpful, and     didn’t describe an approach that I thought a reasonable programmer would reasonably take. The purpose of this <span class="o">ongoing</span> entry is to present a      programmer-friendly description of the problem and of the algorithm I adopted, with the hope that some future developer, facing     the same problem, will have a more satisfying search experience.<br/> <i>[Important update: There’s a serious error halfway through; see <a href='#p-9'>here</a>.]</i></div></summary>
  742. <content type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>
  743.    <p>In building Quamina, I needed to compute the union of two finite automata (FAs). I remembered from some university course 100 years
  744.    ago that this was possible in theory, so I went looking for the algorithm, but was left unhappy.
  745.    The descriptions I found tended to be hyper-academic, loaded with mathematical notation that I found unhelpful, and
  746.    didn’t describe an approach that I thought a reasonable programmer would reasonably take. The purpose of this <span
  747.    class='o'>ongoing</span> entry is to present a
  748.    programmer-friendly description of the problem and of the algorithm I adopted, with the hope that some future developer, facing
  749.    the same problem, will have a more satisfying search experience.<br/>
  750.    <i>[Important update: There’s a serious error halfway through; see <a href="#p-9">here</a>.]</i></p>
  751.    <p>There is very little math in this discussion (a few subscripts), and no
  752.    circles-and-arrows pictures. But it does have working Go code.</p>
  753.    <h2 id='p-1'>Finite automata?</h2>
  754.    <p>I’m not going to rehash the theory of FAs (often called state machines). In practice the purpose of an FA is to match (or
  755.    fail to match) some
  756.    input against some pattern. What the software does when the input matches the pattern (or doesn’t) isn’t relevant to
  757.    our discussion today.
  758.    Usually the inputs are strings and the patterns are regular expressions or equivalent. In practice, you compile a pattern
  759.    into an FA, and then you go through the input, character by character, trying to traverse the FA to find out whether it matches
  760.    the input.</p>
  761.    <p>An FA has a bunch of states, and for each state
  762.    there can be a list of input symbols that lead to transitions to other states. What exactly I mean by “input symbol” turns out to be
  763.    interesting and affects your choice of algorithm, but let’s ignore that for now.</p>
  764.    <p>The following statements apply:</p>
  765.    <ol>
  766.      <li><p>One state is designated as the “start state” because, well, that’s where you start.</p></li>
  767.      <li><p>Some states are called “final”, and reaching them means you’ve matched one or more patterns. In Quamina’s FAs, each
  768.      state has an extra field (usually empty) saying “if you got here you matched P*, yay!”, where P* is a list of labels for the
  769.      (possibly more than one) patterns you matched.</p></li>
  770.      <li><p>It is possible that you’re in a state and for some particular input, you transition to more than one other state. If
  771.      this is true, your FA is <em>nondeterministic</em>, abbreviated NFA.</p></li>
  772.      <li><p>It is possible that a state can have one or more “epsilon transitions”, ones that you can just take any time, not requiring
  773.      any particular input. (I wrote about this in
  774.      <a href="/ongoing/When/202x/2024/06/17/Epsilon-Love">Epsilon Love</a>.)
  775.      Once again, if this is true, you’ve got an NFA. If neither this statement nor the previous are true, it’s
  776.      a <em>deterministic</em> finite automaton, DFA.</p></li>
  777.    </ol>
  778.    <p>The discussion here works for NFAs, but lots of interesting problems can be solved with DFAs, which are simpler and faster,
  779.    and this algorithm works there too.</p>
  780.    <h2 id='p-2'>Union?</h2>
  781.    <p>If I have <code>FA1</code> that matches “foo” and <code>FA2</code> that matches “bar”, then their union,
  782.    <code>FA1 ∪ FA2</code>, matches both “foo”
  783.    and “bar”. In practice Quamina often computes the union of a large number of FAs, but it does so a pair at a time, so we’re
  784.    only going to worry about the union of two FAs.</p>
  785.    <h2 id='p-3'>The academic approach</h2>
  786.    <p>There are plenty of Web pages and YouTubes covering this. Most of them are full of Greek characters and math symbols. They go
  787.    like this:</p>
  788.    <ol>
  789.      <li><p>You have two FAs, call them <code>A</code> and <code>B</code>. <code>A</code> has states <code>A<sub>1</sub></code>, …
  790.      <code>A<sub>maxA</sub></code>, <code>B</code> has <code>B<sub>1</sub></code>, … <code>B<sub>maxB</sub></code></p></li>
  791.      <li><p>The union contains all the states in <code>A</code>, all the states in <code>B</code>, and the “product” of
  792.      <code>A</code> and <code>B</code>, which is to say states you could call <code>A<sub>1</sub>B<sub>1</sub></code>,
  793.      <code>A<sub>1</sub>B<sub>2</sub></code>, <code>A<sub>2</sub>B<sub>1</sub></code>, <code>A<sub>2</sub>B<sub>2</sub></code>,
  794.      … <code>A<sub>maxA</sub>B<sub>maxB</sub></code>.</p></li>
  795.      <li><p>For each state <code>A<sub>X</sub>B<sub>Y</sub></code>, you work out its transitions by looking at the transitions of
  796.      the two states being combined. For some input symbol, if <code>A<sub>X</sub></code> has a transition to
  797.      <code>A<sub>XX</sub></code> but <code>B<sub>Y</sub></code> has no transition, then the combined state just has the A
  798.      transition. The reverse for an input where <code>B<sub>Y</sub></code> has a transition but <code>A<sub>X</sub></code>
  799.      doesn’t. And if <code>A<sub>X</sub></code> transitions to <code>A<sub>XX</sub></code> and <code>B<sub>Y</sub></code> transitions to
  800.      <code>B<sub>YY</sub></code>, then the transition is to <code>A<sub>XX</sub>B<sub>YY</sub></code>.</p></li>
  801.      <li><p>Now you’ll have a lot of states, and it usually turns out that many of them aren’t reachable. But there are plenty of
  802.      algorithms to filter those out. You’re done, you’ve computed the union and <code>A<sub>1</sub>B<sub>1</sub></code> is its
  803.      start state!</p></li>
  804.    </ol>
  805.    <h2 id='p-4'>Programmer-think</h2>
  806.    <p>If you’re like me, the idea of computing all the states, then throwing out the unreachable ones, feels wrong. So here’s
  807.    what I suggest, and has worked well in practice for Quamina:</p>
  808.    <ol>
  809.      <li><p>First, merge <code>A<sub>1</sub></code> and <code>B<sub>1</sub></code> to make your new start state
  810.      <code>A<sub>1</sub>B<sub>1</sub></code>. Here’s how:</p></li>
  811.      <li><p>If an input symbol causes no transitions in either <code>A<sub>1</sub></code> or <code>B<sub>1</sub></code>, it also
  812.      doesn’t cause any in <code>A<sub>1</sub>B<sub>1</sub></code>.</p></li>
  813.      <li><p>If an input symbol causes a transition in <code>A<sub>1</sub></code> to <code>A<sub>X</sub></code> but no transition
  814.      in <code>B<sub>1</sub></code>, then you adopt <code>A<sub>X</sub></code> into the union, and any other <code>A</code> states
  815.      it points to, and any they point to, and so on.</p></li>
  816.      <li><p>And of course if <code>B<sub>1</sub></code> has a transition to <code>B<sub>Y</sub></code> but
  817.      <code>A<sub>1</sub></code> doesn’t transition, you flip it the other way, adopting <code>B<sub>Y</sub></code> and its
  818.      descendents.</p></li>
  819.      <li><p>And if <code>A<sub>1</sub></code> transitions to <code>A<sub>X</sub></code> and <code>B<sub>1</sub></code> transitions
  820.      to <code>B<sub>Y</sub></code>, then you adopt a new state <code>A<sub>X</sub>B<sub>Y</sub></code>, which you compute
  821.      recursively the way you just did for <code>A<sub>1</sub>B<sub>1</sub></code>. So you’ll never compute anything that’s not
  822.      reachable.</p></li>
  823.    </ol>
  824.    <p>I could stop there. I think that’s enough for a competent developers to get the idea?  But it turns out there
  825.    are a few details, some of them interesting. So, let’s dig in.</p>
  826.    <h2 id='p-5'>“Input symbol”?</h2>
  827.    <p>The academic discussion of FAs is very abstract on this subject, which is fair enough, because when you’re talking about how
  828.    to build, or traverse, or compute the union of FAs, the algorithm doesn’t depend very much on what the symbols actually are. But
  829.    when you’re writing code, it turns out to matter a lot.</p>
  830.    <p>In practice, I’ve done a lot of work with FAs over the years, and I’ve only ever seen four things used as input symbols
  831.    to drive them. They are:</p>
  832.    <ul>
  833.      <li><p>Unicode “characters” represented by code points, integers in the range 0…1,114,111 inclusive.</p></li>
  834.      <li><p>UTF-8 bytes, which have values in the range 0…244 inclusive.</p></li>
  835.      <li><p>UTF-16 values, unsigned 16-bit integers. I’ve only ever seen this used in Java programs because that’s what
  836.      its native <code>char</code> type is. You probably don’t want to do this.</p></li>
  837.      <li><p>Enum values, small integers with names, which tend to come in small collections.</p></li>
  838.    </ul>
  839.    <p>As I said, this is all I’ve seen, but 100% of the FAs that I’ve seen automatically generated and subject to
  840.    set-arithmetic operations like Union are based on UTF-8. And that’s what Quamina uses, so that’s what I’m going to use in the
  841.    rest of this discussion.</p>
  842.    <h2 id='p-7'>Code starts here</h2>
  843.    <p>This comes from Quamina’s
  844.    <a href="https://github.com/timbray/quamina/blob/main/nfa.go">nfa.go</a>. We’re going to look at the function
  845.    <code>mergeFAStates</code>, which implements the merge-two-states logic described above.</p>
  846.    <p>Lesson: This process can lead to a lot of wasteful work. Particularly if either or both of the states transition on ranges of
  847.    values like <code>0…9</code> or <code>a…z</code>. So we only want to do the work merging any pair of states once, and we want
  848.    there only to be one merged value.  Thus we start with a straightforward memo-ization.</p>
  849.    <div class="tbc"><pre>
  850. <span class="kd">func</span><span class="w"> </span><span class="nx">mergeFAStates</span><span class="p">(</span><span class="nx">state1</span><span class="p">,</span><span class="w"> </span><span class="nx">state2</span><span class="w"> </span><span class="o">*</span><span class="nx">faState</span><span class="p">,</span><span class="w"> </span><span class="nx">keyMemo</span><span class="w"> </span><span class="kd">map</span><span class="p">[</span><span class="nx">faStepKey</span><span class="p">]</span><span class="o">*</span><span class="nx">faState</span><span class="p">)</span><span class="w"> </span><span class="o">*</span><span class="nx">faState</span><span class="w"> </span><span class="p">{</span>
  851. <span class="w">    </span><span class="c1">// try to memo-ize</span>
  852. <span class="w">    </span><span class="nx">mKey</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">faStepKey</span><span class="p">{</span><span class="nx">state1</span><span class="p">,</span><span class="w"> </span><span class="nx">state2</span><span class="p">}</span>
  853. <span class="w">    </span><span class="nx">combined</span><span class="p">,</span><span class="w"> </span><span class="nx">ok</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">keyMemo</span><span class="p">[</span><span class="nx">mKey</span><span class="p">]</span>
  854. <span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="nx">ok</span><span class="w"> </span><span class="p">{</span>
  855. <span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="nx">combined</span>
  856. <span class="w">    </span><span class="p">}</span>
  857. </pre>
  858.    <p>Now some housekeeping. Remember, I noted above that any state might contain a signal saying that arriving here
  859.    means you’ve matched pattern(s). This is called <code>fieldTransitions</code>, and the merged state obviously has to
  860.    match all the things that either of the merged states match. Of course, in the vast majority of cases neither merged state
  861.    matched anything and so this is a no-op.</p>
  862. <pre>
  863. <span class="w">    </span><span class="nx">fieldTransitions</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nb">append</span><span class="p">(</span><span class="nx">state1</span><span class="p">.</span><span class="nx">fieldTransitions</span><span class="p">,</span><span class="w"> </span><span class="nx">state2</span><span class="p">.</span><span class="nx">fieldTransitions</span><span class="o">...</span><span class="p">)</span></pre>
  864.    <p>Since our memo-ization attempt came up empty, we have to allocate an empty structure for the new merged state, and add it to the
  865.    memo-izer.</p>
  866.    <pre>
  867. <span class="w">    </span><span class="nx">combined</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="o">&amp;</span><span class="nx">faState</span><span class="p">{</span><span class="nx">table</span><span class="p">:</span><span class="w"> </span><span class="nx">newSmallTable</span><span class="p">(),</span><span class="w"> </span><span class="nx">fieldTransitions</span><span class="p">:</span><span class="w"> </span><span class="nx">fieldTransitions</span><span class="p">}</span>
  868. <span class="w">    </span><span class="nx">keyMemo</span><span class="p">[</span><span class="nx">mKey</span><span class="p">]</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nx">combined</span></pre>
  869.    <p>Here’s where it gets interesting.  The algorithm talks about looking at the inputs that cause transitions in the states we’re
  870.    merging. How do you find them?  Well, in the case where you’re transitioning on UTF-8 bytes, since there are only 244 values,
  871.    why not do the simplest thing that could possibly work and just check each byte value?</p>
  872.    <p>Every Quamina state contains a table that encodes the byte transitions, which operates  like the Go construct
  873.    <code>map[byte]state</code>. Those tables are implemented in
  874.    <a href="/ongoing/When/202x/2022/06/25/Small-Tables">a compact data structure optimized for fast traversal</a>. But for doing this
  875.    kind of work, it’s easy to “unpack” them into a fixed-sized table; in Go, <code>[244]state</code>. Let’s do that for the states
  876.    we’re merging and for the new table we’re building.</p>
  877. <pre><span class="w">    </span><span class="nx">u1</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">unpackTable</span><span class="p">(</span><span class="nx">state1</span><span class="p">.</span><span class="nx">table</span><span class="p">)</span>
  878. <span class="w">    </span><span class="nx">u2</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">unpackTable</span><span class="p">(</span><span class="nx">state2</span><span class="p">.</span><span class="nx">table</span><span class="p">)</span>
  879. <span class="w">    </span><span class="kd">var</span><span class="w"> </span><span class="nx">uComb</span><span class="w"> </span><span class="nx">unpackedTable</span></pre>
  880. <p><code>uComb</code> is where we’ll fill in the merged transitions.</p>
  881. <p>Now we’ll run through all the possible input values; <code>i</code> is the byte value,  <code>next1</code> and <code>next2</code>
  882. are the transitions on that value. In practice, <code>next1</code> and <code>next2</code> are going to be null most of the time.</p>
  883. <pre><span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="nx">i</span><span class="p">,</span><span class="w"> </span><span class="nx">next1</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="k">range</span><span class="w"> </span><span class="nx">u1</span><span class="w"> </span><span class="p">{</span>
  884. <span class="w">        </span><span class="nx">next2</span><span class="w"> </span><span class="o">:=</span><span class="w"></span><span class="nx"> u2</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span></pre>
  885.    <p>Here’s where we start building up the new transitions in the unpacked array <code>uComb</code>.</p>
  886.    <p>For many values of <code>i</code>, you can avoid actually merging the states to create a new one. If the transition is the
  887.    same in both input FAs, or if either of them are null, or if the transitions for this value of <code>i</code> are the same as
  888.    for the last value.  This is all about avoiding unnecessary work and the <code>switch</code>/<code>case</code> structure is the
  889.    result of a bunch of profiling and optimization.</p>
  890. <pre><span class="w">        </span><span class="k">switch</span><span class="w"> </span><span class="p">{</span>
  891. <span class="w">        </span><span class="k">case</span><span class="w"> </span><span class="nx">next1</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nx">next2</span><span class="p">:</span><span class="w"> </span><span class="c1">// no need to merge</span>
  892. <span class="w">            </span><span class="nx">uComb</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nx">next1</span>
  893. <span class="w">        </span><span class="k">case</span><span class="w"> </span><span class="nx">next2</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="kc">nil</span><span class="p">:</span><span class="w"> </span><span class="c1">// u1 must be non-nil</span>
  894. <span class="w">            </span><span class="nx">uComb</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nx">next1</span>
  895. <span class="w">        </span><span class="k">case</span><span class="w"> </span><span class="nx">next1</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="kc">nil</span><span class="p">:</span><span class="w"> </span><span class="c1">// u2 must be non-nil</span>
  896. <span class="w">            </span><span class="nx">uComb</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nx">next2</span>
  897. <span class="w">        </span><span class="k">case</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="p">&gt;</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="nx">next1</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nx">u1</span><span class="p">[</span><span class="nx">i</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="nx">next2</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nx">u2</span><span class="p">[</span><span class="nx">i</span><span class="o">-</span><span class="mi">1</span><span class="p">]:</span><span class="w"> </span><span class="c1">// dupe of previous step - happens a lot</span>
  898. <span class="w">            </span><span class="nx">uComb</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nx">uComb</span><span class="p">[</span><span class="nx">i</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span></pre>
  899.    <p>If none of these work, we haven’t been able to avoid merging the two states. We do that by a recursive call to invoke
  900.    all the logic we just discussed.</p>
  901.    <p>There is a complication. The automaton might be nondeterministic, which means that there might be more than one transition
  902.    for some byte value. So the data structure actually behaves like <code>map[byte]*faNext</code>, where <code>faNext</code> is a
  903.    wrapper for a list of states you can transition to.</p>
  904.    <p>So here we’ve got a nested loop to recurse for each possible combination of transitioned-to states that can occur on this
  905.    byte value. In a high proportion of cases the FA is deterministic, so there’s only one state from each FA being merged and this
  906.    nested loop collapses to a single recursive call.</p>
  907. <pre><span class="w">        </span><span class="k">default</span><span class="p">:</span><span class="w"> </span><span class="c1">// have to recurse &amp; merge</span>
  908. <span class="w">            </span><span class="kd">var</span><span class="w"> </span><span class="nx">comboNext</span><span class="w"> </span><span class="p">[]</span><span class="o">*</span><span class="nx">faState</span>
  909. <span class="w">            </span><span class="k">for</span><span class="w"> </span><span class="nx">_</span><span class="p">,</span><span class="w"> </span><span class="nx">nextStep1</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="k">range</span><span class="w"> </span><span class="nx">next1</span><span class="p">.</span><span class="nx">states</span><span class="w"> </span><span class="p">{</span>
  910. <span class="w">                </span><span class="k">for</span><span class="w"> </span><span class="nx">_</span><span class="p">,</span><span class="w"> </span><span class="nx">nextStep2</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="k">range</span><span class="w"> </span><span class="nx">next2</span><span class="p">.</span><span class="nx">states</span><span class="w"> </span><span class="p">{</span>
  911. <span class="w">                    </span><span class="nx">comboNext</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nb">append</span><span class="p">(</span><span class="nx">comboNext</span><span class="p">,</span><span class="w"> </span><span class="nx">mergeFAStates</span><span class="p">(</span><span class="nx">nextStep1</span><span class="p">,</span><span class="w"> </span><span class="nx">nextStep2</span><span class="p">,</span><span class="w"> </span><span class="nx">keyMemo</span><span class="p">))</span>
  912. <span class="w">                </span><span class="p">}</span>
  913. <span class="w">            </span><span class="p">}</span>
  914. <span class="w">            </span><span class="nx">uComb</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="o">&amp;</span><span class="nx">faNext</span><span class="p">{</span><span class="nx">states</span><span class="p">:</span><span class="w"> </span><span class="nx">comboNext</span><span class="p">}</span>
  915. <span class="w">        </span><span class="p">}</span>
  916. <span class="w">    </span><span class="p">}</span></pre>
  917.    <p>We’ve filled up the unpacked state-transition table, so we’re almost done. First, we have to compress it into its
  918.    optimized-for-traversal form.</p>
  919. <pre><span class="w">    </span><span class="nx">combined</span><span class="p">.</span><span class="nx">table</span><span class="p">.</span><span class="nx">pack</span><span class="p">(</span><span class="o">&amp;</span><span class="nx">uComb</span><span class="p">)</span></pre>
  920.    <p>Remember, if the FA is nondeterministic, each state can have “epsilon” transitions which you can follow any time without
  921.    requiring any particular input. The merged state needs to contain all the epsilon transitions from each input state.</p>
  922. <pre><span class="w">    </span><span class="nx">combined</span><span class="p">.</span><span class="nx">table</span><span class="p">.</span><span class="nx">epsilon</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nb">append</span><span class="p">(</span><span class="nx">state1</span><span class="p">.</span><span class="nx">table</span><span class="p">.</span><span class="nx">epsilon</span><span class="p">,</span><span class="w"> </span><span class="nx">state2</span><span class="p">.</span><span class="nx">table</span><span class="p">.</span><span class="nx">epsilon</span><span class="o">...</span><span class="p">)</span>
  923.  
  924. <span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nx">combined</span>
  925. <span class="p">}</span></pre>
  926.    </div>
  927.    <p>And, we’re done. I mean, we are once all those recursive calls have finished crawling through the states being merged.</p>
  928.    <h2 id='p-9'>Oops</h2>
  929.    <p>The discussion of epsilons above is wrong, in a way that’s harder to reproduce than you might think.
  930.    The discussion is still
  931.    correct for DFA’s and (weirdly) (I think) (not sure why yet) the shell-style “wildcard” <code>*</code> operator, which means
  932.    <code>.*</code> in a regular expression.</p>
  933.    <p>It’s not clear that in general there’s a way to merge (Quamina-style) two NFA states when either or both of them have epsilon transitions.
  934.    Per the
  935.    academic literature, the right way to get the union of two NFAs is to have an empty branch state with two epsilon transitions,
  936.    one to each NFA. So you traverse the two in parallel.</p>
  937.    <p>It took me a a whole lot of pain to figure this out and I haven’t entirely worked out the best implementation. I promise more
  938.    regular-expressions-at-scale walls of text and code in this space when I do.</p>
  939.    <p>I write this because when you type “merge nondeterministic finite automata” into Web search, the blog you are now reading is
  940.    dangerously high in the search results.</p>
  941.    <h2 id='p-8'>Is that efficient?</h2>
  942.    <p>As I said above, this is an example of a “simplest thing that could possibly work” design. Both the recursion and the
  943.    unpack/pack sequence are kind of code smells, suggesting that this could be a pool of performance quicksand.</p>
  944.    <p>But apparently not. I ran a benchmark where I added 4,000 patterns synthesized from the Wordle
  945.    word-list; each of them looked like this:</p>
  946.    <p><code>{"allis": { "biggy": [ "ceils", "daisy", "elpee", "fumet", "junta", … </code> (195 more).</p>
  947.    <p>This produced a <em>huge</em> deterministic FA with about 4.4 million states, with the addition of these hideous worst-case
  948.    patterns running at 500/second. Good enough for rock ’n’ roll.</p>
  949.    <p>How about nondeterministic FAs? I went back to that Wordle source and, for each of its 12,959 words, added a pattern with a
  950.    random wildcard; here are three of them:</p>
  951.    <p><code>{"x": [ {"shellstyle": "f*ouls" } ] }<br/>
  952. {"x": [ {"shellstyle": "pa*sta" } ] }<br/>
  953. {"x": [ {"shellstyle": "utter*" } ] }</code></p>
  954.   <p>This produced an NFA with 46K states, the addition process ran at 70K patterns/second.
  955.   </p>
  956.   <p>Sometimes the simplest thing that could possibly work, works.</p>
  957. </div></content></entry>
  958.  
  959. <entry>
  960. <title>Perfectly Different Colors</title>
  961. <link href='https://www.tbray.org/ongoing/When/202x/2025/05/31/Colors' />
  962. <link rel='replies'        thr:count='3'        type='application/xhtml+xml'        href='/ongoing/When/202x/2025/05/31/Colors#comments' />
  963. <id>https://www.tbray.org/ongoing/When/202x/2025/05/31/Colors</id>
  964. <published>2025-05-31T12:00:00-07:00</published>
  965. <updated>2025-06-02T08:51:38-07:00</updated>
  966. <category scheme='https://www.tbray.org/ongoing/What/' term='Arts/Photos' />
  967. <category scheme='https://www.tbray.org/ongoing/What/' term='Arts' />
  968. <category scheme='https://www.tbray.org/ongoing/What/' term='Photos' />
  969. <category scheme='https://www.tbray.org/ongoing/What/' term='Arts/Photos/Cameras' />
  970. <category scheme='https://www.tbray.org/ongoing/What/' term='Cameras' />
  971. <summary type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>This considers how two modern cameras handle a difficult color challenge, illustrated by photos of a perfect rose and a piano</div></summary>
  972. <content type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>
  973.    <p>This considers how two modern cameras handle a difficult color challenge, illustrated by photos of a perfect rose and a piano.</p>
  974.    <p>We moved into our former place in January 1997 and, that summer, discovered the property included this slender little rose
  975.    that only had a couple blossoms every year, but they were perfection, beautifully shaped and in a unique shade of red I’d
  976.    never seen anywhere else (and still haven’t). Having no idea of its species, we’ve always called it “our perfect rose”.</p>
  977.    <p>So when
  978.    <a href="/ongoing/When/202x/2025/02/28/Moved">we moved</a> last year, we took the rose with us. It seems to
  979.    like the new joint, has a blossom out and two more on the way and it’s still May.</p>
  980.    <p>I was looking at it this morning and it occurred to me that its color might be an interesting challenge to the two fine cameras I use
  981.    regularly, namely a Google Pixel 7 and a Fujifilm X-T5.</p>
  982.    <p>First the pictures.</p>
  983.    <img src="https://www.tbray.org/ongoing/When/202x/2025/05/31/PXL_20250531_185139866.png" alt="The “perfect” rose." />
  984.    <img src="https://www.tbray.org/ongoing/When/202x/2025/05/31/TXT55657.png" alt="The “perfect” rose" />
  985.    <h2 id='p-2'>Limitations</h2>
  986.    <p>First of all, let’s agree that this comparison is horribly flawed. To start with, by the time the pixels have made it from
  987.    the camera to your screen, they’ve been through Lightroom, possibly a social-media-software uploader and renderer, and then
  988.    your browser (or mobile app) and screen contribute their opinions.
  989.    Thus the colors are likely to vary a lot depending where you are and what you’re using.</p>
  990.    <p>Also, it’s hard to get really comparable shots out of the Pixel and Fuji; their lenses and processors and underlying
  991.    architectures are really different. I was going to disclose the reported shutter speeds, aperture, and ISO values, but they are
  992.    so totally non-comparable that I decided that’d be actively harmful. I’ll just say that I tried to let each do its best.</p>
  993.    <p>I post-processed both, but limited that to cropping; nothing about the color or exposure was touched.</p>
  994.    <p>And having said all that, I think the exercise retains interest.</p>
  995.    <h2 id='p-1'>Which?</h2>
  996.    <p>The Pixel is above, the Fuji below.</p>
  997.    <p>The Pixel is wrong. The Fuji is… not bad. The blossom’s actual color, to my eye, has a little more orange than I see in the
  998.    photo; but only a little. The Pixel subtracts the orange and introduces a suggestion of violet that the blossom, to
  999.    my eye, entirely lacks.</p>
  1000.    <p>Also, the Pixel is artificially sharpening up the petals; in reality, the contrast was low and the shading nuanced; just as
  1001.    presented by the X-T5.</p>
  1002.    <p>Is the Pixel’s rendering a consequence of whatever its sensor is?  Or of the copious amount of processing that
  1003.    contributes to Google’s widely-admired (by me too) “computational photography”? I certainly have no idea. And in fact,
  1004.    most of the pictures I share come from my Android because the best camera (this is always true) is the one you have with
  1005.    you. For example…</p>
  1006.    <img src="https://www.tbray.org/ongoing/When/202x/2025/05/31/PXL_20250531_032232026.png" alt="Grand piano by itself in an old church" />
  1007.    <div class='caption'><p>That same evening we took in a concert put on by the local Chopin Society featuring 89-year-old
  1008.    <a href="MikhailVoskresensky">Mikhail Voskresensky</a>, who plays really fast and loud in an old super-romantic style, just the
  1009.    thing for the music: Very decent Beethoven and Mozart, kind of aimless Grieg, and the highlight, a lovely take on Chopin’s
  1010.    Op. 58 Sonata, then a <cite>Nocturne</cite> in the encores.</p>
  1011.    <p>Anyhow, I think the Camera I Had With Me did fine. This is
  1012.    <a href="https://www.thecathedral.ca/programs/architecture-heritage">Vancouver’s oldest still-standing
  1013.    building</a>, Christ Church Cathedral, an exquisite space for the eyes and ears.</p></div>
  1014.    <p>Maybe I’ll do a bit more conscious color-correction on the Pixel shots in future (although I didn’t on the piano). Doesn’t
  1015.    mean it’s not a great camera.</p>
  1016. </div></content></entry>
  1017.  
  1018. <entry>
  1019. <title>Comparing Numbers Badly</title>
  1020. <link href='https://www.tbray.org/ongoing/When/202x/2025/05/30/Number-Comparison-Representation' />
  1021. <link rel='replies'        thr:count='4'        type='application/xhtml+xml'        href='/ongoing/When/202x/2025/05/30/Number-Comparison-Representation#comments' />
  1022. <id>https://www.tbray.org/ongoing/When/202x/2025/05/30/Number-Comparison-Representation</id>
  1023. <published>2025-05-30T12:00:00-07:00</published>
  1024. <updated>2025-05-30T16:15:25-07:00</updated>
  1025. <category scheme='https://www.tbray.org/ongoing/What/' term='Language' />
  1026. <category scheme='https://www.tbray.org/ongoing/What/' term='Language' />
  1027. <category scheme='https://www.tbray.org/ongoing/What/' term='Technology/Math' />
  1028. <category scheme='https://www.tbray.org/ongoing/What/' term='Technology' />
  1029. <category scheme='https://www.tbray.org/ongoing/What/' term='Math' />
  1030. <summary type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>This is just a gripe about two differently bad ways to compare numbers. They share a good alternative</div></summary>
  1031. <content type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>
  1032.    <p>This is just a gripe about two differently bad ways to compare numbers. They share a good alternative.</p>
  1033.    <h2 id='p-1'>“Order of magnitude”</h2>
  1034.    <p>Typically sloppy usages: “AI increases productivity by an order of magnitude”, “Revenue from recorded music is orders of
  1035.    magnitude smaller than back in the Eighties”.</p>
  1036.    <p>Everyone reading this probably already knows that “order of magnitude” has a precise meeting: Multiply or divide by
  1037.    ten. But clearly, the people who write news stories and marketing spiels either don’t, or are consciously using the idioms to
  1038.    lie. In particular, they are trying to say “more than” or “less than” in a dramatic and impressive-sounding way.</p>
  1039.    <p>Consider that first example. It is saying that AI delivers a ten-times gain in productivity. If they’d actually said “ten
  1040.    times” people would be more inclined to ask “What units?” and “How did you measure?” This phrase makes me think that its author
  1041.    is probably lying.</p>
  1042.    <p>The second example is even more pernicious. Since “orders” is plural, they are claiming at least two orders of magnitude,
  1043.    i.e. that revenue is down by <em>at least</em> a factor of a hundred. The difference between two, three, and four orders of
  1044.    magnitude is huge!  I’d probably argue that the phrase “order<b>s</b> of magnitude” should probably
  1045.    never be used. In this case, I highly doubt that the speaker has any data, and that they’re just trying to say that the
  1046.    revenue is down really a lot.</p>
  1047.    <p>The solution is simple: Say “by a factor of ten” or “ten times as high” or “at least 100 times less.”  Assuming your claim is
  1048.    valid, it will be easily understood; Almost everyone has a decent intuitive understanding of what a ten-times or hundred-times
  1049.    difference feels like.</p>
  1050.    <h2 id='p-2'>“Percent”</h2>
  1051.    <p>What actually got me started reading this was reading a claim that some business’s “revenue increased by 250%.”
  1052.    Let’s see. If the revenue were one million and it increased by 10%, it’d be 1.1 million. If it increased by 100% it’d be two
  1053.    million. 200% is three million. So what they meant by 250% is that the revenue increased by a factor of 3.5.  It is <em>so
  1054.    much</em> easier to understand “3.5 times” than 250%. Furthermore, I bet a lot of people intuitively feel that 250% means “2.5
  1055.    times”, which is just wrong.</p>
  1056.    <p>I think quoting percentages is clear and useful for values less than 100. There is nothing wrong with talking about a 20%
  1057.    increase or 75% decrease.</p>
  1058.    <p>So, same solution: For percentages past 100, don’t use them, just say “by a factor of X”. Once again, people have an instant
  1059.    (and usually correct) gut feel for what a 3.5-times increase feels like.</p>
  1060.    <h2 id='p-3'>“But English is a living language!”</h2>
  1061.    <p>Not just living, but also squirmy and slutty, open to both one-night stands and permanent relationships with neologisms no
  1062.    matter how ugly and
  1063.    imports from other dialects no matter how sketchy. Which is to say, there’s nothing I can do to keep “orders of magnitude” from
  1064.    being used to mean “really a lot”.</p>
  1065.    <p>In fact, it’s only a problem when you’re trying to communicate a numeric difference. But that’s an important application of
  1066.    human language.</p>
  1067.    <p>Perversely, I guess you could argue that these
  1068.    bad idioms are useful in helping you detect statements that are probably either ignorant or just lies. Anyhow, now you know that
  1069.    when I hear them, I hear patterns that make me inclined to disbelieve. And I bet I’m not the only one.</p>
  1070. </div></content></entry>
  1071.  
  1072. <entry>
  1073. <title>CL XLVI: Happy Colors</title>
  1074. <link href='https://www.tbray.org/ongoing/When/202x/2025/05/27/Happy-Colors' />
  1075. <link rel='replies'        thr:count='0'        type='application/xhtml+xml'        href='/ongoing/When/202x/2025/05/27/Happy-Colors#comments' />
  1076. <id>https://www.tbray.org/ongoing/When/202x/2025/05/27/Happy-Colors</id>
  1077. <published>2025-05-27T12:00:00-07:00</published>
  1078. <updated>2025-05-28T21:58:08-07:00</updated>
  1079. <category scheme='https://www.tbray.org/ongoing/What/' term='The World/Cottage Life' />
  1080. <category scheme='https://www.tbray.org/ongoing/What/' term='The World' />
  1081. <category scheme='https://www.tbray.org/ongoing/What/' term='Cottage Life' />
  1082. <summary type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>Last weekend we were at our cabin on     <a href='https://en.wikipedia.org/wiki/Keats_Island_(British_Columbia)'>Keats Island</a> and I came away with two     <a href='/ongoing/What/The%20World/Cottage%20Life/'>cottage-life</a> pictures I     wanted to write about. To write cheery stuff actually, a rare pleasure in these dark days.  Both have a story but this first one’s     simple</div></summary>
  1083. <content type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>
  1084.    <p>Last weekend we were at our cabin on
  1085.    <a href="https://en.wikipedia.org/wiki/Keats_Island_(British_Columbia)">Keats Island</a> and I came away with two
  1086.    <a href="/ongoing/What/The%20World/Cottage%20Life/">cottage-life</a> pictures I
  1087.    wanted to write about. To write cheery stuff actually, a rare pleasure in these dark days.  Both have a story but this first one’s
  1088.    simple.</p>
  1089.    <img src="https://www.tbray.org/ongoing/When/202x/2025/05/27/PXL_20250525_212106021.png" alt="Evergreen branches in spring with the new life showing" />
  1090.    <p>It’s just an ordinary evergreen tree, not very tall, nothing special about it. But spring’s here! So at the end of each branch
  1091.    there’s a space where the needles are new and shout their youth in light green, a fragile color as compared to the soberly rich
  1092.    shade of the middle-aged needles further up the branch. Probably a metaphor for something complicated but I just see a tree
  1093.    getting on with the springtime business of tree-ness. Good on it.</p>
  1094.    <p>Now a longer story.
  1095.    What happened was, we had an extra-low tide. Tide is a big deal, we get 17 vertical feet at the extremes which can cause
  1096.    problems for boats and docks and if you happen to arrive with several days worth of supplies at low tide well it sucks to be
  1097.    you, because you’re gonna be toting everything up that much further.</p>
  1098.    <p>But I digress.</p>
  1099.    <img src="https://www.tbray.org/ongoing/When/202x/2025/05/27/PXL_20250525_172750708.png" alt="Purple sea stars hide among dark rocks" />
  1100.    <p>I went for a walk at low tide because you see things that are usually mostly hidden. For example these
  1101.    <a href="https://en.wikipedia.org/wiki/Starfish">starfish</a>, also known as sea stars or even “asteroids”. No, really, check
  1102.    that link.</p>
  1103.    <p>These are
  1104.    <a href="https://en.wikipedia.org/wiki/Pisaster_ochraceus"><i>Pisaster ochraceus</i></a>, distinguished by that pleasing violet color.
  1105.    Have a close look. They’re intertidal creatures hiding from the unaccustomed light and air. The important thing is that
  1106.    they’re more or less whole, which is to say free of
  1107.    <a href="https://en.wikipedia.org/wiki/Sea_star_wasting_disease">wasting disease</a>, of which there’s been a major epizootic in
  1108.    recent years. The disease isn’t subtle, it makes their arms melt away into purple goo; extremely gross.</p>
  1109.    <p>Plus, ecologies being what they are, there are downstream effects. Sea stars predate on sea urchins only recently they
  1110.    haven’t been because wasting disease. It turns out that sea urchins eat the kelp that baby shrimp trying to grow up hide in.
  1111.    Fewer stars, more urchins, less prawns. Which means that the commercial prawn-fishers have been coming up
  1112.    empty and going out of business.</p>
  1113.    <p>Anyhow, seeing a cluster of disease-free stars is nice, whether you’re in the seafood business or you just like
  1114.    the stars for their own sake, as I do.</p>
  1115.    <p>And light-green needles too. And spring. Enjoy it while you can.</p>
  1116. </div></content></entry>
  1117.  
  1118. <entry>
  1119. <title>The Lens of Spring</title>
  1120. <link href='https://www.tbray.org/ongoing/When/202x/2025/05/17/Springtime-Lens' />
  1121. <link rel='replies'        thr:count='3'        type='application/xhtml+xml'        href='/ongoing/When/202x/2025/05/17/Springtime-Lens#comments' />
  1122. <id>https://www.tbray.org/ongoing/When/202x/2025/05/17/Springtime-Lens</id>
  1123. <published>2025-05-17T12:00:00-07:00</published>
  1124. <updated>2025-05-18T11:53:07-07:00</updated>
  1125. <category scheme='https://www.tbray.org/ongoing/What/' term='The World/Economics' />
  1126. <category scheme='https://www.tbray.org/ongoing/What/' term='The World' />
  1127. <category scheme='https://www.tbray.org/ongoing/What/' term='Economics' />
  1128. <category scheme='https://www.tbray.org/ongoing/What/' term='Arts/Photos/Cameras' />
  1129. <category scheme='https://www.tbray.org/ongoing/What/' term='Arts' />
  1130. <category scheme='https://www.tbray.org/ongoing/What/' term='Photos' />
  1131. <category scheme='https://www.tbray.org/ongoing/What/' term='Cameras' />
  1132. <category scheme='https://www.tbray.org/ongoing/What/' term='Arts/Photos' />
  1133. <summary type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>Back in the early days of this blog, I used to publish posts that were mostly pictures of plants and flowers. Especially at this     time of year. I think that energy went into Twitter and now the Fediverse, where it’s so easy to take a picture and post it     right then. This week I got a freshly-repaired lens back from the shop and it put me in the mood to get closer to the     botanical frenzy springing at us from every direction. Herewith four pix of two plants, one of a lens, and more thoughts on a     familiar subject: Whether it’s better to repair than to replace</div></summary>
  1134. <content type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>
  1135.    <p>Back in the early days of this blog, I used to publish posts that were mostly pictures of plants and flowers. Especially at this
  1136.    time of year. I think that energy went into Twitter and now the Fediverse, where it’s so easy to take a picture and post it
  1137.    right then. This week I got a freshly-repaired lens back from the shop and it put me in the mood to get closer to the
  1138.    botanical frenzy springing at us from every direction. Herewith four pix of two plants, one of a lens, and more thoughts on a
  1139.    familiar subject: Whether it’s better to repair than to replace.</p>
  1140.    <p>The lens, by the way, was the
  1141.    <a href="https://www.fujifilm-x.com/en-ca/products/lenses/xf18-55mmf28-4-r-lm-ois/">Fuji 18-55</a> oops its full name is
  1142.    “Fujinon XF18-55mmF2.8-4 R LM OIS” so there. I
  1143.    <a href="/ongoing/When/201x/2013/03/06/Fuji-X-E1-in-Tokyo">bought it</a> in March of 2013 and have dropped it more than once; I
  1144.    have retained 1,432 pictures taken with it over the years. But then it stopped working.</p>
  1145.    <p>More words on that later, but pictures first.</p>
  1146.    <img src="https://www.tbray.org/ongoing/When/202x/2025/05/17/TXT55621.png" alt="A yellow Fru Dagmar Hastrup rose blossom" />
  1147.    <div class='caption'><p>Roses have names and this one is “Fru Dagmar Hastrup”. Therein
  1148.    <a href="/ongoing/When/200x/2008/06/26/Yellow-Rugosa">lies a tale</a> that is either 17 or 111 years old, depending how you
  1149.    count.</p></div>
  1150.    <p>That’s the first picture I took with the repaired 18-55. But then I thought that the whole point of this basic zoom was that
  1151.    you could go wide to capture big things, or long to, well, zoom in on ’em. So I went out front.</p>
  1152.    <img src="https://www.tbray.org/ongoing/When/202x/2025/05/17/TXT55626.png" alt="Looking up into the branches of a large deciduous tree" />
  1153.    <div class='caption'><p>Trees have names too. This is a
  1154.    <a href="https://en.wikipedia.org/wiki/Fraxinus_americana">White Ash</a> (<i>Fraxinus americana</i>).</p></div>
  1155.    <p>That ash is one of the trees lining the street we
  1156.    <a href="/ongoing/When/202x/2025/02/28/Moved">moved onto last October</a>. It’s really immense. Let’s crank the zoom way wide and
  1157.    capture most of it.  Doing this reveals really great geometry, so let’s subtract the color and add some
  1158.    <a href="https://nikcollection.dxo.com/nik-silver-efex/">Silver Efex</a> sizzle.</p>
  1159.    <img src="https://www.tbray.org/ongoing/When/202x/2025/05/17/TXT55625-Edit.png" alt="Black and white rendition of the spreading branches of a large tree" />
  1160.    <p>And then we can zoom back in.</p>
  1161.    <img src="https://www.tbray.org/ongoing/When/202x/2025/05/17/TXT55628.png" alt="The first fork in the trunk of a large tree, with moss and outgrowths" />
  1162.    <p>The closer you get, the better it looks.</p>
  1163.    <h2 id='p-1'>Fixing that lens</h2>
  1164.    <p>I like quirky fast compact opinionated prime lenses just as much as the next photoenthusiast, but a decent midrange zoom
  1165.    is just too useful not to have. I could’ve replaced this one with the new-fangled
  1166.    <a href="https://www.fujifilm-x.com/en-ca/products/lenses/xf16-50mmf28-48-r-lm-wr/">16-50mm</a> (also has a long complicated
  1167.    Real Name but never mind). That would cost me extra money and
  1168.    <a href="https://www.youtube.com/watch?v=1rLcCkilADY&amp;t=3s">might not even be better</a>.</p>
  1169.    <p>So I poked around on the Fujifilm Web site and sure enough, they offer repair as a service, just package it up and mail it
  1170.    in. A few days after doing so I got an email quoting me a price and asking for approval, which I granted.
  1171.    You shouldn’t be surprised. Way back in 2011 I wrote
  1172.    <a href="/ongoing/When/201x/2011/10/20/Worth-Repairing">Worth Fixing</a>, the exemplar of which was a different excellent lens.
  1173.    And then just last year my
  1174.    <a href="/ongoing/When/202x/2024/06/01/Parable-of-the-Sofa">Parable of the Sofa</a> touched a few
  1175.    nerves. So I didn’t think very hard about it.</p>
  1176.    <p>But then I realized I hadn’t even checked whether the price was reasonable. So I
  1177.    <a href="https://www.ebay.com/sch/i.html?_nkw=xf18-55">turned to eBay</a> and, well, I could have got a mint-condition
  1178.    secondhand 18-55 for less than the cost of the repair. Not a lot less, but still. Oh well. If it were reasonable to care
  1179.    about a single instance of a standardized commercial product, I’d care about that lens.</p>
  1180.    <p>Anyhow, it works pretty well. Showing its age, but still reasonably handsome.</p>
  1181.    <img src="https://www.tbray.org/ongoing/When/202x/2025/05/17/PXL_20250518_040716981.png" alt="Fujifilm x-T5 camera with the 18-55mm lens attached" />
  1182.    <p>If I live long enough maybe I’ll take another thousand pictures with it.</p>
  1183. </div></content></entry>
  1184.  
  1185. <entry>
  1186. <title>Long Links</title>
  1187. <link href='https://www.tbray.org/ongoing/When/202x/2025/05/06/Long-Links' />
  1188. <link rel='replies'        thr:count='5'        type='application/xhtml+xml'        href='/ongoing/When/202x/2025/05/06/Long-Links#comments' />
  1189. <id>https://www.tbray.org/ongoing/When/202x/2025/05/06/Long-Links</id>
  1190. <published>2025-05-06T12:00:00-07:00</published>
  1191. <updated>2025-05-08T14:22:54-07:00</updated>
  1192. <category scheme='https://www.tbray.org/ongoing/What/' term='The World' />
  1193. <category scheme='https://www.tbray.org/ongoing/What/' term='The World' />
  1194. <summary type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>Another <cite>Long Links</cite> curation (the 31<sup>st</sup>!); substantial pieces of reading (or watching or listening)     that you probably don’t have time to take in all of. One or two, though, might reward your attention. The usual assortmet of     music, geekery, and cosmology</div></summary>
  1195. <content type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>
  1196.    <p>Another <cite>Long Links</cite> curation (the 31<sup>st</sup>!); substantial pieces of reading (or watching or listening)
  1197.    that you probably don’t have time to take in all of. One or two, though, might reward your attention. The usual assortmet of
  1198.    music, geekery, and cosmology.</p>
  1199.    <h2 id='p-1'>Galactic clusters</h2>
  1200.    <p>Ever heard of
  1201.    <a href="https://en.wikipedia.org/wiki/Laniakea_Supercluster">Laniakea</a>? Neither had I. It’s another word for our home.
  1202.    This 7-minute YouTube video,
  1203.    <a href="https://www.youtube.com/watch?v=Ayj4p3WFxGk">The Laniakea supercluster of galaxies</a>, is graceful and mind-expanding;
  1204.    highly recommended.</p>
  1205.    <h2 id='p-2'>Atom Heart Mother</h2>
  1206.    <p>I was sitting up late, pretty mellow, and Google Music showed me
  1207.    <a href="https://www.youtube.com/watch?v=RqcNqRA07yQ">Atom Heart Mother</a> as performed by Japanese tribute band
  1208.    Pink Floyd Trips in 2016. It woke me right up. The Japanese
  1209.    hipsters are instrumentally strong and use keyboards for the acoustic-instrument parts. As for the vocals, well, oh my oh
  1210.    my, definitely
  1211.    next level. Good stuff.</p>
  1212.    <p>Which made me curious about other performances of <cite>Atom Heart Mother</cite>. Turns out Floyd recorded
  1213.    <a href="https://www.youtube.com/watch?v=jWR-aI1qtEU">a 1971 performance</a>, coincidentally also from Japan.
  1214.    Obviously they’re competent, but they’re just four guys and the keyboard technology was way more primitive back then, so they’re
  1215.    at a disadvantage compared to the resources they had in the studio when recording it, or the technology deployed by
  1216.    PF Trips. A lot of the visuals are of the band arriving in and traveling around Japan, which is OK, because their
  1217.    performances in that era weren’t particularly visually stimulating. Credit to Gilmour for hitting the high notes (albeit with
  1218.    some electronic assist), but once
  1219.    again, he’s at a disadvantage compared to the awesome Japanese singers.</p>
  1220.    <p>The arrangement is quite a bit different than the original on the eponymous album and, within the limitations, is good.</p>
  1221.    <p>There’s a cover by “Pussycherry et l'Orchestre d'harmonie de Clermont Ferrand” which I abandoned partway through because the
  1222.    orchestra just isn’t very good, clumsy and harsh. There is a nice little cello part though.</p>
  1223.    <p>I will link to
  1224.    <a href="https://www.youtube.com/watch?v=0ra6B5evR2o">Orchestre Philharmonique de Radio France with Ron Geesin at the Théâtre du
  1225.    Chatelet</a>, once again an orchestra and a chorus. Ron Geesin is the guy that Floyd hired to do all the orchestral stuff after
  1226.    they’d recorded the basic tracks and went on tour. The orchestra is way better but disappointingly equals neither Geesin’s
  1227.    original take on the album, nor PF Trips. And the big choir doesn’t come close to those two Japanese women.</p>
  1228.    <p>There are more performances out there, but I had to go to bed.</p>
  1229.    <h2 id='p-3'>C2PA C2PA C2PA</h2>
  1230.    <p>I have
  1231.    <a href="/ongoing/What/Technology/Identity/">written quite a bit</a> about
  1232.    <a href="https://c2pa.org/">C2PA</a> and other “Content Authenticity” initiative stuff. Recently, Adobe has released more
  1233.    C2PA-enabling technology in several of its apps, and there is commentary from
  1234.    <a href="https://www.dpreview.com/opinion/6029161962/adobe-content-authenticity-credentials-app-public-beta-ai-training">DPReview</a>
  1235.    and
  1236.    <a href="https://petapixel.com/2025/04/24/why-photographers-should-care-about-the-new-content-authenticity-app/">PetaPixel</a>.</p>
  1237.    <p>If you care about this stuff like I do you’ll probably enjoy reading both pieces. But they (mostly) miss what I think is the key
  1238.    point. The biggest value offered by this stuff is establishing provenance, and the most important place to establish provenance
  1239.    is on social media. Knowing that a pic on Fedi or Bluesky was first uploaded by <code>@joe@somewhere.example</code> is highly
  1240.    useful in helping people decide whether it’s real or not, and would not require a major technical leap from any social-media
  1241.    provider.</p>
  1242.    <h2 id='p-4'>Less attention</h2>
  1243.    <p>Joan Westerberg’s excellent
  1244.    <a href="https://www.joanwestenberg.com/notes-from-the-exit-why-i-left-the-attention-economy/">Notes from the Exit: Why I Left
  1245.    the Attention Economy</a> is full of passion and truth. About stepping off the “content creator” treadmill, she writes:</p>
  1246.    <blockquote><p>Leaving the attention economy doesn’t mean vanishing. It means choosing to matter to fewer people, more
  1247.    deeply. It means owning the means of distribution. It means publishing like a human being instead of a content mill. It means
  1248.    you stop playing to the house odds and start building your own game.</p></blockquote>
  1249.    <p>And the rest is just as good. For what it’s worth, what she’s describing is what I’ve been trying to do in this space for the
  1250.    last 22 years.</p>
  1251.    <!--
  1252.    <h2 id='p-5'>Monochromicity</h2>
  1253.    <p><a href="https://www.culture-critic.com/p/why-is-the-world-losing-color">Why is the world losing color?</a> is the question
  1254.    from Culture-critic.com. There’s no metaphor here, they’re talking about color literally, as in how and why monochrome color
  1255.    palettes are crowding out vibrant ones.</p>-->
  1256.    <h2 id='p-6'>Defective outlook</h2>
  1257.    <p>I don’t read <cite>The Register</cite> often enough; for many years they’ve been full of fresh takes and exhibited a usefully
  1258.    belligerant attitude. For example,
  1259.    <a href="https://www.theregister.com/2025/03/31/opinion_column_big_tech/">When even Microsoft can’t understand its own Outlook,
  1260.    big tech is stuck in a swamp of its own making</a> excoriates “the weird cruft that happens when Microsoft saws bits of our
  1261.    limbs off to make us fit into whatever profit center is running strategy today.” I actually disagree with some of the
  1262.    article, as I often do with the <cite>Reg</cite>, but I enjoyed reading it anyhow.</p>
  1263.    <h2 id='p-7'>A billion times a second</h2>
  1264.    <p>Time to put on your hardcore-geek hat and look at
  1265.    <a href="https://www.amazon.science/publications/formally-verified-cloud-scale-authorization">Formally verified cloud-scale
  1266.    authorization</a>. A group at AWS replaced a single heavily-used API call implementation with formally-verified code,
  1267.    simultaneously making it smaller and faster. The link is to an overview piece, the full PDF is
  1268.    <a href="https://assets.amazon.science/bb/40/22ac44f84f6d8eb625ac9666a00f/formally-verified-cloud-scale-authorization.pdf">here</a>.</p>
  1269.    <p>These are not lightweight technologies and this was not a cheap project; a lot of people did a lot of work and these are not
  1270.    junior people.  But when what you’re working on is this call:</p>
  1271.    <blockquote><p><code>Answer evaluate(List&lt;Policy> ps, Request r)</code></p></blockquote>
  1272.    <p>That call is at the core of where AWS grants or denies access by anything to anything, and it’s called more than a billion
  1273.    times a second. That’s billion with a B. A situation where this kind of investment isn’t merely justifiable, it’s a no-brainer.
  1274.    I know a couple of the people on the authors list, and I offer all of them my congratulations. Strong work!</p>
  1275.    <h2 id='p-8'>Decarbonization at sea</h2>
  1276.    <p>Regular readers know that my family has a boat, that we’re trying to
  1277.    <a href="/ongoing/When/202x/2020/01/19/Decarbonization">decarbonize our lives</a>, and that the boat has been the hardest part
  1278.    of that.</p>
  1279.    <p>So, I pay close attention to the latest news from the electric-boat scene.  I’m starting to gain confidence that in a
  1280.    single-digit number of years we’ll be using a quieter, cheaper, more environmentally praiseworthy vessel of some sort. So, in
  1281.    case anybody has similar worries, here are snapshots from a few of the more viable electric-boat startups:
  1282.    <a href="https://www.navierboat.com/about">Navier</a>,
  1283.    <a href="https://www.torqeedo.com/en/home">Torqueedo</a>,
  1284.    <a href="https://xshore.com/us/">X Shore</a>,
  1285.    <a href="https://candela.com">Candela</a>.  Also, here’s
  1286.    <a href="https://www.aqua-superpower.com">Aqua superPower</a>, which wants to bring dockside charging to the electric-boat
  1287.    scene.
  1288.    And finally, here is the
  1289.    <a href="https://electrek.co/guides/electric-boats/">Electric boats</a> category from the always-useful <cite>electrek</cite>
  1290.    electric-mobility site.</p>
  1291. </div></content></entry>
  1292.  
  1293. <entry>
  1294. <title>Censoring Social Media</title>
  1295. <link href='https://www.tbray.org/ongoing/When/202x/2025/04/28/Censoring-Social-Media' />
  1296. <link rel='replies'        thr:count='5'        type='application/xhtml+xml'        href='/ongoing/When/202x/2025/04/28/Censoring-Social-Media#comments' />
  1297. <id>https://www.tbray.org/ongoing/When/202x/2025/04/28/Censoring-Social-Media</id>
  1298. <published>2025-04-28T12:00:00-07:00</published>
  1299. <updated>2025-05-05T12:18:53-07:00</updated>
  1300. <category scheme='https://www.tbray.org/ongoing/What/' term='The World/Social Media' />
  1301. <category scheme='https://www.tbray.org/ongoing/What/' term='The World' />
  1302. <category scheme='https://www.tbray.org/ongoing/What/' term='Social Media' />
  1303. <summary type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>In mid-April      <a href='https://techcrunch.com/2025/04/23/government-censorship-comes-to-bluesky-but-not-its-third-party-apps-yet/'>we     learned</a> about Bluesky censoring accounts as demanded by the government of Türkiye. While I haven’t seen     coverage of who the account-holders were and what they said, the action followed on protests against Turkish autocrat Erdoğan      for ordering the arrest of an opposition leader<span class="dashes"> —</span> typical behavior by a     thin-skinned Führer-wannabe. This essay concerns how we might think about censorship, its mechanics, and how the ecosystems     built around ActivityPub and ATproto can implement and/or fight it</div></summary>
  1304. <content type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>
  1305.    <p>In mid-April
  1306.    <a href="https://techcrunch.com/2025/04/23/government-censorship-comes-to-bluesky-but-not-its-third-party-apps-yet/">we
  1307.    learned</a> about Bluesky censoring accounts as demanded by the government of Türkiye. While I haven’t seen
  1308.    coverage of who the account-holders were and what they said, the action followed on protests against Turkish autocrat Erdoğan
  1309.    for ordering the arrest of an opposition leader<span class='dashes'> —</span> typical behavior by a
  1310.    thin-skinned Führer-wannabe. This essay concerns how we might think about censorship, its mechanics, and how the ecosystems
  1311.    built around ActivityPub and ATproto can implement and/or fight it.</p>
  1312.    <p>That link above is to TechCrunch’s write-up of the situation, which is good. There’s going to be overlap between that and
  1313.    this but neither piece is a subset of the other, so you might want to read TechCrunch too.</p>
  1314.    <h2 id='p-1'>Censorship goals and non-goals</h2>
  1315.    <p>How, as the community of people who live and converse online, should we want our decentralized social media to behave?</p>
  1316.    <p>I’m
  1317.    restricting this to <em>decentralized</em> social media because the issues around censorship differ radically between
  1318.    a service owned and controlled by a profit-seeking corporation, and an ecosystem
  1319.    of interoperating providers who may not be in it for the money.</p>
  1320.    <p>So, from the decentralized point of view, what should be the core censorship goals? As Mencken said, “For every complex
  1321.    problem there is an answer that is clear, simple, and wrong.” Here are two of those:</p>
  1322.    <ol>
  1323.      <li><p>No censorship. Let people say what they will and the contest of ideas proceed. Freedom of speech must be
  1324.      absolute.</p></li>
  1325.      <li><p>Suppress any material which is illegal in the jurisdiction where the human participant is located. Stop there,
  1326.      because making policy in
  1327.      this area is not the domain of of social-media providers.</p></li>
  1328.    </ol>
  1329.    <h2 id='p-2'>“Free speech”?</h2>
  1330.    <p>The absolutists’ position is at least internally consistent. But it has two fatal flaws, one generic and one
  1331.    specific. In general, a certain proportion of people are garbage and will post terrible, hateful, damaging things that make
  1332.    the online experience somewhere in the range between unpleasant and intolerable, to the extent that many who deserve to be heard will
  1333.    be driven away.</p>
  1334.    <p>And specifically, history teaches us that certain narratives are dangerous to civic sanity and human life: Naziism, revanchism,
  1335.    hypernationalism, fomenting ethnic hatred, and so on.</p>
  1336.    <p>Another way to put this: Everyone has a basic right to free speech, but nobody has a right to be listened to.</p>
  1337.    <p>So, the Free Speech purists can now please show themselves out. (Disclosure: I didn’t mean that “please”.)</p>
  1338.    <h2 id='p-3'>“Rule of law”?</h2>
  1339.    <p>I can get partially behind this. If you’re running a social-media service in a civilized democratic country and posting
  1340.    X is against the law, you’d better think carefully about allowing X. (Not saying that civil disobedience is always wrong, just
  1341.    that you need to think about it.)</p>
  1342.    <p>But mostly no. The legalist approach suffers from positive and negative failures. Negative, as in censoring-is-wrong: I really
  1343.    DGAF about Turkish legal restrictions, because they’re more or less whatever Erdoğan says they are, and Erdoğan is a tinpot
  1344.    tyrant. Similarly, on Trump’s current trajectory it’ll soon be illegal to express anti-Netanyahu sentiment in the USA.</p>
  1345.    <p>Positive, as in not-censoring is wrong: Lolicon is legal in Japan and treated like
  1346.    <a href="https://en.wikipedia.org/wiki/CSAM">CSAM</a> elsewhere. Elsewhere is right, Japan
  1347.    is wrong. Another example: Anti-trans hate is increasingly cheerled by conservative culture warriors all over the place and  
  1348.    <a href="https://www.bbc.com/news/articles/crldey0z00ro">is now the official policy of the British government</a>. Sir Keir
  1349.    Starmer would probably be suspended from
  1350.    <a href="https://cosocial.ca">my Mastodon instance</a> and invited to find somewhere else, except for somewhere else would be
  1351.    mass-defederated if it tolerated foolish bigots like Starmer.</p>
  1352.    <h2 id='p-4'>How Bluesky does it</h2>
  1353.    <p>(I should maybe say “How ATproto does it” but this seems more reader-friendly.) It’s not as though they pushed some button
  1354.    and silenced the hated-by-Erdoğan accounts. In fact, it’s subtle and complicated.
  1355.    For details, see
  1356.    <a href="https://fediversereport.com/bluesky-censorship-and-country-based-moderation/">Bluesky, censorship and country-based
  1357.    moderation</a> by Laurens Hof at <cite>The Fediverse Report</cite>.  Seriously, if you think you might have an opinion about
  1358.    Bluesky and what they’re doing, go read Hof before you share it.</p>
  1359.    <p>Having said that, I think I can usefully offer a short form. Bluesky supports the use of multiple composable
  1360.    moderation services, and client software can decide which of them to subscribe to.  It provides a central moderation service
  1361.    aimed at stopping things like CSAM and genocide-cheerleading that’s designed to operate at the scale of the whole network, which
  1362.    seems good to me.</p>
  1363.    <p>It also offers “geographic moderation labelers”, which can attach “forbidden” signals to posts which are being read by people
  1364.    in particular areas.  That’s what they did in this case; the Erdoğan-hated accounts had those labels
  1365.    attached to their posts, but only for people who are in Türkiye.</p>
  1366.    <p>The default Bluesky client software subscribes to the geographic labeler and does as it’s told, which made Erdoğan and his
  1367.    toadies happy.</p>
  1368.    <p>But anyone can write Bluesky client software, and there’s nothing in the technology that requires clients to subscribe to or
  1369.    follow the instructions of any moderation service.  One alternate client,
  1370.    <a href="https://deer.social">Deer.social</a>, is a straightforward fork of the default, but with the geographic
  1371.    moderation removed. (It may have other features but looks about like basic Bluesky to me.)</p>
  1372.    <h2 id='p-5'>How the Fediverse does it</h2>
  1373.    <p>(I should maybe say “How ActivityPub does it” or “How Mastodon does it” but…) Each instance does its own moderation and
  1374.    (this is important) makes its own decision as to which other instances to federate with.  There are plenty of sites out there
  1375.    running Fediverse software that are full of CSAM and Lolicon and Nazis and so on. But the “mainstream” instances have
  1376.    universally defederated them, so it’s rare to run across that stuff. I never do.</p>
  1377.    <p>To make things easy, there are “shared block-lists” that try to keep up-to-date on the malignant instances. It’s early days
  1378.    yet but I think this will be a growth area.</p>
  1379.    <p>Most moderation is based on “reporting”<span class='dashes'> —</span> if you see something you think is abusive or breaks the
  1380.    rules, you can hit the “report” button, and the moderators for your instance and the source instance will get messaged and can
  1381.    decide what to do about it.</p>
  1382.    <p>The effect is that there is a shared culture across a few thousand “mainstream” instances that leads, in my opinion, to a
  1383.    pretty pleasing atmosphere and low abuse level. We have a problem in that it’s still too easy to for a bad person to post
  1384.    abusive stuff in a way that is
  1385.    <a href="/ongoing/When/202x/2024/07/30/Invisible-Attackers">hard for moderators to see</a>, but
  1386.    <a href="https://social.growyourown.services/@FediTips/114149382005729304">it’s being worked on</a> and I’m
  1387.    optimistic.</p>
  1388.    <h2 id='p-6'>Dealing with Erdoğan: Bluesky</h2>
  1389.    <p>So, suppose we want our social-media services to route around Erdoğan’s attempts to silence his political opponents. I do.
  1390.    How effective would Bluesky and the Fediverse be at that?</p>
  1391.    <p>Bluesky makes it easy: Just use an alternate client. Yay! Except for, most people don’t and won’t and shouldn’t have
  1392.    to. Boo!</p>
  1393.    <p>Still I dunno, in a place where the politics is hot, the word might get out on the grapevine and a lot of people could give
  1394.    another client a try. Maybe? Back in the day a <em>lot</em> of people used alternate Twitter clients, until Twitter stomped those
  1395.    out.  I’m not smart enough to predict whether this could really be effective at routing round Erdoğan. I lean pessimistic
  1396.    though.</p>
  1397.    <p>Wait, what about the Bluesky Web interface? Who needs a client anyhow! No luck; it turns out that that’s a
  1398.    big fat React app with mostly the same code that’s in the mobile apps. Oh well.</p>
  1399.    <p>Anyhow, this ignores the real problem. Which is that if Erdoğan’s goons notice that people are dodging the censorship they’ll
  1400.    go nuclear on Bluesky (the company) and tell them to just stop displaying those people’s posts and to do it right fucking
  1401.    now.</p>
  1402.    <p>If that doesn’t work, they have a lot of options, starting with just blocking access to bsky.app, and extending to arresting any
  1403.    in-country staff or, even better, their families. And throwing them in an unheated basement.  I dunno, a courageous and
  1404.    smart company might be able to fight back, but it wouldn’t be a good situation.</p>
  1405.    <p>And that’s a problem, because even though the ATproto is by design decentralized, in practice there’s only one central
  1406.    service that routes the firehose of posts globally. So my bet would be that Erdoğan wins.</p>
  1407.    <h2 id='p-7'>Dealing with Erdoğan: Fediverse</h2>
  1408.    <p>This is a very different picture. Block access to the app and a lot of people won’t notice because they use the browser,
  1409.    connecting to one of the thousands of Fediverse instances,
  1410.    desktop or mobile, and it’ll work fine.
  1411.    OK, how about finding out which instances the people they’re trying to ban
  1412.    are on, and going after those instances? If the instance is in a rule-of-law democracy, the Turks
  1413.    would probably be told to go pound sand.</p>
  1414.    <p>OK, so what if the Turks ferociously attacked the home servers of the Thought Criminals? No problemo, they’d migrate
  1415.    to a more resilient instance and, since this is the Fediverse, their followers might never notice, they’d just come along with
  1416.    them.</p>
  1417.    <p>Pretty quickly the Erdoğan gang are gonna end up playing whack-a-mole.
  1418.    In fact I think it’s going to be really, really hard in general for oppressive governments to censor the Fediverse.  Not
  1419.    impossible; the people who operate the
  1420.    <a href="https://en.wikipedia.org/wiki/Great_Firewall">Great Firewall</a> would probably find a way.</p>
  1421.    <p>When Bluesky progresses to the point that there isn’t a single essential company at the center of everything, it
  1422.    should be censorship-resilient too, for the same reasons.</p>
  1423.    <h2 id='p-8'>Take-aways</h2>
  1424.    <p>I think that, to resist misguided censorship by misguided governments, we need (at least) these things:</p>
  1425.    <ol>
  1426.      <li><p>A service with no central choke-points, but rather a large number of independent co-operating nodes.</p></li>
  1427.      <li><p>Accounts, and the follower relationships between them, are not tied to any single node.</p></li>
  1428.    </ol>
  1429.    <p>Clearly these conditions are necessary; we don’t know yet whether or not they’re sufficient.
  1430.    But I’m generally optimistic that decentralized social media has the potential to offer a pretty decent level of censorship
  1431.    resistance.</p>
  1432. </div></content></entry>
  1433.  
  1434. <entry>
  1435. <title>Southsiders</title>
  1436. <link href='https://www.tbray.org/ongoing/When/202x/2025/05/04/Southsiders' />
  1437. <link rel='replies'        thr:count='2'        type='application/xhtml+xml'        href='/ongoing/When/202x/2025/05/04/Southsiders#comments' />
  1438. <id>https://www.tbray.org/ongoing/When/202x/2025/05/04/Southsiders</id>
  1439. <published>2025-05-04T12:00:00-07:00</published>
  1440. <updated>2025-05-05T11:21:34-07:00</updated>
  1441. <category scheme='https://www.tbray.org/ongoing/What/' term='Sports/Soccer' />
  1442. <category scheme='https://www.tbray.org/ongoing/What/' term='Sports' />
  1443. <category scheme='https://www.tbray.org/ongoing/What/' term='Soccer' />
  1444. <category scheme='https://www.tbray.org/ongoing/What/' term='The World/Places/Vancouver' />
  1445. <category scheme='https://www.tbray.org/ongoing/What/' term='The World' />
  1446. <category scheme='https://www.tbray.org/ongoing/What/' term='Places' />
  1447. <category scheme='https://www.tbray.org/ongoing/What/' term='Vancouver' />
  1448. <category scheme='https://www.tbray.org/ongoing/What/' term='Arts/Photos' />
  1449. <category scheme='https://www.tbray.org/ongoing/What/' term='Arts' />
  1450. <category scheme='https://www.tbray.org/ongoing/What/' term='Photos' />
  1451. <summary type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>Ever been to a soccer match and noticed the “supporters section”, full of waving flags and drummers and wild enthusiasm?     Last Saturday I went there. And marched in their parade, even. I could claim it was anthropology research. But maybe it’s just     old guys wanna have fun. Which I did. Not sure if I will again</div></summary>
  1452. <content type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>
  1453.    <p>Ever been to a soccer match and noticed the “supporters section”, full of waving flags and drummers and wild enthusiasm?
  1454.    Last Saturday I went there. And marched in their parade, even. I could claim it was anthropology research. But maybe it’s just
  1455.    old guys wanna have fun. Which I did. Not sure if I will again.</p>
  1456.    <p>For the rest of this piece, when I say “football” I mean fútbol as in soccer, because that‘s what everyone on the scene says.</p>
  1457.    <h2 id='p-1'>Background</h2>
  1458.    <p><a href="https://www.mlssoccer.com">MLS</a> (for Major League Soccer) is the top-level football league in North America and,
  1459.    depending on whose ratings you believe, the 9<sup>th</sup> or 10<sup>th</sup> strongest league in the world.
  1460.    At the moment, the
  1461.    <a href="https://www.whitecapsfc.com">Vancouver Whitecaps</a> are the strongest team in MLS and are
  1462.    <a href="https://www.concacaf.com/rankings/club/">ranked #2 in Concacaf</a> which means North and Central America.
  1463.    That may become #1 if they win the
  1464.    win the <a href="https://www.concacaf.com/champions-cup/">Champions Cup Final on June 1<sup>st</sup> in Mexico City</a>, against
  1465.    #1-ranked
  1466.    <a href="https://cfcruzazul.com">Cruz Azul</a>.</p>
  1467.    <p>Who knows if these good times will last, but for
  1468.    the moment it means they’re kind of a big deal here my home town.
  1469.    I’ve become a fan, because the Whitecaps are fun to watch.</p>
  1470.    <p>Mind you, the team is for sale and will probably be snapped up by a Yankee billionaire and relocated to Topeka or somewhere.</p>
  1471.    <p>When I’ve been to Whitecaps games, I’ve always been entertained by the raucous energy coming out of the supporters section. They
  1472.    provide a background roar, shout co-ordinated insults at the other team and referee, have a drum section, and feature a waving
  1473.    forest of flags.</p>
  1474.    <h2 id='p-2'>Southsiders</h2>
  1475.    <p>They’re called that because they inhabit the south end of the stadium, behind the goal that the Whitecaps attack
  1476.    in the second half. Check out the
  1477.    <a href="https://vancouversouthsiders.ca">Web site</a>.</p>
  1478.    <p>So, on a manic impulse, I joined up. It didn’t cost much and got me a big-ass scarf with “Vancouver” on one side and
  1479.    “Southsiders” on the other.
  1480.    Which I picked up, along with a shiny new membership card, at
  1481.    <a href="https://www.dublincalling.com/vancouver/home">Dublin Calling</a>, a perfectly decent sports bar where the membership
  1482.    card gets you a discount.  I have to say that the Southsiders people were friendly, efficient, and welcoming.</p>
  1483.    <p>My son was happy to come along; we got to the bar long enough before The Parade to have a beer and perfectly OK bar food at
  1484.    what, especially with the discount, seemed a fair price.  This matters because the food and beer at the stadium is exorbitantly
  1485.    priced slop.</p>
  1486.    <h2 id='p-6'>Alternatives</h2>
  1487.    <p>Since I wrote this, I learned that there are actually
  1488.    <a href="https://www.whitecapsfc.com/matchday/supporter-groups">four different fan clubs</a>. Especially, check out
  1489.    <a href="https://vssg.ca">Vancouver Sisters</a>.</p>
  1490.    <h2 id='p-3'>The Parade</h2>
  1491.    <p>Forty-five minutes before game time, the fans leave Dublin Calling a couple hundred strong and march to the stadium,
  1492.    chanting dopey chants and singing dopey songs and generally having good clean fun.
  1493.    It’s a family affair.</p>
  1494.    <img src="https://www.tbray.org/ongoing/When/202x/2025/05/04/PXL_20250504_004756238.png" alt="Southsiders parade" />
  1495.    <p>Note: Kid on Dad’s shoulders. Flags. Spectators, and here’s a thing: When you’re in a loud cheerful parade, everybody smiles
  1496.    at you. Well, except for the drivers stuck at an intersection. Since we’re Canadian we’re polite, so we stop the parade at red
  1497.    lights. Sometimes, anyhow.</p>
  1498.    <img src="https://www.tbray.org/ongoing/When/202x/2025/05/04/PXL_20250504_005058831.png" alt="Southsiders parade" />
  1499.    <p>Note: Maximal fan. Scarves held aloft (this happens a lot). Blue smoke. Flags in Whitecaps blue and Canada red.</p>
  1500.    <p>When the parade gets to the stadium, everyone kneels.</p>
  1501.    <img src="https://www.tbray.org/ongoing/When/202x/2025/05/04/PXL_20250504_005738243.png" alt="Southsider parade kneels" />
  1502.    <img src="https://www.tbray.org/ongoing/When/202x/2025/05/04/PXL_20250504_005802321.png" alt="Southsider parade kneels" />
  1503.    <p>After a bit, someone starts a slow quiet chant, then they wind it up and up until everyone explodes to their feet and
  1504.    leaps around madly. That’s all then, time to pile into the stadium.</p>
  1505.    <img src="https://www.tbray.org/ongoing/When/202x/2025/05/04/PXL_20250504_010531982.png" alt="Inside BC Place stadium" />
  1506.    <p>Which is visually impressive on with the lid open on a sunny day.</p>
  1507.    <h2 id='p-4'>Indoor fun</h2>
  1508.    <p>The Southsiders section is General Admission, pick anywhere to stand. And I mean stand, there’s no sitting down while the
  1509.    game’s on. There’s a big flag propped up every half-dozen seats or so you can grab and wave when the spirit moves you.
  1510.    There’s a guy on a podium down at the front, facing the crowd, and he co-ordinates the cheers and songs and…
  1511.    He. Never. Stops.</p>
  1512.    <p>The Southsiders gleefully howl in joy at every good Whitecaps move and with rage at every adverse whistle, have
  1513.    stylized moves like for example whenever the opposing keeper launches a big goal kick everyone yells “You fat bastard!” No, I
  1514.    don’t know why.</p>
  1515.    <p>When I shared that I was going to do this crazy thing people wondered if it was safe, would I get vomited on, was there
  1516.    violence, and so on.  In the event it was perfectly civilized as long as you don’t mind a lot of noise and shouting. The
  1517.    beer-drinking was steady but I didn’t see anyone who seemed the worse for the wear.
  1518.    If it weren’t for all the colorful obscenity I’d be comfy bringing a kid along.</p>
  1519.    <p>The crowd is a little whiter than usual for Vancouver, mostly pretty young, male dominated, with a visible gay
  1520.    faction. Nothing special.</p>
  1521.    <img src="https://www.tbray.org/ongoing/When/202x/2025/05/04/PXL_20250504_024141039.png" alt="View from the Southsiders section at BC Place" />
  1522.    <p>Note: Canadian and rainbow flags. Somewhat obstructed view; the flags are out because a goal has just been scored, you can
  1523.    see the smoke from the fireworks. The opposing goal is a long way away.</p>
  1524.    <p>What’s good: Being right on top of any goals scored at the near end. The surges of shared emotion concerning the action in
  1525.    the game.</p>
  1526.    <p>What’s bad: Standing all through the game. The action at the other end is too far away. The songs and chants grow wearing
  1527.    after a while.</p>
  1528.    <h2 id='p-5'>The game</h2>
  1529.    <p>The Whitecaps won, which was nice. It was pretty close, actually, against a team that shouldn’t be much of a threat.
  1530.    But then, most of Vancouver’s best players were out in healing-from-injury or resting-from-overwork mode.
  1531.    I still think the Whitecaps are substandard at working the ball through the middle of the field, but do well at both ends; At
  1532.    the moment <a href="https://www.mlssoccer.com/standings/">the stats</a> seem to say that they’re on top
  1533.    both at scoring and preventing goals.</p>
  1534.    <p>Here’s what to do if you’re watching a game: If either Pedro Vite (#45) or Jayden Nelson (#7) get the ball, lean in and
  1535.    focus. Both those guys are lightning in a bottle. I’ve enjoyed watching this team more than any other Vancouver sports franchise
  1536.    ever. It probably can’t last.</p>
  1537.    <p>Will I do the Southsiders section again? Maybe. I suspect I’ll enjoy their energy and edge just as much
  1538.    even when I’m not in the section, plus I’ll get to sit down.  We’ll see.</p>
  1539.    <p>My son and I had fun. No regrets.</p>
  1540. </div></content></entry>
  1541.  
  1542. <entry>
  1543. <title>CL XLV: Island Spring</title>
  1544. <link href='https://www.tbray.org/ongoing/When/202x/2025/04/21/Happy-Island-Spring' />
  1545. <link rel='replies'        thr:count='1'        type='application/xhtml+xml'        href='/ongoing/When/202x/2025/04/21/Happy-Island-Spring#comments' />
  1546. <id>https://www.tbray.org/ongoing/When/202x/2025/04/21/Happy-Island-Spring</id>
  1547. <published>2025-04-21T12:00:00-07:00</published>
  1548. <updated>2025-04-24T12:02:55-07:00</updated>
  1549. <category scheme='https://www.tbray.org/ongoing/What/' term='The World/Cottage Life' />
  1550. <category scheme='https://www.tbray.org/ongoing/What/' term='The World' />
  1551. <category scheme='https://www.tbray.org/ongoing/What/' term='Cottage Life' />
  1552. <category scheme='https://www.tbray.org/ongoing/What/' term='Arts/Photos' />
  1553. <category scheme='https://www.tbray.org/ongoing/What/' term='Arts' />
  1554. <category scheme='https://www.tbray.org/ongoing/What/' term='Photos' />
  1555. <summary type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>Join me for a walk through a rain forest on a corner of a small island.     This is to remind everyone that even in a world full of bad news, the trees are still there.      From the slopes leading down to the sea they reach up for sunshine and rain,     offering no objections to humans walking     in the tall quiet spaces between them</div></summary>
  1556. <content type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>
  1557.    <p>Join me for a walk through a rain forest on a corner of a small island.
  1558.    This is to remind everyone that even in a world full of bad news, the trees are still there.
  1559.    From the slopes leading down to the sea they reach up for sunshine and rain,
  1560.    offering no objections to humans walking
  1561.    in the tall quiet spaces between them.</p>
  1562.    <p>[The island is
  1563.    <a href="https://en.wikipedia.org/wiki/Keats_Island_(British_Columbia)">Keats Island</a>, where we’ve
  1564.    <a href="/ongoing/What/The%20World/Cottage%20Life/">had a cabin since 2008</a>. It’s mostly just trees and cabins, you can buy an
  1565.    oceanfront mansion for millions or a basic Place That Needs Work for much less (as we did) or you can
  1566.    <a href="https://bcparks.ca/plumper-cove-marine-park">camp cheap</a>. Come on over sometime.]</p>
  1567.    <p>On the path up from the water to the cabin there’s this camellia that was unhappy at our home in the city, its flowers
  1568.    always stained brown even as they opened. So we brought it to the island and now look at it!</p>
  1569.    <img src="https://www.tbray.org/ongoing/When/202x/2025/04/21/PXL_20250418_211131388.png" alt="Camellia bush with many white and gold blossoms" />
  1570.    <p>One interior shot. On this recent visit I wired up this desk, a recent hand-me-down from old friend
  1571.    <a href="https://en.wikipedia.org/wiki/Tamara_Munzner">Tamara</a>.</p>
  1572.    <img src="https://www.tbray.org/ongoing/When/202x/2025/04/21/PXL_20250419_193220121.png" alt="A desk with a computer and outboard monitor and really great views" />
  1573.    <p>When I got it all wired up I texted her “Now I write my masterpiece” but
  1574.    instead I wrote that one
  1575.    <a href="/ongoing/When/202x/2025/04/16/Decentralized-Schemes">about URI schemes</a>, no masterpiece but I was happy with it. And
  1576.    anyhow, it’s lovely space to sit and tap a keyboard.</p>
  1577.    <p>Now the forest walk.</p>
  1578.    <img src="https://www.tbray.org/ongoing/When/202x/2025/04/21/PXL_20250420_190132412.png" alt="Pacific Northwest rain forest" />
  1579.    <p>These are rain forests and they are happy in their own way when it rains but I’m a <em>Homo sapiens</em>, we evolved in a
  1580.    sunny part of the world and my eyes welcome all those photons.</p>
  1581.    <p>In 2008 I was told that the island had been logged “100 years ago”. So most of these are probably in the Young-Adult tree
  1582.    demographic, but there are a few of the real old giants still to be seen.</p>
  1583.    <p>Sometimes the trees seem to dance with each other.</p>
  1584.    <img src="https://www.tbray.org/ongoing/When/202x/2025/04/21/TXT55561.png" alt="Tall bare tree trunks seem to dance" />
  1585.    <img src="https://www.tbray.org/ongoing/When/202x/2025/04/21/TXT55554.png" alt="Tall bare tree trunks seem to dance" />
  1586.    <p>Both of those pictures feature (but not exclusively) <i>Acer macrophyllum</i>, the bigleaf Maple, the only deciduous tree I
  1587.    know of that can compete for sun with the towering Cedar/Fir/Hemlock evergreens.  It’s beautiful both naked (as here) and in its
  1588.    verdant midsummer raiment.</p>
  1589.    <p>But sometimes when you dance too hard you can fall over. He are two different photographic takes on a bigleaf that seems to
  1590.    have lost its grip and is leaning on a nearby hemlock.</p>
  1591.    <img src="https://www.tbray.org/ongoing/When/202x/2025/04/21/PXL_20250420_185053570.png" alt="Tall trees leaning together" />
  1592.    <img src="https://www.tbray.org/ongoing/When/202x/2025/04/21/TXT55572.png" alt="Tall trees leaning together" />
  1593.    <p>And sometimes you can just totally lose it.</p>
  1594.    <img src="https://www.tbray.org/ongoing/When/202x/2025/04/21/TXT55552.png" alt="Nurse log rolled, laying a tree trunk flat" />
  1595.    <p>It is very common in these forests to see a tree growing out of a fallen log; these are called “nurse logs”. It turns out to
  1596.    be a high-risk arboreal lifestyle, as we see here. It must have been helluva drama when the nurse rolled.</p>
  1597.    <p>I’m about done and will end as I began, with a flower.</p>
  1598.    <img src="https://www.tbray.org/ongoing/When/202x/2025/04/21/TXT55560.png" alt="Small pink blossom, a bit tattered, the background out of focus" />
  1599.    <p>This is the blossom of a salmonberry (<i>Rubus spectabilis</i>) a member of the rose family. It has berries in late summer
  1600.    but they’re only marginally edible.</p>
  1601.    <p>It’s one of the first blossoms you see in the forest depths as spring struggles free of the shackles of the northwest
  1602.    winter.</p>
  1603.    <p>Go hug a tree sometime soon, it really does help.</p>
  1604. </div></content></entry>
  1605.  
  1606. <entry>
  1607. <title>Decentralizing Schemes</title>
  1608. <link href='https://www.tbray.org/ongoing/When/202x/2025/04/16/Decentralized-Schemes' />
  1609. <link rel='replies'        thr:count='11'        type='application/xhtml+xml'        href='/ongoing/When/202x/2025/04/16/Decentralized-Schemes#comments' />
  1610. <id>https://www.tbray.org/ongoing/When/202x/2025/04/16/Decentralized-Schemes</id>
  1611. <published>2025-04-16T12:00:00-07:00</published>
  1612. <updated>2025-04-21T11:08:00-07:00</updated>
  1613. <category scheme='https://www.tbray.org/ongoing/What/' term='Technology/Web' />
  1614. <category scheme='https://www.tbray.org/ongoing/What/' term='Technology' />
  1615. <category scheme='https://www.tbray.org/ongoing/What/' term='Web' />
  1616. <category scheme='https://www.tbray.org/ongoing/What/' term='The World/Social Media' />
  1617. <category scheme='https://www.tbray.org/ongoing/What/' term='The World' />
  1618. <category scheme='https://www.tbray.org/ongoing/What/' term='Social Media' />
  1619. <summary type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>I’m a fan of decentralized social media and that’s partly because I enjoy using it. But mostly because     history teaches that decentralization is the best basis for sustainable, resilient online     conversation. (Evidence? Email!) For the purpose of this      essay, let’s assume that you agree with me. Let’s also assume that our online life is still Web-flavored.     I’m going to describe a few unfortunate things that can happen in a decentralized world,     then look at a basic built-in feature of the Web that might make the problems go away</div></summary>
  1620. <content type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>
  1621.    <p>I’m a fan of decentralized social media and that’s partly because I enjoy using it. But mostly because
  1622.    history teaches that decentralization is the best basis for sustainable, resilient online
  1623.    conversation. (Evidence? Email!) For the purpose of this
  1624.    essay, let’s assume that you agree with me. Let’s also assume that our online life is still Web-flavored.
  1625.    I’m going to describe a few unfortunate things that can happen in a decentralized world,
  1626.    then look at a basic built-in feature of the Web that might make the problems go away.</p>
  1627.    <p>Let’s start with bad-experience scenarios</p>
  1628.    <h2 id='p-1'>Sharing pain</h2>
  1629.    <p>Suppose I post a picture to my social-media feed and since Ash follows me, it shows up in their stream. They can favorite
  1630.    or boost it, but let’s suppose they think their friend Layla might like it too, so they grab the link and drop into their chat window
  1631.    with Layla, or maybe they send her an email.</p>
  1632.    <p>By “link” I mean “URL”, and by “URL” I mean “URI” (the distinction will matter in a bit). Here’s what that looks like, first
  1633.    on the Fediverse:
  1634.    <br/> <a href="https://cosocial.ca/@timbray/114361121438267145"><code>https://cosocial.ca/@timbray/114361121438267145</code></a>
  1635.    <br/>And on Bluesky:
  1636.    <br/> <a href="https://bsky.app/profile/tbray.org/post/3lmxrkmwz5k2u"><code>https://bsky.app/profile/tbray.org/post/3lmxrkmwz5k2u</code></a></p>
  1637.    <p>Layla sees the link and clicks it or taps it and yay, there’s the picture. She dislikes it and wants to add a negative comment.
  1638.    On the Fediverse, if it turns out she’s logged onto
  1639.    <a href="https://cosocial.ca">CoSocial.ca</a> like me she’ll have no trouble, she can fire away.  If she’s logged into
  1640.    another instance (and the Fediverse has thousands) she’s out of luck, even though she’s got a live Fediverse session. She can
  1641.    paste the URL or just “@timbray” into her search window and that might get her there indirectly if she’s lucky.</p>
  1642.    <p>This is a bad experience.</p>
  1643.    <p>On Bluesky, it’ll probably just work. Well, for now. Because while Bluesky is based on the
  1644.    <a href="https://en.wikipedia.org/wiki/AT_Protocol">AT Protocol</a> (ATproto for short) which is in theory decentralized, at the
  1645.    moment Ash is logged into the “App View” at <code>bsky.app</code> just like I am, because in practice everybody
  1646.    on Bluesky is.</p>
  1647.    <p>But in a future where there are multiple ATproto App Views, which is to say when Bluesky becomes as decentralized as the
  1648.    Fediverse is today, we’re back with the Fediverse problem, because her browser doesn’t know that the URI
  1649.    identifies an ATproto post that she should be able to boost or like.</p>
  1650.    <h2 id='p-3'>Client pain</h2>
  1651.    <p>There’s another problem in this scenario. Suppose Layla <em>was</em> logged into CoSocial.ca, but she wasn’t using the
  1652.    default Mastodon client, but rather an alternative such as
  1653.    <a href="https://phanpy.social/">Phanpy</a> or
  1654.    <a href="https://elk.zone">Elk.zone</a>. When Layla clicks on that link she won’t be in her fave Fedi client but back in vanilla
  1655.    Mastodon.</p>
  1656.    <p>Not a good experience.</p>
  1657.    <h2 id='p-4'>Post portability pain</h2>
  1658.    <p>Let’s look at the URI for a different Fediverse post of a pretty picture:
  1659.    <br/> <a href="https://mastodon.cloud/@timbray/109508984818551909"><code>https://mastodon.cloud/@timbray/109508984818551909</code></a></p>
  1660.    <p>It’s one of my posts all right, but it’s not from <code>cosocial.ca</code>, it’s from
  1661.    <code>mastodon.cloud</code>, which was my first home on the Fediverse.  I left it in December 2022 because it
  1662.    was sold to another company which is sketchy, by which I mean
  1663.    <a href="https://en.wikipedia.org/wiki/Lolicon">Lolicon</a>-friendly.</p>
  1664.    <p>Whatever I think of whoever’s running <code>mastodon.cloud</code>, I have a lot of posts over there, some of which I care
  1665.    about. For now, they’re still there, but I’m not contributing any money to those guys, nor will I, so if they pull the plug and
  1666.    vanish I can’t complain. Only if they do, so do all those posts that I cared about back then and still do a bit.</p>
  1667.    <p>Another bad experience.</p>
  1668.    <h2 id='p-2'>URIs and schemes</h2>
  1669.    <p><i>[Anyone who already understands URIs schemes and so on can skip to the next section.]</i></p>
  1670.    <p>Let’s look at that Fediverse link again:<br/> <code>https://cosocial.ca/@timbray/114280972142347258</code></p>
  1671.    <p>I call it a “URI” because that’s the official name for what it is.
  1672.    What they look like and how to use them are very thoroughly specified
  1673.    in several Internet Engineering Task Force publications starting with
  1674.    <a href="https://datatracker.ietf.org/doc/html/rfc3986">RFC3986</a>. URLs are also URIs, but URIs can do surprising things that
  1675.    you’ve probably never seen in the world of ordinary URLs.</p>
  1676.    <p>The crucial thing about both the Fediverse and Bluesky URIs is that they begin with the magic letters “https” followed by a
  1677.    colon. All URIs
  1678.    begin with a short string and a colon; the string is called the URI <b>scheme</b>.  For each possible scheme, there’s a set of rules
  1679.    saying how to handle URIs of that flavor. If it’s “https”, then the rules say, using that Fediverse URI as an example, to make
  1680.    an encrypted connection to the server at <code>cosocial.ca</code> and ask it to send you
  1681.    <code>/@timbray/114280972142347258</code>. You’ll get some bytes that represent what the URI identifies.</p>
  1682.    <p><i>[Yes, I’m oversimplifying. Sorry.]</i></p>
  1683.    <p>While most of the URLs you’re ever likely to encounter begin with “https:” there are other schemes. Suppose your email is
  1684.    “tim@example.com”. Paste <code>mailto:tim@example.com</code> into your browser, hit Enter, and see what happens.  This is a URI
  1685.    whose scheme is “mailto” and it works just fine.</p>
  1686.    <p>When I tried this just now on my Mac, all three of Safari, Firefox, and Chrome noticed that I use the
  1687.    <a href="https://mimestream.com">Mimestream</a> mail app and popped that up. Which shows that somewhere in this computer there’s
  1688.    a notion of a registered handler for a particular URI scheme. Which is exactly what URI schemes were designed for.</p>
  1689.    <p>I mean, if I can install an email app to handle <code>mailto:</code> URIs, why can’t I install a Fediverse app to handle
  1690.    <code>fedi:</code>?</p>
  1691.    <p>There are lots of URI schemes! Here’s
  1692.    <a href="https://www.iana.org/assignments/uri-schemes/uri-schemes.xhtml">the official registry</a>. Now, most of these are
  1693.    marked as “provisional” which means “we’re just reserving this scheme because we think we’re going to use it” and even among the
  1694.    ones that aren’t provisional, very few of them are in widespread enough use that you can expect your browser to handle them.</p>
  1695.    <p>You’ll notice that the <code>at:</code> scheme is in there, registered by the Bluesky people (after I suggested they do so). For the
  1696.    Fediverse, I see
  1697.    <a href="https://fedilinks.org/spec/en/6-The-web-ap-URI"><code>web+ap:</code></a> (which I’d never heard of before starting to
  1698.    write this).</p>
  1699.    <p>Let’s suppose that there were URI schemes for both ATproto (<code>at:</code>) and the Fediverse(I
  1700.    <a href="https://github.com/timbray/fedi-uri">suggest <code>fedi:</code></a>
  1701.    rather than <code>web+ap:</code> for reasons I’ll discuss later).
  1702.    Let’s also suppose that they were well supported by operating systems and browsers. I claim that this would help solve all three
  1703.    of those pain
  1704.    scenarios.</p>
  1705.    <h2 id='p-5'>Solving sharing and client pain</h2>
  1706.    <p>Remember, Ash copied the URI for a post and dropped into their chat window with Layla; when Layla clicked it, she saw the
  1707.    post but couldn’t boost it or reply to it.</p>
  1708.    <p>But suppose it began with either <code>at:</code> or
  1709.    <code>fedi:</code><span class='dashes'> —</span> then the computer or mobile would dispatch to whatever Layla uses to interact
  1710.    with ATproto/Fediverse software, and it’d know how to go about opening that post in the way Layla expects so she can reply and
  1711.    boost and so on. I’m ignoring
  1712.    the details of how that’d work, and some of them are tricky, but <em>this could be done</em>.</p>
  1713.    <h2 id='p-6'>Solving migration pain</h2>
  1714.    <p>This is a little more ambitious, but remember that “mastodon.cloud” post that might go away some day if the server does?
  1715.    Suppose we change it slightly, like so:
  1716.    <br/> <code>fedi://mastodon.cloud/@timbray/109508984818551909</code></p>
  1717.    <p>Once again, because it begins with “fedi:” not “https:”, the job would be handed off to Fediverse-savvy software. And since
  1718.    the Fediverse already knows how to migrate accounts from one server to another and bring your followers along, why shouldn’t it
  1719.    also copy your posts and store them somewhere, and when it hits that URI, remember “Oh wait, that @timbray@mastodon.cloud handle
  1720.    migrated a couple of times but that’s OK, I still have the posts from the old servers stored away so I can fetch that post
  1721.    rather than just giving up because mastodon.cloud went away”.</p>
  1722.    <p>Now, as far as I know, Mastodon doesn’t have any capabilities like that, nor does any other Fediverse software.  But once
  1723.    again, it’s a thing that <em>could be done</em>. And if we
  1724.    have a new URI scheme, there’d be a hook to hang that kind of software on.</p>
  1725.    <p>At the moment, ATproto/Bluesky is a lot closer to being able to do this. Your ATproto account isn’t tied to the server
  1726.    you happen to be logged into when you posted it, it’s a long-lived asymmetric-crypto based thing and it assumes that there’ll be
  1727.    per-account storage not tied to any particular App View. Also posts are identified by content hash, which should be helpful.</p>
  1728.    <p>But as far as I know, even with ATproto, if my browser’s visiting the <code>bsky.app</code> App View and I shoot a URL beginning
  1729.    with <code>https://bsky.app</code> to someone on the <code>blacksky.web.xyz</code> App View, I don’t see how the browser can
  1730.    figure out that that URL should invoke ATproto software.</p>
  1731.    <p>But if it began <code>at://bsky.capp</code>, it’d be perfectly tractable (I think).</p>
  1732.    <h2 id='p-7'>Scheme details and problems</h2>
  1733.    <p>There multiple proposals for a Fediverse URI scheme. I already mentioned <code>web+ap:</code> and then there’s
  1734.    <a href="https://codeberg.org/fediverse/fep/src/branch/main/fep/07d7/fep-07d7.md"><code>web+activitypub:</code></a> from
  1735.    <a href="https://codeberg.org/silverpill">silverpill</a> (which may be the same?), and
  1736.    <a href="https://github.com/timbray/fedi-uri"><code>fedi:</code></a> from me. The “web+” ones are more descriptive but mine is
  1737.    cooler and I think that matters.
  1738.    The proposals include useful discussions of the issues, which include those discussed in this essay; if you care about this
  1739.    stuff I think both would reward a read.</p>
  1740.    <p>I also have to note
  1741.    <a href="https://github.com/mastodon/mastodon/issues/19679#issuecomment-1301180085">this</a> from Mastodon author Eugen Rochko
  1742.    back in 2022:
  1743.    “We've done this before but removed because browser support / UX was inadequate.”</p>
  1744.    <p>(Before I go on I should point out that Eugen is right about support for alternate schemas in Web browsers being weak, but
  1745.    not all of them.
  1746.    On
  1747.    Android, any app can register itself to handle URIs of a particular scheme. I assume iOS has something similar? So this
  1748.    isn’t completely science-fictional.)</p>
  1749.    <p>So using URI schemees isn’t a new idea and yeah, patchy browser support is a problem.
  1750.    The people who build Safari and Chrome and Firefox are busy and are fanatically concerned
  1751.    with security and stability for their billions of users, and if I go and tap them on the shoulder and say “Here are new schemes
  1752.    and here’s the decentralized-social-media software I want registered to handle them” they’re not gonna to just say “Okay” and do
  1753.    it.</p>
  1754.    <p>Bit I dunno, the times they are a changin’. As Bluesky and the Fediverse build momentum, and the decentralized path forward looks more and more
  1755.    attractive, the case for new URI schemes probably becomes easier to make.</p>
  1756.    <p>As it should. Because the notion of the URI is a core foundational piece of the Web’s architecture, and the design of URIs has
  1757.    multiple protocol support baked in, and the URI schemes exist specifically to enable it.</p>
  1758.    <p>So, we should work on using it.</p>
  1759. </div></content></entry>
  1760.  
  1761. <entry>
  1762. <title>Coachella 2025</title>
  1763. <link href='https://www.tbray.org/ongoing/When/202x/2025/04/14/Coachella-2025' />
  1764. <link rel='replies'        thr:count='3'        type='application/xhtml+xml'        href='/ongoing/When/202x/2025/04/14/Coachella-2025#comments' />
  1765. <id>https://www.tbray.org/ongoing/When/202x/2025/04/14/Coachella-2025</id>
  1766. <published>2025-04-14T12:00:00-07:00</published>
  1767. <updated>2025-04-16T11:01:25-07:00</updated>
  1768. <category scheme='https://www.tbray.org/ongoing/What/' term='Arts/Music' />
  1769. <category scheme='https://www.tbray.org/ongoing/What/' term='Arts' />
  1770. <category scheme='https://www.tbray.org/ongoing/What/' term='Music' />
  1771. <summary type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>Last weekend I spent a few hours watching Coachella on YouTube. The audio and video quality are high. It’s free of ad     clutter, but maybe that’s because I pay for Google Music? The quality of the music is all over the map. If I read     <a href='https://www.coachella.com/schedule'>the schedule</a> correctly, they’ll repeat the exercise next weekend, so I thought     a few recommendations might be helpful. Even if it’s not available live, quite a few captures still seem to be     there on YouTube, so check ’em out</div></summary>
  1772. <content type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>
  1773.    <p>Last weekend I spent a few hours watching Coachella on YouTube. The audio and video quality are high. It’s free of ad
  1774.    clutter, but maybe that’s because I pay for Google Music? The quality of the music is all over the map. If I read
  1775.    <a href="https://www.coachella.com/schedule">the schedule</a> correctly, they’ll repeat the exercise next weekend, so I thought
  1776.    a few recommendations might be helpful. Even if it’s not available live, quite a few captures still seem to be
  1777.    there on YouTube, so check ’em out.</p>
  1778.    <p>I tried sorting these into themes but that tied me in knots, so you get alphabetical order.</p>
  1779.    <img src="https://www.tbray.org/ongoing/When/202x/2025/04/14/LG-skeleton.png" alt="Lady Gaga at Coachella 2025" />
  1780.    <div class='caption'><p>Lady Gaga brings it.</p></div>
  1781.    <h2 id='p-1'>Blonde Redhead</h2>
  1782.    <p>Not sure what kind of music to call this, but the drums and guitar (played by identical twins Simone and Amedeo Pace) are
  1783.    both hot, and Kazu Makino
  1784.    on everything else has loads of charisma, and they all sang well. Didn’t regret a minute of my time with this one.</p>
  1785.    <h2 id='p-2'>Ben Böhmer</h2>
  1786.    <p>I have no patience whatsoever for EDM. Deadmau5 and Zedd and their whole tribe should go practice goat-herding in Bolivia or
  1787.    anything else that’ll keep them away from audiences who want to hear music played by musicians. But there were multiple artists
  1788.    this year you could describe as X+EDM for some value of X, and much to my surprise a few of them worked.</p>
  1789.    <p>(One that notably didn’t was
  1790.    <a href="https://en.wikipedia.org/wiki/Parcels_(band)">Parcels</a>, whose genius idea is EDM+Lightweight Aussie pretty-boy pop. On
  1791.    top of which, every second of their
  1792.    performance featured brilliant lights strobing away, shredding my retinas and forebrain.
  1793.    I say it’s EDM and I say to hell with it. Go back to Australia and stay.)</p>
  1794.    <p>But Mr Böhmer not only held my attention but had my toes tappin’. His stuff isn’t just hot dance moves against
  1795.    recorded tracks, it’s moody and cool and phase-shifty and dreamy. It helps that he plays actual musical notes on actual
  1796.    keyboards.</p>
  1797.    <h2 id='p-4'>Beth Gibbons</h2>
  1798.    <p>I thought “I remember that name.” (Sadly, on first glance at the schedule I did <em>not</em> in fact
  1799.    recognize many names.) Ms Gibbons was the singer for Portishead, standard-bearers of Trip-hop back in
  1800.    the day. Her voice sounds exactly the same today as it did three decades ago, which is to say vulnerable and lovely.</p>
  1801.    <p>The songs were all new (aside from Portishead’s <cite>Glory Box</cite>) and good.
  1802.    Beth never had any stage presence and
  1803.    still doesn’t, draped motionless over the mike except when she turns away from the crowd to watch someone soloing.</p>
  1804.    <p>What made the show a Coachella highlight was the band, who apparently had just arrived from another planet.
  1805.    It was wonderfully strange as in I didn’t even know what some of the instruments were. Anyhow
  1806.    it all sounded great albeit weird, the perfect complement to
  1807.    Beth’s spaced-out (I mean that in the nicest way) vocal arcs.</p>
  1808.    <h2 id='p-5'>Go-Gos</h2>
  1809.    <p>This posse of sixtysomething women won my heart in the first three seconds of their set with a blast of girl-group punk/surf
  1810.    guitar noise and a thunderous backbeat. The purest rock-&amp;-roll imaginable, played with love and bursting with joy. They can
  1811.    sing, they can play, they
  1812.    still have plenty of moves. It‘s only rock and roll but I like it, like it, yes I do.</p>
  1813.    <h2 id='p-7'>HiTech</h2>
  1814.    <p>OK, this is another X+EDM, where the X is
  1815.    “<a href="https://en.wikipedia.org/wiki/Ghettotech">Ghettotech</a>, house, Rap &amp; Miami base” (quoting
  1816.    <a href="https://hitechdetroit.co/about">their Web site</a>). I have no idea what “Miami base” is but I guess I like it, because
  1817.    they’re pretty great. Outta Detroit.</p>
  1818.    <p>Their set was affably chaotic, the rapping part sharp-edged and hot, and they had this camera cleverly mounted on the
  1819.    DJ deck giving an intense close-up of whichever HiTech-ers were currently pulling the levers and twisting the knobs. Sometimes
  1820.    it was all three of them and that was great fun to watch.</p>
  1821.    <p>I’m an elderly well-off white guy and am not gonna pretend to much understanding of any of HiTech’s genres, but
  1822.    I’m pretty confident that a lot of people would be entertained.</p>
  1823.    <h2 id='p-6'>Kraftwerk sigh</h2>
  1824.    <p>They are historically important but the show, I dunno, I seem to recall being impressed in 1975 but it felt kinda static and
  1825.    tedious. The only reason I mention them is that a few of their big video-backdrop screens, near the start of the set, were
  1826.    totally Macrodata Refinement, from <cite>Severance</cite>. I wonder if any of the showrunners were Kraftwerk fans?</p>
  1827.    <h2 id='p-8'>LA Phil, conducted by Gustavo Dudamel</h2>
  1828.    <p>Give Coachella credit for giving this a try. Dudamel is a smart guy and put together a program that wasn’t designed
  1829.    to please a heavy classics consumer like me. I mean, opening with <cite>Ride of the Valkyries</cite>?  But there were
  1830.    two pieces of Bach and the orchestra turned into a backup band for Laufey, an Icelandic folk/jazz singer, a Gospel
  1831.    singer/choir, and some other extremely random stuff. If you’re not already a classics fan, this might open your eyes a bit.</p>
  1832.    <h2 id='p-3'>Lady Gaga</h2>
  1833.    <p>I’m sure you’ve already read one or two rave write-ups about this masterpiece. It’s going to be one of the
  1834.    performances remembered by name forever, like Prince at the Superbowl or Muddy Waters at the Last Waltz.
  1835.    They built a freaking opera house in the desert, and that makes me wonder what the Coachella economics are; someone has to pay
  1836.    for this stuff, do Gaga and Coachella split it or is it the price of getting her to come and play?</p>
  1837.    <p>To be fair, as the review in <cite>Variety</cite> accurately noted, it was pretty well New-York-flavored hoofing and
  1838.    belting wrapped in a completely incomprehensible Goth/horror narrative. So what?! The songs were great. The singing was
  1839.    fantastic and the dancing white-hot, plus she had a pretty hard-ass live metal-adjacent band and an operatic string section, and she
  1840.    brought her soul along with her and unwrapped it. It was easy to believe she loved the audience just as much as she said. She
  1841.    didn’t leave anything on the stage. They should make it into a big-screen movie.</p>
  1842.    <p>I did feel a little sorry for the physical audience, quite a bit of the performance seemed to be optimized for couch potatoes
  1843.    with big
  1844.    screens like for example me. Anyhow, if you get a chance to see this one don’t miss it.</p>
  1845.    <h2 id='p-10'>Other headliners?</h2>
  1846.    <p>There were three nights and thus three headliners. You’ll notice that I only talked up Friday night’s Lady-Gaga set. That’s
  1847.    because the other two were some combination of talentless and uninspired and offensive. Obviously I’m in a minority here, they
  1848.    wouldn’t get the big slots if millions didn’t love ’em. And I like an unusually wide variety of musical forms. But not that shit.</p>
  1849. </div></content></entry>
  1850.  
  1851. <entry>
  1852. <title>The CoSocialist Future</title>
  1853. <link href='https://www.tbray.org/ongoing/When/202x/2025/04/05/The-CoSocialist-Future' />
  1854. <link rel='replies'        thr:count='4'        type='application/xhtml+xml'        href='/ongoing/When/202x/2025/04/05/The-CoSocialist-Future#comments' />
  1855. <id>https://www.tbray.org/ongoing/When/202x/2025/04/05/The-CoSocialist-Future</id>
  1856. <published>2025-04-05T12:00:00-07:00</published>
  1857. <updated>2025-04-05T14:06:37-07:00</updated>
  1858. <category scheme='https://www.tbray.org/ongoing/What/' term='The World/Social Media' />
  1859. <category scheme='https://www.tbray.org/ongoing/What/' term='The World' />
  1860. <category scheme='https://www.tbray.org/ongoing/What/' term='Social Media' />
  1861. <summary type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>This week marks the second anniversary of     <a href='https://blog.cosocial.ca/blog/its-happening/'>the launch</a> of the     <a href='https://cosocial.ca'>CoSocial.ca</a> Mastodon server, which is     <a href='https://cosocial.ca/@timbray'>one leg</a> of my online presence (the other is     <a href='https://www.tbray.org/ongoing'>this blog</a>.)     I’ve never been more convinced that online social interaction has to change paths and take a new direction.      And I think CoSocial has lessons to teach about that direction. Here are some</div></summary>
  1862. <content type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>
  1863.    <p>This week marks the second anniversary of
  1864.    <a href="https://blog.cosocial.ca/blog/its-happening/">the launch</a> of the
  1865.    <a href="https://cosocial.ca">CoSocial.ca</a> Mastodon server, which is
  1866.    <a href="https://cosocial.ca/@timbray">one leg</a> of my online presence (the other is
  1867.    <a href="https://www.tbray.org/ongoing">this blog</a>.)
  1868.    I’ve never been more convinced that online social interaction has to change paths and take a new direction.
  1869.    And I think CoSocial has lessons to teach about that direction. Here are some.</p>
  1870.    <p>A personal note: I’ve been fortunate in that bits and pieces of my career have felt like
  1871.    building the future.  For example, right now, about the Fediverse generally and CoSocial in particular.
  1872.    In this essay I’ll try to explain why. But it’s a fine feeling.</p>
  1873.    <h2 id='p-8'>Decentralized</h2>
  1874.    <p>This is maybe the biggest thing.  The Web, by design, is decentralized. You don’t need permission to put up any kind of Web
  1875.    server or service. Social media should follow the decentralized path blazed by the Web and by the world’s oldest and most
  1876.    successful conversational app, namely email.</p>
  1877.    <p>It seems painfully obvious that a network of thousands or millions of servers, independently operated, sizes ranging from tiny
  1878.    to huge, is inherently more flexible and resilient than having all the conversations owned and operated by one
  1879.    globally-centralized business empire.</p>
  1880.    <p>To be decentralized, you need a protocol framework so the servers can talk to each other. CoSocial uses ActivityPub, which
  1881.    at the moment I think is the best choice.</p>
  1882.    <p>Some smart people who like the Bluesky experience are trying
  1883.    to make its AT Protocol work in a way that’s as demonstrably decentralized as ActivityPub is today. Maybe they’ll
  1884.    succeed; then operations like CoSocial should maybe consider it as an alternative. We’ll see.</p>
  1885.    <h2 id='p-5'>Not for profit</h2>
  1886.    <p>Our goals do not include enriching any investors. We plan to pay the people who do the work and
  1887.    <a href="https://blog.cosocial.ca/blog/wanted-system-administrator/">have just advertised for our first paid position</a>.</p>
  1888.    <p>We’re not-for-profit because the goals of the investor community are incompatible with a healthy online experience. In 2025,
  1889.    companies are judged on profit growth; everything else is secondary.  If you can grow your audience organically, good, but the
  1890.    world is finite, so when you’ve attracted everyone you’re going to, you’re going to have to focus on raising prices and reducing
  1891.    costs. Which is likely to produce an unpleasant experience for the people you serve.</p>
  1892.    <p>Cory Doctorow
  1893.    <a href="https://doctorow.medium.com/social-quitting-1ce85b67b456">aptly uses “enshittification”</a> to describe this
  1894.    often-observed pattern.</p>
  1895.    <h2 id='p-6'>A registered co-operative</h2>
  1896.    <p>There are a lot of different ways to set up a not-for-profit. The simplest organization is no organization: Someone buys a
  1897.    domain name, puts up a server, invites people on board, and uses Patreon donations to keep the lights on.</p>
  1898.    <p>Which is exactly what
  1899.    <a href="https://mstdn.ca/@chad">Chad</a> did at
  1900.    <a href="https://mstdn.ca">Mstdn.ca</a>, and it seems to be working OK. It’s a testament
  1901.    to the strong fibres of the Web, still there after all these decades of corrupting big money, that you can just do this without
  1902.    asking anyone’s permission, and get away with it.</p>
  1903.    <p>But we didn’t. We are a registered co-operative in BC, Canada’s westernmost province. It took us a couple of months to pull
  1904.    together the Board and constitution and bylaws. We have to file annual reports and comply with
  1905.    <a href="https://www.bclaws.gov.bc.ca/civix/document/id/complete/statreg/99028_01">governing legislation</a>.</p>
  1906.    <p>I am absolutely not going to suggest that a cooperative is the optimal not-for-profit approach. But I am pretty convinced that
  1907.    if you want to be treated as an organic component of civil society, you should work within its frameworks. Plus, it seems to me,
  1908.    on the evidence, that member-owned cooperatives are a pretty great way to organize human activities.</p>
  1909.    <h2 id='p-7'>More than a click to join</h2>
  1910.    <p>As I write this, most modern social-media products let you just roll up to the Web site and say “I wanna join”,
  1911.    and they say “click here”. Or even just make a couple of API calls.</p>
  1912.    <p>We’re not like that. You have to apply for membership and offer a few words about why. Then you have to
  1913.    <em>[*gasp*]</em> pay. A big fifty Canadian dollars a year buys a co-op membership and a Fediverse account. The first year of
  1914.    Fediverse is $40 so we can book $10 of your initial payment as payment for a CoSocial share (refundable if you later cancel).</p>
  1915.    <p>When you apply, we check that you did so from an IP address in Canada, we glance at your reasons for wanting to join, then if you
  1916.    haven’t already contributed, we send you an email asking you to pony up and, once you have, we let you in.</p>
  1917.    <p>The whole thing takes maybe five minutes of effort from the new member and a CoSocial moderator.</p>
  1918.    <p>What matters about this process? The fact that it exists. Nicole the Fediverse Chick can’t get a CoSocial account, nor can
  1919.    any other flavor of low-rent griefer or channer or MAGA chud. Just the fact that you can’t join by calling a few APIs filters
  1920.    out most of the problems, and then being asked to, you know, pay a little money, takes care of the rest.</p>
  1921.    <p>Which is to say, being a CoSocial moderator is dead easy. Sure, we get reports on our members from time to time. So far,
  1922.    zero have been really worrying. On a small single-digit-number of times, we’ve asked a member to consider the fact that they
  1923.    seem to be irritating some people.</p>
  1924.    <p>And we throw reports from
  1925.    <a href="https://en.wikipedia.org/wiki/Public_diplomacy_of_Israel#:~:text=Hasbara">Hasbara</a> keyboard warriors and similarly
  1926.    non-credible sources on the floor.</p>
  1927.    <p>The key take-away: Imposing just a little teeny-tiny bit of friction on the onboarding process seems to achieve
  1928.    troll-resistance in one easy step.</p>
  1929.    <h2 id='p-9'>Transparent</h2>
  1930.    <p>We have a bank account and credit cards and so on, but we run all our finances through a nice service called OpenCollective.
  1931.    Which makes all our financial moves 100% transparent:
  1932.    <a href="https://opencollective.com/cosocial">Here they are</a>.</p>
  1933.    <h2 id='p-10'>No Advertising</h2>
  1934.    <p>CoSocial has none, and never will.</p>
  1935.    <p>It is a repeating pattern that advertising-supported
  1936.    social-media products offered by for-profit enterprises become engulfed in a tempest of
  1937.    controversy and litigation.</p>
  1938.    <p>Since it’s axiomatic that centralized social media has to be free to use, ads are required, which means
  1939.    the advertisers are the customers. Those customers will continuously agitate for more intrusive advertising capabilities and
  1940.    for brand protection by avoiding sex, activism, or anything that might make anyone uncomfortable.</p>
  1941.    <p>I don’t know about you, but I’m interested in sex and activism.</p>
  1942.    <p>Intellectually, I appreciate that advertising should be a normal facet of a functional economy. How else am I going to find
  1943.    out what’s for sale?  But empirically, advertising as it’s done now seems to exert a powerfully corrupting influence.</p>
  1944.    <h2 id='p-11'>The only way forward?</h2>
  1945.    <p>I’m not claiming that CoSocial is. But I am arguing <em>strongly</em> for the combination of decentralization, not-for-profit,
  1946.    legal registration, non-zero onboarding friction, transparency, and advertising rejection.
  1947.    There are lots of ways to shape resilient social-media products that do these things. There are other legally
  1948.    regulated non-profit structures that aren’t co-ops.</p>
  1949.    <p>Also, there are plenty of other organizations that would benefit from
  1950.    hosting social-media voices: Government departments, academic institutions, sports teams, fan clubs, marketing groups,
  1951.    professional societies, videogame platforms, and, well, the list is long.</p>
  1952.    <h2 id='p-12'>How’s CoSocial doing?</h2>
  1953.    <p>Slow and steady.  We’re tiny, less than 200 strong, but we get a few new members every month. Two years in, a grand total
  1954.    of two members have decided not to renew.</p>
  1955.    <p>We’ve got a modestly pleasing buildup of money in the bank account, which means that we need to get serious about
  1956.    becoming less volunteer-centric, and thus more resilient.</p>
  1957.    <p>The service is fun to use, it’s reliable, and about as troll-free as can be.
  1958.    <a href="https://cosocial.ca/auth/sign_up">Come on in</a>!</p>
  1959.    <p>(But only if you’re in Canada and willing to pay a bit.)</p>
  1960. </div></content></entry>
  1961.  
  1962. <entry>
  1963. <title>Latest Music (feat. Qobuz)</title>
  1964. <link href='https://www.tbray.org/ongoing/When/202x/2025/03/27/Music-Plus-Qobuz' />
  1965. <link rel='replies'        thr:count='6'        type='application/xhtml+xml'        href='/ongoing/When/202x/2025/03/27/Music-Plus-Qobuz#comments' />
  1966. <id>https://www.tbray.org/ongoing/When/202x/2025/03/27/Music-Plus-Qobuz</id>
  1967. <published>2025-03-27T12:00:00-07:00</published>
  1968. <updated>2025-03-27T16:50:41-07:00</updated>
  1969. <category scheme='https://www.tbray.org/ongoing/What/' term='Arts/Music' />
  1970. <category scheme='https://www.tbray.org/ongoing/What/' term='Arts' />
  1971. <category scheme='https://www.tbray.org/ongoing/What/' term='Music' />
  1972. <category scheme='https://www.tbray.org/ongoing/What/' term='The World/Life Online' />
  1973. <category scheme='https://www.tbray.org/ongoing/What/' term='The World' />
  1974. <category scheme='https://www.tbray.org/ongoing/What/' term='Life Online' />
  1975. <summary type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>I’ve written a lot about ways of listening to music; in the current decade about     <a href='/ongoing/When/202x/2021/07/17/Music-Notes'>liking YouTube Music</a> but then about     <a href='/ongoing/When/202x/2024/03/10/Play-My-Music'>de-Googling</a>. What’s new is that I’m spending most of my time with     <a href='https://www.plex.tv/en-ca/plexamp/'>Plexamp</a> and     <a href='https://www.qobuz.com/'>Qobuz</a>. The trade-offs are complicated</div></summary>
  1976. <content type='xhtml'><div xmlns='http://www.w3.org/1999/xhtml'>
  1977.    <p>I’ve written a lot about ways of listening to music; in the current decade about
  1978.    <a href="/ongoing/When/202x/2021/07/17/Music-Notes">liking YouTube Music</a> but then about
  1979.    <a href="/ongoing/When/202x/2024/03/10/Play-My-Music">de-Googling</a>. What’s new is that I’m spending most of my time with
  1980.    <a href="https://www.plex.tv/en-ca/plexamp/">Plexamp</a> and
  1981.    <a href="https://www.qobuz.com/">Qobuz</a>. The trade-offs are complicated.</p>
  1982.    <h2 id='p-1'>YouTube Music</h2>
  1983.    <p>I liked YTM because:</p>
  1984.    <ol>
  1985.      <li><p>It let me upload my existing ten thousand tracks or so, which include many oddities that aren’t on streamers.</p></li>
  1986.      <li><p>It did a good job of discovering new artists for me.</p></li>
  1987.      <li><p>The Android Auto integration lets me say “Play Patti Smith” and it just does the right thing.</p></li>
  1988.    </ol>
  1989.    <p>But the artist discovery has more or less ran out of gas. I can’t remember the last time I heard something new that made me
  1990.    want more, and when I play “My Supermix”, it seems to always be the same couple of dozen songs, never anything good
  1991.    and new.</p>
  1992.    <p>Also: Bad at classical.</p>
  1993.    <p>I think I might keep on paying for YTM for the moment, because I really like to watch live concerts before I go to bed, and
  1994.    it seems like YTM subscribers never see any ads, which is worth something.</p>
  1995.    <img src="https://www.tbray.org/ongoing/When/202x/2025/03/27/Plexamp.png" alt="Plexamp" />
  1996.    <h2 id='p-2'>Plexamp</h2>
  1997.    <p>I wrote up what it does in that <a href="/ongoing/When/202x/2024/03/10/Play-My-Music">de-Googling</a> link. Tl;dr: Runs a
  1998.    server on a Mac Mini at home and lets me punch through to it from anywhere in the world.
  1999.    I’ve been
  2000.    listening to it a lot, especially in the car, since YTM got boring.</p>
  2001.    <p>My back inventory of songs contains many jewels from CDs that I bought and loved
  2002.    in like 1989 or 2001 and subsequently forgot all about, and what a thrill when one of them lights up my day.</p>
  2003.    <p>I still feel vaguely guilty that I’m not paying Plex anything, but on the other hand what I’m doing costs them peanuts.</p>
  2004.    <p>But, I still want to hear new stuff.</p>
  2005.    <img src="https://www.tbray.org/ongoing/When/202x/2025/03/27/Qobuz.png" alt="Qobuz" />
  2006.    <h2 id='p-4'>Qobuz</h2>
  2007.    <p>I vaguely knew it was out there among the streamers, but I got an intense hands-on demonstration recently while
  2008.    <a href="/ongoing/When/202x/2025/03/07/Totem-Tribe-Tower">shopping for new speakers</a>; Phil at audiofi pulled up all my
  2009.    good-sound demo tracks with a couple of taps each, in what was apparently CD quality. Which opened my eyes.</p>
  2010.    <p>What I like about Qobuz:</p>
  2011.    <ol>
  2012.      <li><p>It pays artists more per stream than any other service, by a wide margin.</p></li>
  2013.      <li><p>It seems to have as much music as anyone else.</p></li>
  2014.      <li><p>It’s album-oriented, and I appreciate artists curating their own music.</p></li>
  2015.      <li><p>Classical music is a first-class citizen.</p></li>
  2016.      <li><p>While it doesn’t have an algorithm that finds music it thinks I’ll like, it is actively curated and they highlight new
  2017.      music regularly, and pick a “record of the week”. This week’s, for example, is <cite>For Melancholy Brunettes (&amp; Sad
  2018.      Women)</cite> by <a href="https://japanesebreakfast.rocks">Japanese Breakfast</a>. It’s extremely sweet stuff, maybe a little
  2019.      too low-key for me, but I still enjoyed it. They’re coming to town, I might go.</p></li>
  2020.      <li><p>This isn’t the only weekly selection that I’ve enjoyed.  Qobuz gives evidence of being built by people who love
  2021.      music.</p></li>
  2022.    </ol>
  2023.    <p>What don’t I like about Qobuz? The Mac app is kinda dumb, I sometimes can’t figure out how to do what I want, and for the
  2024.    life of me I can’t get it to show a simple full-screen display about the current song. But the Android app works OK.</p>
  2025.    <p>As for Qobuz’s claim to offer “Hi-Res” (i.e. better than CD) sound, meh.  I’m not convinced that this is actually
  2026.    audible and if it in principle were, I suspect that either my ears or my stereo would be a more important limiting factor.</p>
  2027.    <h2 id='p-3'>Records!</h2>
  2028.    <p>Yep, I still occasionally drop the needle on the vinyl on the turntable, and don’t think I’ll ever stop.</p>
  2029.    <h2 id='p-5'>And a reminder</h2>
  2030.    <p>If you really want to support artists, buy concert tickets. That thrill isn’t gone at all.</p>
  2031. </div></content></entry>
  2032.  
  2033. </feed>
  2034.  

If you would like to create a banner that links to this page (i.e. this validation result), do the following:

  1. Download the "valid Atom 1.0" banner.

  2. Upload the image to your own server. (This step is important. Please do not link directly to the image on this server.)

  3. Add this HTML to your page (change the image src attribute if necessary):

If you would like to create a text link instead, here is the URL you can use:

http://www.feedvalidator.org/check.cgi?url=http%3A//www.tbray.org/ongoing/ongoing.atom

Copyright © 2002-9 Sam Ruby, Mark Pilgrim, Joseph Walton, and Phil Ringnalda