Making a Vote Forward checklist

In How and why to write letters to voters I discussed Vote Forward, my favorite way for those of us who aren’t in swing states to reach out to voters in swing states. The site works really well for adopting batches of voters, and downloading packets of form letters. As I close in on 1000 letters, though, I’m finding it isn’t great for tracking progress at scale. Here’s how my dashboard page looks.

With 50 bundles in play, many of which are farmed out to friends and neighbors who are helping with the project, it’s become cumbersome to keep track of which bundles are prepped (ready to mail) or not. Here is the checklist I needed to see.

VoteForward Dashboard Report

mmorg: 1-UNPREPPED
r23Pp: 2-UNPREPPED
v9Kbo: 3-UNPREPPED
wLMPw: 4-UNPREPPED
24L4o: 5-PREPPED
4nNnj: 6-PREPPED
5rQmV: 7-PREPPED
...
YV4dL: 48-PREPPED
zKjne: 49-PREPPED
ZrKJz: 50-PREPPED

If you’re in the same boat, here’s a piece of code you can use to make your own checklist. It’s gnarly, if you aren’t a programmer I advise you not even to look at it, just copy it, and then paste it into your browser to have it open a new window with your report.

Vote Forward checklist maker (expand to copy)
javascript:(function(){
  // First part: Adjust height of divs with inline styles
  document.querySelectorAll('div[style]').forEach(div => {
    let inlineStyle = div.getAttribute('style');
    if (inlineStyle.includes('position: relative')) {
      div.style.height = '20000px';  // Set the height to 20000px
    }
  });

  // Introduce a delay before processing the list of items
  setTimeout(() => {
    const items = document.querySelectorAll('li.bundle-list-item.individual');

    let dataList = [];

    // Iterate over the items to capture data-testid and ID
    items.forEach(item => {
        let dataTestId = item.getAttribute('data-testid');
        
        // Use the id attribute of the input element to extract the ID
        const toggleInput = item.querySelector('input.slide-out-toggle');
        const toggleId = toggleInput ? toggleInput.getAttribute('id') : '';
        
        // Extract the ID part from the toggleId pattern "toggle-24L4o-PREPPED"
        const id = toggleId ? toggleId.split('-')[1] : 'ID not found';

        // Remove "bundle-" and the number part from dataTestId, keeping only "PREPPED" or "UNPREPPED"
        dataTestId = dataTestId.split('-').pop();  // Extract only the "PREPPED" or "UNPREPPED" part

        // Push the data into the array
        dataList.push({ dataTestId, id });
    });

    // Sort first by whether it's PREPPED or UNPREPPED (descending for UNPREPPED first), 
    // then by the ID within each group
    dataList.sort((a, b) => {
        if (a.dataTestId.includes("PREPPED") && b.dataTestId.includes("UNPREPPED")) {
            return 1;  // UNPREPPED comes before PREPPED
        } else if (a.dataTestId.includes("UNPREPPED") && b.dataTestId.includes("PREPPED")) {
            return -1;
        }
        // Sort by ID if they belong to the same category
        return a.id.localeCompare(b.id);
    });

    // Prepare the output string
    let output = '';
    dataList.forEach((item, index) => {
        output += `${item.id}: ${index + 1}-${item.dataTestId}\n`;
    });

    // Open a new window with the output in a text area for easy copying
    let newWindow = window.open('', '', 'width=500,height=500');
    newWindow.document.write('<html><body><h2>VoteForward Dashboard Report</h2><pre>' + output + '</pre></body></html>');
    newWindow.document.close();
  }, 2000);  // Adjust delay as needed
})();

Here are instructions for Chrome/Edge, Safari, and Firefox. You might need to tell your browser to allow the popup window in which it writes the report.

Chrome/Edge:

  1. Open the VoteForward dashboard in your browser.
  2. Open the developer console:
    • Windows/Linux: Press Ctrl + Shift + J.
    • Mac: Press Cmd + Option + J.
  3. Paste the code into the console.
  4. Press Enter to run the code.

Firefox:

  1. Open the VoteForward dashboard in your browser.
  2. Open the developer console:
    • Windows/Linux: Press Ctrl + Shift + K.
    • Mac: Press Cmd + Option + K.
  3. Paste the code into the console.
  4. Press Enter to run the code.

Safari:

  1. Open the VoteForward dashboard in your browser.
  2. Enable the developer console (if it’s not already enabled):
    • Go to Safari > Preferences.
    • Click the Advanced tab.
    • Check “Show Develop menu in menu bar” at the bottom.
  3. Open the developer console:
    • Press Cmd + Option + C.
  4. Paste the code into the console.
  5. Press Enter to run the code.

It would be nice to have this as a built-in feature of the site but, as we come down to the wire, this may be a helpful workaround.

Thanks, again, to the Vote Forward team for all you do! It’s a great way to encourage voter turnout.

deo absente deum culpa

On a recent trip I saw this pair of Latin phrases tattooed on the back of a flight attendant’s arms:

Left: Deo absente. Right: Deum culpa.

I took Latin in middle school, and could guess what the combination might mean. It’s not a common construction, and a search seems to confirm my guess. Both Google and Bing take you to a couple of Reddit posts in r/Latin.

Would this be the correct translation?

A song I like, Deus in absentia by Ghost, has that line in it intending to mean “In the absence of God”, so I was looking into alternate translations/syntax of the phrase intending to mean “In the absence of God; Blame/Fault God”. Would this make sense: “Deum in absente; Culpa Deus” or “Deus Culpa”?

Does the phrase “Deus In Absentia, Deus Culpa” make sense?

I’m using this for a tattoo and want to be absolutely sure it works in the sense of ‘In the absence of God, blame God’. All help appreciated!

Is that the same person I saw? If so, the responses in r/Latin seem to have guided them to the final text inked on their arms. And if so, the message is essentially what I had guessed. The intent of the message, though, is open to interpretation. I’m not quite sure how to take it. What do you think it means? Would it have been rude to ask?

Revisiting the Elm City project

“Communities that want to build comprehensive public calendars will be able to do so using a hybrid approach that blends existing iCalendar feeds with feeds synthesized from web calendars. It’s not a perfect solution, but with LLM assistance it’s a workable one. And who knows, maybe if people see what’s possible when information silos converge, the common tools that can ease convergence will seem more attractive.” — An LLM-Turbocharged Community Calendar Reboot

Part of the LLM series at The New Stack.

Building a Steampipe Plugin — and Powerpipe Dashboards — for WordPress

“Users of the WordPress API may enjoy the abstraction — and standardization — that a SQL interface provides. If you need to query multiple WordPress sites, Steampipe’s connection aggregator will be really handy. And if you want to integrate data from WordPress with data from other APIs wrapped by other plugins in the Steampipe hub, performing literal SQL JOINs across disparate APIs is a heady experience.” — Building a Steampipe Plugin — and Powerpipe Dashboards — for WordPress

Part of the LLM series at The New Stack.

How LLMs Guide Us to a Happy Path for Configuration and Coding

“Some argue that by aggregating knowledge drawn from human experience, LLMs aren’t sources of creativity, as the moniker “generative” implies, but rather purveyors of mediocrity. Yes and no. There really are very few genuinely novel ideas and methods, and I don’t expect LLMs to produce them. Most creative acts, though, entail novel recombinations of known ideas and methods. Because LLMs radically boost our ability to do that, they are amplifiers of — not threats to — human creativity.” – How LLMs Guide Us to a Happy Path for Configuration and Coding

Part of the LLM series at The New Stack.

When not to LLM

Here’s the latest installment in the series on working with LLMS: https://thenewstack.io/choosing-when-to-use-or-not-use-llms-as-a-developer/

For certain things, the LLM is a clear win. If I’m looking at an invalid blob of JSON that won’t even parse, there’s no reason to avoid augmentation. My brain isn’t a fuzzy parser — I’m just not wired to see that kind of problem, and that isn’t likely to change with effort and practice. But if there are structural problems with code, I need to think about them before reaching for assistance.

The rest of the series:

1 When the rubber duck talks back

2 Radical just-in-time learning

3 Why LLM-assisted table transformation is a big deal

4 Using LLM-Assisted Coding to Write a Custom Template Function

5 Elevating the Conversation with LLM Assistants

6 How Large Language Models Assisted a Website Makeover

7 Should LLMs Write Marketing Copy?

8 Test-Driven Development with LLMs: Never Trust, Always Verify

9 Learning While Coding: How LLMs Teach You Implicitly

10 How LLMs Helped Me Build an ODBC Plugin for Steampipe

11 How to Use LLMs for Dynamic Documentation

12 Let’s talk: conversational software development

13 Using LLMs to Improve SQL Queries

14 Puzzling over the Postgres Query Planner with LLMs

15 7 Guiding Principles for Working with LLMs

16 Learn by Doing: How LLMs Should Reshape Education

17 How to Learn Unfamiliar Software Tools with ChatGPT

18 Creating a GPT Assistant That Writes Pipeline Tests

19 Using AI to Improve Bad Business Writing

20 Code in Context: How AI Can Help Improve Our Documentation

21 The Future of SQL: Conversational Hands-on Problem Solving

22 Pairing With AI: A Senior Developer’s Journey Building a Plugin

23 How LLMs Can Unite Analog Event Promotion and Digital Calendars

24 Using LLMs to Help Write a Postgres Function

25 Human Insight + LLM Grunt Work = Creative Publishing Solution

How and why to write letters to voters

If you don’t live in a swing state, but would like to do more than just send money to help encourage voter turnout in those places, what are your options? For me the best one is Vote Forward, which orchestrates letter-writing to registered voters. I sent hundreds of such letters in 2020 and am aiming to do lots more, with help from friends, this time around.

Even if I lived in a swing state, I’m not someone who’d be comfortable knocking on doors. And the last thing I want to do is pester people in those places with yet another unwanted phone call or text message. The Vote Forward method is perfect for me personally, and I also think it’s the most clever and sensible way to encourage voters in other states. Here’s how it works.

You “adopt” voters in batches of 5 or 20. I just adopted my first 100: 20 in each of Ohio, Pennsylvania, Michigan, New Hampshire, and North Carolina. You download each batch as a PDF that prints 21 pages. Page one has the instructions and the list of registered voters’ names and addresses

The fact that you write the letters (and address the envelopes) by hand is a great idea. We receive very few hand-addressed letters nowadays, I think they have a pretty good chance of being opened. And once opened, the hand-written message is again unusual. The fact that somebody made the effort to do that signals a rare kind of authenticity.

Likewise, I think the nonpartisan tone of the message is unusual and conveys authenticity. I wish voting were mandatory in the US, as it is in Australia and elsewhere. However the chips fall in November, I would like to know that the result truly reflects what everyone thinks. My message last time was something like:

“… because it’s not really a democracy unless everyone’s voice is heard.”

Pages 2-21 are the letter templates. They look like this:

The hardest part for me was the handwriting. I famously struggled with cursive writing in fifth grade. By the time I reached high school I had reverted to printing. Then, in college, I realized that cursive is more efficient and relearned how to do it. I had to relearn all over again in 2020 because cursive was the fastest way to write all those letters. And I’ll probably have to relearn again this time. I suspect many in younger generations never learned cursive at all, in which case writing the letters by hand will be even harder. So: keep the message short!

If you’ve received a link to this post directly from me, it’ll come with an invitation to drop by our house, hang out on the porch, and help me complete batches of these letters. Otherwise, I hope you might try this method yourself, and/or share it with others. In the past week I’ve switched from doomscrolling to hopescrolling and that’s a huge relief. But I also want to do something tangible (again, beyond donations) and this will be my focus. It feels good to do the work, and will feel really good when I visit the post office sometime in October and drop off a big stack of hand-addressed envelopes.

But is it effective? That’s another thing I like about Vote Forward. They’ve made a sincere effort to measure the impact. And they are honest about the findings: the measurable effect is small. I’ll give them the last word here.

Why should we get excited about small differences?

Because getting people who don’t vote to show up at the polls (or mail in a ballot) is actually pretty hard. Most of the factors that affect whether people vote are tied to big, structural issues (like voter ID laws or polling place accessibility) or deep-seated attitudes (e.g., a lack of faith that elections matter). Given these obstacles, boosting turnout by even a small amount is a real achievement! And, when it comes to politics, we know that many races are decided by tight margins, so a small boost in turnout can translate into a meaningful difference in electoral outcomes.

Seymour and Brownie

My family, on my dad’s side, were Jews from Poland and Ukraine. His parents came to America before the shit hit the fan, but I grew up knowing two people who weren’t so lucky. Seymour Mayer lived across the street during my teens. And Annie Braunschweig, who we knew as Brownie, had taken care of my sister and me as four- and five-year-old kids when our mom – unusually at that time – went back to work full-time teaching at a university. Both Seymour and Brownie were survivors of Nazi concentration camps, with tattooed numbers on their arms.

I never heard Seymour talk about it. Brownie rarely did, though I remember one story about a mother who tossed her swaddled baby to a stranger as the train was leaving to take her to the gas chambers.

Very few survivors remain. And there are not many of us who have known survivors. I’ve thought a lot, over the years, about what happens when that kind of personal connection ends, and living memories fall off the continental shelf into the deep ocean of history. I suspect the Holocaust may seem no more real, to many born in this century, than the Spanish Inquisition.

I don’t know if Seymour and Brownie ever read “It Can’t Happen Here” but I am pretty sure they’d have thought it absolutely can, they’d be even more horrified in this moment than many of us are, and they’d reject the fatalism that I see taking root among friends and acquaintances.

“It hasn’t happened yet,” they’d say, “you can still prevent it, do not despair prematurely, there is still time, but you must find a way to focus your efforts and unite all whose votes can matter.”

The things we carry

For a long time there were only two essential things that I carried everywhere: keys and wallet. Two was a manageable number of objects that I had to remember to put into pockets, and two was a manageable number of pockets to put them in.

Then my first phone bumped that number to three. When reading glasses became the fourth must-carry item, it started to feel like there were too many objects to always remember and too few pockets to put them in. When the seasons changed, or when traveling, it got harder to reset the canonical locations for all four things.

Although I listen to tons of podcasts, headphones never made the list of always-carry items. But when I emptied my pockets the other day I realized that my magic number is now five. AirPods are the new take-everywhere item.

For a while I resisted the recommendation to upgrade from a wired headset to AirPods. Did I really need another small, rechargeable, easy-to-lose object (actually, three of them)? I’ve learned not to expect that yet another electronic gadget will improve my life. But this one has. Dave Winer, you were right.

Obviously this trend can’t continue indefinitely. Will that thing we anachronistically call a “phone” absorb the wallet, and maybe even the keys? I’m not sure how I feel about that!

Meanwhile, there’s my trusty belt pack. It’s dorky but there’s a pocket for everything, and it works consistently across seasons and continents.

Human Insight + LLM Grunt Work = Creative Publishing Solution

Here’s the latest installment in the series on working with LLMS: https://thenewstack.io/human-insight-llm-grunt-work-creative-publishing-solution/

Although streamlined publishing of screenshots is nice, the biggest win comes from reviewing and revising in Google Docs; which, for better and worse, has become the defacto collaboration standard for many of us.

I am ridiculously pleased with this solution.

The rest of the series:

1 When the rubber duck talks back

2 Radical just-in-time learning

3 Why LLM-assisted table transformation is a big deal

4 Using LLM-Assisted Coding to Write a Custom Template Function

5 Elevating the Conversation with LLM Assistants

6 How Large Language Models Assisted a Website Makeover

7 Should LLMs Write Marketing Copy?

8 Test-Driven Development with LLMs: Never Trust, Always Verify

9 Learning While Coding: How LLMs Teach You Implicitly

10 How LLMs Helped Me Build an ODBC Plugin for Steampipe

11 How to Use LLMs for Dynamic Documentation

12 Let’s talk: conversational software development

13 Using LLMs to Improve SQL Queries

14 Puzzling over the Postgres Query Planner with LLMs

15 7 Guiding Principles for Working with LLMs

16 Learn by Doing: How LLMs Should Reshape Education

17 How to Learn Unfamiliar Software Tools with ChatGPT

18 Creating a GPT Assistant That Writes Pipeline Tests

19 Using AI to Improve Bad Business Writing

20 Code in Context: How AI Can Help Improve Our Documentation

21 The Future of SQL: Conversational Hands-on Problem Solving

22 Pairing With AI: A Senior Developer’s Journey Building a Plugin

23 How LLMs Can Unite Analog Event Promotion and Digital Calendars

24 Using LLMs to Help Write a Postgres Function

Pairing with ChatGPT to help write a Postgres function

Here’s the latest installment in the series on working with LLMS: https://thenewstack.io/techniques-for-using-llms-to-help-write-a-postgres-function/

It was only after I deployed the function and used it in three different dashboards that the penny finally dropped. This had begun as an exercise to wrap a SQL idiom that made use of the lag() function. But when I looked at the final version of the function, I realized it wasn’t using lag(). Nor was it using dense_rank(). Just row_number() with partition logic was sufficient. Why, I asked ChatGPT, wasn’t that initially obvious?

ChatGPT: The final solution using ROW_NUMBER() and partition logic was not immediately apparent due to a combination of reliance on familiar patterns, the evolving understanding of requirements, and the iterative nature of problem-solving. This process highlights the importance of flexibility and openness to re-evaluating initial approaches to find the simplest and most effective solution.

It’s a good answer that synthesizes wisdom drawn from the human minds represented in the corpus of SQL queries and related conversations that ChatGPT feeds on.

The rest of the series:

1 When the rubber duck talks back

2 Radical just-in-time learning

3 Why LLM-assisted table transformation is a big deal

4 Using LLM-Assisted Coding to Write a Custom Template Function

5 Elevating the Conversation with LLM Assistants

6 How Large Language Models Assisted a Website Makeover

7 Should LLMs Write Marketing Copy?

8 Test-Driven Development with LLMs: Never Trust, Always Verify

9 Learning While Coding: How LLMs Teach You Implicitly

10 How LLMs Helped Me Build an ODBC Plugin for Steampipe

11 How to Use LLMs for Dynamic Documentation

12 Let’s talk: conversational software development

13 Using LLMs to Improve SQL Queries

14 Puzzling over the Postgres Query Planner with LLMs

15 7 Guiding Principles for Working with LLMs

16 Learn by Doing: How LLMs Should Reshape Education

17 How to Learn Unfamiliar Software Tools with ChatGPT

18 Using AI to Improve Bad Business Writing

19 Code in Context: How AI Can Help Improve Our Documentation

20 The Future of SQL: Conversational Hands-on Problem Solving

21 Pairing With AI: A Senior Developer’s Journey Building a Plugin

22 How LLMs Can Unite Analog Event Promotion and Digital Calendars

The future of SQL: conversational hands-on problem solving

Here’s the latest installment in the series on working with LLMS: https://thenewstack.io/the-future-of-sql-conversational-hands-on-problem-solving/

I keep returning to the theme of choral explanations (#4 on my list of best practices), and it’s especially relevant in the SQL domain where there are just so many ways to write a query.

Exploring the range of possibilities used to be arduous, time-consuming and hard to justify. Now it’s becoming hard to justify not doing that; optimizations (sometimes major ones) can and do emerge.

The rest of the series:

1 When the rubber duck talks back

2 Radical just-in-time learning

3 Why LLM-assisted table transformation is a big deal

4 Using LLM-Assisted Coding to Write a Custom Template Function

5 Elevating the Conversation with LLM Assistants

6 How Large Language Models Assisted a Website Makeover

7 Should LLMs Write Marketing Copy?

8 Test-Driven Development with LLMs: Never Trust, Always Verify

9 Learning While Coding: How LLMs Teach You Implicitly

10 How LLMs Helped Me Build an ODBC Plugin for Steampipe

11 How to Use LLMs for Dynamic Documentation

12 Let’s talk: conversational software development

13 Using LLMs to Improve SQL Queries

14 Puzzling over the Postgres Query Planner with LLMs

15 7 Guiding Principles for Working with LLMs

16 Learn by Doing: How LLMs Should Reshape Education

17 How to Learn Unfamiliar Software Tools with ChatGPT

18 Using AI to Improve Bad Business Writing

19 Code in Context: How AI Can Help Improve Our Documentation

Code in Context: How AI Can Help Improve Our Documentation

Here’s the latest installment in the series on working with LLMS: https://thenewstack.io/code-in-context-how-ai-can-help-improve-our-documentation/.

Writing documentation from scratch is as uncommon as writing code from scratch. More typically, you’re updating or expanding or refactoring existing docs. My expectation was that an LLM-powered tool primed with both code and documentation could provide a powerful assist, and Unblocked did.

I don’t know how to measure the boost it gave me. But I do know that I’ll never again want to undertake this kind of project without a tool that can help me assemble the necessary context.


The rest of the series:

1 When the rubber duck talks back

2 Radical just-in-time learning

3 Why LLM-assisted table transformation is a big deal

4 Using LLM-Assisted Coding to Write a Custom Template Function

5 Elevating the Conversation with LLM Assistants

6 How Large Language Models Assisted a Website Makeover

7 Should LLMs Write Marketing Copy?

8 Test-Driven Development with LLMs: Never Trust, Always Verify

9 Learning While Coding: How LLMs Teach You Implicitly

10 How LLMs Helped Me Build an ODBC Plugin for Steampipe

11 How to Use LLMs for Dynamic Documentation

12 Let’s talk: conversational software development

13 Using LLMs to Improve SQL Queries

14 Puzzling over the Postgres Query Planner with LLMs

15 7 Guiding Principles for Working with LLMs

16 Learn by Doing: How LLMs Should Reshape Education

17 How to Learn Unfamiliar Software Tools with ChatGPT

18 Using AI to Improve Bad Business Writing

Creating a GPT Assistant That Writes Pipeline Tests

Here’s the latest installment in the series on working with LLMS: Creating a GPT Assistant That Writes Pipeline Tests.

Once you get the hang of writing these tests, it’s mostly boilerplate, so I figured my team of assistants could help. I recruited Cody, GitHub Copilot, and Unblocked — with varying degrees of success. Then I realized I hadn’t yet tried creating a GPT. As OpenAI describes them, “GPTs are custom versions of ChatGPT that users can tailor for specific tasks or topics by combining instructions, knowledge, and capabilities.”


The rest of the series:

1 When the rubber duck talks back

2 Radical just-in-time learning

3 Why LLM-assisted table transformation is a big deal

4 Using LLM-Assisted Coding to Write a Custom Template Function

5 Elevating the Conversation with LLM Assistants

6 How Large Language Models Assisted a Website Makeover

7 Should LLMs Write Marketing Copy?

8 Test-Driven Development with LLMs: Never Trust, Always Verify

9 Learning While Coding: How LLMs Teach You Implicitly

10 How LLMs Helped Me Build an ODBC Plugin for Steampipe

11 How to Use LLMs for Dynamic Documentation

12 Let’s talk: conversational software development

13 Using LLMs to Improve SQL Queries

14 Puzzling over the Postgres Query Planner with LLMs

15 7 Guiding Principles for Working with LLMs

16 Learn by Doing: How LLMs Should Reshape Education

17 How to Learn Unfamiliar Software Tools with ChatGPT

How to Learn Unfamiliar Software Tools with ChatGPT

Here’s the latest installment in the series on working with LLMS: How to Learn Unfamiliar Software Tools with ChatGPT.

Ideally, tools like GeoGebra and Metabase provide interfaces so intuitive that you rarely need to read the docs, and you can learn the software just by poking around in it. In reality, of course, we need those docs — and they still need to be excellent. But now, we’ll extract a new benefit from them. When we can partner with machines that have read the docs, and can look over our shoulders as we try to do the things described in the docs, we’ll turbocharge our ability to dive into unfamiliar software tools and quickly learn how to use them.


The rest of the series:

1 When the rubber duck talks back

2 Radical just-in-time learning

3 Why LLM-assisted table transformation is a big deal

4 Using LLM-Assisted Coding to Write a Custom Template Function

5 Elevating the Conversation with LLM Assistants

6 How Large Language Models Assisted a Website Makeover

7 Should LLMs Write Marketing Copy?

8 Test-Driven Development with LLMs: Never Trust, Always Verify

9 Learning While Coding: How LLMs Teach You Implicitly

10 How LLMs Helped Me Build an ODBC Plugin for Steampipe

11 How to Use LLMs for Dynamic Documentation

12 Let’s talk: conversational software development

13 Using LLMs to Improve SQL Queries

14 Puzzling over the Postgres Query Planner with LLMs

15 7 Guiding Principles for Working with LLMs

16 Learn by Doing: How LLMs Should Reshape Education

You say feature, I say bug: the enshittification of Microsoft Paint

I’ve happily used MS Paint as my basic bitmap editor since Windows 3, almost 25 years ago. Mostly I’ve used it to create images from screenshots, but that has suddenly become way harder. Formerly, when I’d cut a region, the now-empty region would display using the default white background. Now it displays a checkered background like so.

Here is the procedure to refill the white background:

  1. Switch the foreground color to white
  2. Use the Fill tool to fill the checkered region
  3. Then switch the foreground back to black.

ARE YOU KIDDING ME?

Nope. It’s evidently an unintended consequence of a pair of new feature: layers and transparency.

To get started, click on the new Layers button in the toolbar, which will open a panel on the side of the canvas.”

Microsoft also revealed today that an upcoming Paint feature is support for image transparency, which will add the ability to open and save transparent PNG files.

During editing, users will notice a prominent checkerboard pattern displayed on the canvas, serving as a visual indicator and highlighting the transparent regions within the image.

This ensures that when content is erased from the canvas, it is completely removed, eliminating the need to cover unwanted regions of an image with white fill.

bleepingcomputer.com

I never asked for these “long-awaited” new features, Paint is (or was) useful to me precisely because it only does the kind of basic bitmap editing I need when compositing screenshots. But I can opt out, right?

Nope.

ARE YOU KIDDING ME?

Nope.

This feature (layers and image transparency) seems to be introduced in September 2023 and doesn’t actually allow to be turned off.

Doing what vengy proposes for each and every image being edited is a natural madness and will drive even the most sane person crazy.

What worked for me was to uninstall Paint and replace it with a classic version:

  1. Uninstalling can be done by simply right-clicking Paint icon in Start Menu and selecting Uninstall from context menu.
  2. Classic Paint can be get from here or here.

  3. Download and install it.

  4. Go to Settings → Apps → Apps & Features → More settings → App execution aliases.

  5. Toggle the switch to Off for mspaint.exe and pbrush.exe items.

superuser.com

Evidently people are willing to hack their systems in order to revert to a now-unsupported version that they prefer. As insane as it would be, I’m considering whether to become one of those people. Sigh. I guess 25 years was a pretty good run.

Learn by Doing: How LLMs Should Reshape Education

Here’s the latest installment in the series on working with LLMS: Learn by Doing: How LLMs Should Reshape Education.

If you’re teaching SQL, this article points to a pedagogical challenge/opportunity: How would I create a lesson that guides a student to an understanding of CROSS JOIN without ever mentioning or explicitly teaching anything about it?

If you’re teaching anything else, the same question could (I’ll argue should) apply. How to scaffold learning by doing?


The rest of the series:

1 When the rubber duck talks back

2 Radical just-in-time learning

3 Why LLM-assisted table transformation is a big deal

4 Using LLM-Assisted Coding to Write a Custom Template Function

5 Elevating the Conversation with LLM Assistants

6 How Large Language Models Assisted a Website Makeover

7 Should LLMs Write Marketing Copy?

8 Test-Driven Development with LLMs: Never Trust, Always Verify

9 Learning While Coding: How LLMs Teach You Implicitly

10 How LLMs Helped Me Build an ODBC Plugin for Steampipe

11 How to Use LLMs for Dynamic Documentation

12 Let’s talk: conversational software development

13 Using LLMs to Improve SQL Queries

14 Puzzling over the Postgres Query Planner with LLMs

15 7 Guiding Principles for Working with LLMs

7 Guiding Principles for Working with LLMs

Here’s the latest installment in the series on working with LLMS: 7 Guiding Principles for Working with LLMs.


The rest of the series:

1 When the rubber duck talks back

2 Radical just-in-time learning

3 Why LLM-assisted table transformation is a big deal

4 Using LLM-Assisted Coding to Write a Custom Template Function

5 Elevating the Conversation with LLM Assistants

6 How Large Language Models Assisted a Website Makeover

7 Should LLMs Write Marketing Copy?

8 Test-Driven Development with LLMs: Never Trust, Always Verify

9 Learning While Coding: How LLMs Teach You Implicitly

10 How LLMs Helped Me Build an ODBC Plugin for Steampipe

11 How to Use LLMs for Dynamic Documentation

12 Let’s talk: conversational software development

13 Using LLMs to Improve SQL Queries

14 Puzzling over the Postgres Query Planner with LLMs

Watch your hands

I’m lucky to have two hands, let’s be clear, and the minor struggles I’ve had with them over the years don’t qualify as any kind of real hardship. Yet there have been a lot of small injuries — an ongoing annoyance made worse by being mostly my fault.

Consider the most recent incident. To relieve strain on my left hand, I switched a few months ago from a steel-string to a nylon-string guitar. I knew I wanted the lesser force required to press nylon strings, and the vacation from steel strings has really helped. The wider spacing between the strings is also better for my hands, I realized as I settled in. I’d started on a classical guitar, then hadn’t owned one in decades, it feels good to have one again and I’ve been playing it a lot.

Being the guy who wrote a blog post about an early warning system for RSI not even six months ago, I see the absurdity of my situation. Back in July I was rehabbing an overextended little finger. Now I’m rehabbing a thumb and related muscles insulted by my failure to properly adapt to the new instrument.

You can wrap your thumb around the narrower neck of a steel-string guitar in order to grab the lowest string. You can do that with the wider neck of classical guitar too. But as I probably learned the first time and then forgot, you really shouldn’t. A D major chord with F# in the bass is too much of a stretch for the thumb, at least for my thumb, on a classical guitar. You won’t see classical guitarists do that. Instead they’ll make a tripod with the index, middle, and ring fingers.

So once again I get to rewire my hand posture. Which, again, is a minor hardship, not remotely comparable to the guy I mentioned last time who had to switch sides and learn to fret with his right hand. As I also mentioned there, he found an upside. Now he’s a switch-hitter who can use both halves of his brain directly. In my case, I’m trying to embrace the rewiring as a way to break a habit and form new neural pathways. It’d be nice, though, if that weren’t always a response to self-inflicted injury!

But like I said, it’s a minor hardship. My hands could have been mangled in my dad’s car engine that one time, or in the anchor chain of Ben Smith’s boat that other time: two escapes from disaster that still provoke the occasional nightmare. I’m lucky to have these two hands, and again vow to take better care of them.

Why is it so hard (for me, at least) to detect and avoid injurious hand postures? I guess it’s because whatever you’re projecting — when you write sentences or lines of code, or play notes and chords — has to flow through your hands with minimal conscious attention to your hands. Note to self: pay more attention.

Critical mass in the Goldilocks zone

The use of the phrase “critical mass” in this NYTimes story about the enshittification of Goodreads stopped me in my tracks.

Give all of Goodreads’s issues, it might seem easy enough to encourage writers and readers simply to flock to another forum. Sites like The Storygraph and Italic Type have sprung up as promising alternatives, but they’re still far from reaching a critical mass of users.

Nuclear physicists know they are dancing with the devil when they bring fissile material to criticality. They also know that the reaction can be controlled, that it must be, and that the means of control obey well-understood principles.

Social sites typically push toward supercriticality with no such understanding. If Goodreads enshittifies at 125 million users, why would another service expect a different outcome at similar scale?

We can learn from a natural experiment. Not mentioned in the story is a long-running service, LibraryThing, that’s been going strong since 2005. I interviewed its founder and lead developer, Tim Spalding, back in 2008. Listening to that interview again today reminded me that everything I loved about LibraryThing remains important and matters even more now.

LibraryThing was, and remains, a place where you make and share lists of books in order to connect with other people and with books — not primarily via friend relationships but rather book relationships. It’s a small business that’s kept Tim and his crew happily engaged in serving a few million bibliophiles, some of whom pay a membership fee to be super-cataloguers.

I’m not in LibraryThing’s core demographic. Books aren’t as central to my life as they are to members of the service who carefully curate their own lists, tag books and authors, contribute to a common knowledge wiki, and write reviews. But I appreciate their work when I visit the site.

Today I added Ed Yong’s remarkable An Immense World to my list. Among the book’s dozens of reviews on the site, I found a 2000-word essay that usefully highlights many of the strange (to humans) powers of animal perception that Yong describes.

I guess LibraryThing isn’t on the Times’ radar because it hasn’t reached a critical mass of … what, exactly? Tens of millions of people? Hundreds of millions? I’m glad it hasn’t! That’s a recipe for meltdown. LibraryThing has been going strong, for almost two decades, in the Goldilocks zone: neither too little activity nor too much, just the right amount for meaningful experiences at human scale.

I feel the same way about Mastodon. Conventional wisdom says it’s dead in the water: “nobody” goes there, no Mastodon apps rank highly in the app stores. But if critical mass means operating at the scale of Twitter or Facebook, then who wants that? Who benefits from the inevitable enshittification? Not me, and probably not you.

LibraryThing shows that a controlled reaction, at smaller scale, is sustainable over time. Mastodon so far has been successful in the same way, and I see no reason why that can’t continue. Although Mastodon is young, my connections there date back to social networking’s roots in the early blogosphere. It feels like the right amount of critical mass. For me, a billion people on Mastodon is an anti-goal. I would much rather see hundreds or maybe thousands of healthy communities emerge, each operating in its own Goldilocks zone. Many small and safe critical masses, instead of a few huge and dangerous ones, powering small businesses whose proprietors are — like Tim Spalding and his crew — able to maintain real relationships with their customers.

That global conversation we thought we were having on Twitter? We don’t know how to control that reaction and I’m not sure it makes sense to try.

Don’t look ahead. Look sideways as you climb the hill.

I do a lot more cycling in Sonoma County, California than was possible in Cheshire County, New Hampshire. The Mediterranean climate here, which enables me to ride year-round, is a blessing for my mental and physical well-being. And because the topography is even more rugged, I’m doing more climbing that ever.

Yesterday, Luann dropped me at the Coleman Overlook on the coast and I cycled home from there. I’m not a fast climber, I can’t keep up with younger friends when we cycle together, and my rides aren’t extreme by local standards. But my cumulative elevation gain over the course of a year far exceeds what it ever was back east, and I’ve had plenty of time to reflect on climbing strategy.

A better gear ratio would help, but my older road bike won’t accommodate that. So on the steepest pitches I switch to a weaving ascent that eases the grade, which I’ve decided is OK. For a while I resisted shoes with cleats that lock into pedals, but now I use them to gain extra leverage which really helps.

It’s never mainly about the equipment, though, the real challenge is always mental. How do you think about reaching the top of the big hill you’re climbing? One piece of conventional wisdom: don’t look ahead. If you look down at the road you aren’t forced to think about the grade, or your slow progress up it. Instead you see pavement moving beneath you, and feel steady progress.

Of course that defeats the purpose of cycling through spectacular Sonoma County landscapes. Recently a friend suggested a different strategy: look to the side. Of course! There’s little or no traffic on many of these routes, so it’s safe to do that. And the effect is mesmerizing.

I’ve described it like this:

Everything looks different from everywhere. You’re always seeing multiple overlapping planes receding into the distance, like dioramas. And they change dramatically as you move around even slightly. Even just ten paces in any direction, or a slight change in elevation, can alter the sightlines completely and reveal or hide a distant landmark.

So, don’t look ahead to the top of the hill, and don’t look down at the road. Look left and right to see sliding panels of majestic scenery. It really helps!

Puzzling over the Postgres query planner with LLMs

Here’s the latest installment in the series on LLM-assisted coding over at The New Stack: Puzzling over the Postgres Query Planner with LLMs.


The rest of the series:

1 When the rubber duck talks back

2 Radical just-in-time learning

3 Why LLM-assisted table transformation is a big deal

4 Using LLM-Assisted Coding to Write a Custom Template Function

5 Elevating the Conversation with LLM Assistants

6 How Large Language Models Assisted a Website Makeover

7 Should LLMs Write Marketing Copy?

8 Test-Driven Development with LLMs: Never Trust, Always Verify

9 Learning While Coding: How LLMs Teach You Implicitly

10 How LLMs Helped Me Build an ODBC Plugin for Steampipe

11 How to Use LLMs for Dynamic Documentation

12 Let’s talk: conversational software development

13 Using LLMs to Improve SQL Queries

Debugging SQL with LLMS

Here’s the latest installment in the series on LLM-assisted coding over at The New Stack: Techniques for Using LLMs to Improve SQL Queries.

The join was failing because the two network_interfaces columns contained JSONB objects with differing shapes; Postgres’ JSONB containment operator, @>, couldn’t match them. Since the JSONB objects are arrays, and since the desired match was a key/value pair common to both arrays, it made sense to explode the array and iterate through its elements looking to match that key/value pair.

Initial solutions from ChatGPT, Copilot Chat, and newcomer Unblocked implemented that strategy using various flavors of cross joins involving Postgres’ jsonb_array_elements function.


The rest of the series:

1 When the rubber duck talks back

2 Radical just-in-time learning

3 Why LLM-assisted table transformation is a big deal

4 Using LLM-Assisted Coding to Write a Custom Template Function

5 Elevating the Conversation with LLM Assistants

6 How Large Language Models Assisted a Website Makeover

7 Should LLMs Write Marketing Copy?

8 Test-Driven Development with LLMs: Never Trust, Always Verify

9 Learning While Coding: How LLMs Teach You Implicitly

10 How LLMs Helped Me Build an ODBC Plugin for Steampipe

11 How to Use LLMs for Dynamic Documentation

12 Let’s talk: conversational software development

Let’s Talk: Conversational Software Development

Here’s number 12 in the series on LLM-assisted coding over at The New Stack: Let’s Talk: Conversational Software Development

I keep coming back to the theme of the first article in this series: When the rubber duck talks back. Thinking out loud always helps. Ideally, you get to do that with a human partner. A rubber duck, though a poor substitute, is far better than nothing.

Conversing with LLMs isn’t like either of these options, it’s something else entirely; and we’re all in the midst of figuring out how it can work. Asking an LLM to write code, and having it magically appear? That’s an obvious life-changer. Talking with an LLM about the code you’re partnering with it to write? I think that’s a less obvious but equally profound life-changer.


The rest of the series:

1 When the rubber duck talks back

2 Radical just-in-time learning

3 Why LLM-assisted table transformation is a big deal

4 Using LLM-Assisted Coding to Write a Custom Template Function

5 Elevating the Conversation with LLM Assistants

6 How Large Language Models Assisted a Website Makeover

7 Should LLMs Write Marketing Copy?

8 Test-Driven Development with LLMs: Never Trust, Always Verify

9 Learning While Coding: How LLMs Teach You Implicitly

10 How LLMs Helped Me Build an ODBC Plugin for Steampipe

11 How to Use LLMs for Dynamic Documentation

How to Use LLMs for Dynamic Documentation

Here’s #11 in the new series on LLM-assisted coding over at The New Stack:
How to Use LLMs for Dynamic Documentation

My hunch is that we’re about to see a fascinating new twist on the old idea of literate programming. Some explanations can, will, and should be written by code authors alone, or by those authors in partnership with LLMs. Others can, will, and should be conjured dynamically by code readers who ask LLMs for explanations on the fly.


The rest of the series:

1 When the rubber duck talks back

2 Radical just-in-time learning

3 Why LLM-assisted table transformation is a big deal

4 Using LLM-Assisted Coding to Write a Custom Template Function

5 Elevating the Conversation with LLM Assistants

6 How Large Language Models Assisted a Website Makeover

7 Should LLMs Write Marketing Copy?

8 Test-Driven Development with LLMs: Never Trust, Always Verify

9 Learning While Coding: How LLMs Teach You Implicitly

10 How LLMs Helped Me Build an ODBC Plugin for Steampipe

How LLMs teach you things you didn’t know you didn’t know

Here’s #9 in the new series on LLM-assisted coding over at The New Stack:
Learning While Coding: How LLMs Teach You Implicitly

LLMs can deliver just-in-time knowledge tailored to real programming tasks; it’s a great way to learn about coding idioms and libraries.

As I mentioned on Mastodon, I know we are in a hype cycle, and I’m trying to report these findings in a quiet and matter-of-fact way. But when Greg Lloyd played this quote back to me, I got excited all over again.

This is the kind of tacit knowledge transfer that can happen when you work with another person, you don’t explicitly ask a question, and your partner doesn’t explicitly answer it. The knowledge just surfaces organically, and transfers by osmosis.

I’m certain this augmented way of learning will carry forward in some form, and improve the learning experience in other domains too.


1 When the rubber duck talks back

2 Radical just-in-time learning

3 Why LLM-assisted table transformation is a big deal

4 Using LLM-Assisted Coding to Write a Custom Template Function

5 Elevating the Conversation with LLM Assistants

6 How Large Language Models Assisted a Website Makeover

7 Should LLMs Write Marketing Copy?

8 Test-Driven Development with LLMs: Never Trust, Always Verify

Is there an early warning system for RSI?

My RSI (repetitive strain injury) struggles began 25 years ago, after an intensive push to build and ship the BYTE magazine website. The tendons in both wrists became badly inflamed, and I spent a couple of months in rehab: anti-inflammatory meds, alternating heat and ice, stretching. It mostly resolved, but my left thumb joint remained painful. One day, as I wondered what could possibly be the cause, I looked down at my hands as I was typing. I use the world’s best (and rarest) split keyboard so there’s a left spacebar and a right spacebar. Suddenly it was obvious. I was always hitting the left spacebar with my left thumb, an unconscious habit that was repeated hundreds or thousands of times a day. And I was really slamming it too, another habit that I still have to monitor. Thus began one of a series of interventions to remap the relationship between fingers and keys. In that case, I assigned my right thumb to the spacebar, intending to switch to an alternating pattern once things settled down. All these years later, I look down at my hands now and see that never happened. I’m still using the right spacebar exclusively. I should probably try to change that, but there’s a more pressing problem.

Over the years, I got bitten a few more times by the effects of asymmetry. When my left hand became painful again, I realized I was mousing exclusively with that hand, and switched the mouse to my right side. I think I’ve gone back and forth a few times, currently it’s again on the right.

Another time, when I was doing a lot of lap swimming, my right shoulder became painful. Once again, it was something that should have been obvious, but wasn’t to the medical people I consulted, and wasn’t to me either until, once again, I recognized another asymmetry: I was always breathing on the left side, which put extra strain on the right shoulder. When I switched to an alternating pattern, breathing every third stroke instead of every second, that problem resolved.

You’d think I’d have learned my lesson by now. But when the knuckle of my left pinky suddenly became inflamed two months ago, it was the same story all over again. I attributed it to playing more guitar than usual, but when laying off didn’t help I thought I might have triggered arthritis. An x-ray was negative, though. What could it possibly be?

Then last night, while typing, I felt a twinge and looked down at my hands. It was blindingly obvious: I use emacs key mappings; the CTRL key is part of many of the basic chords; my poor left pinky is overloaded. Amping up the guitar playing probably pushed me over the edge, but it seems clear that is the root cause.

So I’m typing this post in order to adjust to yet another remapping. On this keyboard, there’s also a right CTRL key but it’s not convenient to my right pinky, so I’ve recruited the right SHIFT key (which I apparently never use) to be my new CTRL key. It’s not going to be an easy adjustment, but I won’t complain, I’m just glad to know I’ve found the way forward.

Given these experiences, I’ve thought a lot about how we can unconsciously injure ourselves with repetitive and asymmetric patterns of movement. In my case, I don’t seem to receive any signals until damage is already done. I wish I could notice sooner, do the necessary remapping, and continue with less disruption. But it just doesn’t seem to work that way.

I really can’t complain, though. Recently I met a guy in a guitar shop whose left wrist and hand became so painful that he had to switch sides and learn to fret with his right hand. It’s hard for me to conceive of doing that kind of remapping, but you do what you have to do. And as a bonus, he’s now a switch-hitter: as he recovers some use of his left hand, he finds that he can achieve different effects as a right-handed and left-handed player.

I’m pretty sure I’ll get through this episode. The question will then become: how to avoid the next one? When we use computer keyboards or musical instruments, we need our hands to work unconsciously and automatically. It’s only when injuries happen that we have to surface what’s been unconscious, enter manual mode, and retrain until we can form new unconscious habits. I wish there were an early warning system.

A new series on LLM-assisted coding

In the 20th episode of my Mastodon series I pivoted to a new topic: LLM-assisted coding. After three posts in the new series, it got picked up by The New Stack. Here’s the full list so far, I’ll update it here as the series continues there.

1 When the rubber duck talks back

2 Radical just-in-time learning

3 Why LLM-assisted table transformation is a big deal

4 Using LLM-Assisted Coding to Write a Custom Template Function

5 Elevating the Conversation with LLM Assistants

6 How Large Language Models Assisted a Website Makeover

7 Should LLMs Write Marketing Copy?

8 Test-Driven Development with LLMs: Never Trust, Always Verify

Although I’ve spent decades working with software, and still regularly write code in one form or another, I’m only an average programmer. There’s no doubt that LLM assistants can help me be better. But how much better? In what ways exactly? That’s what I aim to find out. My day job embeds me in a fast-moving open-source project, Steampipe, to which I want to contribute as much as I can. That ambition was, until recently, tempered by my own limitations. Now, augmented by the collective knowledge embodied in LLM assistants, I’m raising my sights. Larry Wall famously said: “Easy things should be easy, and hard things should be possible.” It’s starting to look like even hard things can be easy. But the devil’s in the details, so in this series I’ll focus on concrete examples of how LLM assistants do (and don’t) help me become a better developer.