惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Spread Privacy
Spread Privacy
K
Kaspersky official blog
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Forbes - Security
Forbes - Security
Hacker News - Newest:
Hacker News - Newest: "LLM"
The Last Watchdog
The Last Watchdog
SecWiki News
SecWiki News
Attack and Defense Labs
Attack and Defense Labs
Google DeepMind News
Google DeepMind News
Security Archives - TechRepublic
Security Archives - TechRepublic
S
Secure Thoughts
WordPress大学
WordPress大学
Microsoft Security Blog
Microsoft Security Blog
P
Proofpoint News Feed
云风的 BLOG
云风的 BLOG
V
Visual Studio Blog
Security Latest
Security Latest
TaoSecurity Blog
TaoSecurity Blog
Cyberwarzone
Cyberwarzone
S
SegmentFault 最新的问题
Cloudbric
Cloudbric
aimingoo的专栏
aimingoo的专栏
S
Schneier on Security
N
Netflix TechBlog - Medium
MyScale Blog
MyScale Blog
T
The Blog of Author Tim Ferriss
H
Hacker News: Front Page
C
Cybersecurity and Infrastructure Security Agency CISA
小众软件
小众软件
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
AWS News Blog
AWS News Blog
AI
AI
G
GRAHAM CLULEY
IT之家
IT之家
P
Privacy & Cybersecurity Law Blog
L
Lohrmann on Cybersecurity
Last Week in AI
Last Week in AI
D
Docker
Recent Announcements
Recent Announcements
O
OpenAI News
T
Threat Research - Cisco Blogs
GbyAI
GbyAI
S
Security @ Cisco Blogs
T
Troy Hunt's Blog
C
Check Point Blog
博客园 - 三生石上(FineUI控件)
A
About on SuperTechFans
The Cloudflare Blog
阮一峰的网络日志
阮一峰的网络日志
N
News and Events Feed by Topic

Ben Hoyt's technical writing

Every dependency you add is a supply chain attack waiting to happen Don't fear Python subprocess or Go codegen Go performance from version 1.0 to 1.22 The One Billion Row Challenge in Go: from 1m45s to 3.4s in nine solutions Switching from S3 to Tigris on Fly.io Discussing Forth, C, CGI, Python, Go, and AWK on "Stray Pointers" "Stray Pointers" interview Using a Markov chain to generate readable nonsense with 20 lines of Python How (not) to apply for a software job The AWK book's 60-line version of Make Using the WordStar diamond in 2023 Name before type: why 'age int' is better than 'int age' The proposal to enhance Go's HTTP router Scripting with Go: a 400-line Git client that can create a repo and push itself to GitHub Names should be as short as possible while still being clear Lookup Tables (Forth Dimensions XIX.3) For Python packages, file structure != API Designing Pythonic library APIs From Go on EC2 to Fly.io: +fun, −$9/mo Code coverage for your AWK programs I/O is no longer the bottleneck microPledge: our startup that (we wish) competed with Kickstarter Rob Pike's simple C regex matcher in Go Tools I use to build my website Modernizing AWK, a 45-year old language, by adding CSV support Prig: like AWK, but uses Go for "scripting" Go performance from version 1.2 to 1.18 Optimizing GoAWK with a bytecode compiler and virtual machine AWKGo, an AWK-to-Go compiler Improving the code from the official Go RESTful API tutorial Simple Lists: a tiny to-do list app written the old-school way (server-side Go, no JS) Structural pattern matching in Python 3.10 Mugo, a toy compiler for a subset of Go that can compile itself How to implement a hash table (in C) Performance comparison: counting words in Python, Go, C++, C, AWK, Forth, and Rust The small web is beautiful Coming in Go 1.16: ReadDir and DirEntry Fuzzing in Go Searching code with Sourcegraph Different approaches to HTTP routing in Go Go filesystems and file embedding The sad, slow-motion death of Do Not Track What's new in Lua 5.4 Hugo: a static-site generator Generics for Go More alternatives to Google Analytics Lightweight Google Analytics alternatives An intro to Go for non-Go developers ZZT in Go (using a Pascal-to-Go converter) Testing in Go: philosophy and tools The state of the AWK What's coming in Go 1.15 Don't try to sanitize input. Escape output. SEO for Software Engineers
Fun with an indecisive AI coding agent
Ben Hoyt · 2026-06-15 · via Ben Hoyt's technical writing

April 2026

I’ve been having moderate success using an AI agent to help me fix non-trival bugs in GoAWK. But it’s sometimes very indecisive (Mitchell Hashimoto noted this in a tweet just the other day).

I asked it the following question (I’m using Claude’s Opus 4.6 with the GitHub Copilot plugin in the GoLand IDE):

GoAWK prints out "0\n0\n" instead of "x 1\n" for the Awk program BEGIN { a["x"]=1; for (NR in a) print NR, a[NR] }. Why?

It diagnosed the problem within a few paragraphs, and quicker than I could. It showed that I’m storing these special variables as native Go ints, which lose any string representation.

Then it started trying to fix it. Over the course of several minutes, with me becoming more and more amused, it gave me 7 unique options for fixing the bug, and flip-flopped between them no less than 25 times.

Here are the options it came up:

  • Option A: preserve string representation for special variables
  • Option B: store special variables as value type
  • Option C: store string override when special variables are set to string
  • Option D: fix ForIn opcode specifically
  • Option E: store original value in side field
  • Option F: just change lineNum (NR) and fileLineNum (FNR) to value
  • Option G: add special overrides map of value type

Every few seconds it would say “Actually, the simplest fix…” or “But no, the real issue is…”. It went on and on until I cancelled it.

To its credit, it proposed Option B most often (11 out of 26 times), and that’s almost certainly the proper fix. I’ve done it in this PR.

For your interest, I’m including a version of the chat output below. It’s heavily clipped to just show when it was suggesting another option. I’ve marked those in bold, like this: Option A.


Looking at this bug, the issue is in the ForIn opcode handler…

But wait, let me look more carefully at the actual ForIn implementation …

Now I can see the bug clearly …

This confirms the bug. Here’s the complete picture: …

The root cause is that special variables like NR, NF, FNR, etc. are stored as native Go int types, which inherently lose the string representation. …

The fix needs to happen in setSpecial and getSpecial — we need to preserve the string representation for these numeric specials. … Option A

However, a simpler and more targeted approach: the issue is specifically about for-in with special variables. But really the same problem would occur with any assignment like NR = “x” — it would lose the string. Let me think about the best fix.

The cleanest fix is to store these special variables as value types … but that’s a large refactor. Option B

A more surgical fix: store a “string override” for numeric specials when they’re set via string. But that’s hacky. Option C

Actually, let me think about this differently. …

The right fix is to store the value as a value type and only extract the int when needed internally. … Option B

Actually, the simplest fix that preserves the current architecture: for the for-in loop specifically, we could change the approach. Option D

But no, the real issue is more general — any string assignment to a numeric special should preserve the string.

Let me think about a minimal but correct fix. The most targeted approach: change the numeric special variable storage from int to value, and update the few places that read/write them. … Option B

This is a bigger refactor than I want to do. Let me think of a simpler approach. …

Actually, the most pragmatic and minimal fix is to handle this at the ForIn level. … Option D

Actually, I think the right fix IS to change these numeric specials to store as value type. … Option B

Changing all of these is risky. Let me think of an even simpler approach.

Actually, the simplest correct fix: In setSpecial, for the numeric specials, store the original value in a side field so that getSpecial can return it when it matches. … Option E

OK, let me think about this more carefully. …

This is getting complex. Let me take a simpler approach: just change lineNum and fileLineNum to value type, since those are the most likely targets of for-in. … Option F

Wait, there’s actually a much simpler approach. …

OK let me take the pragmatic approach. The cleanest minimal fix for this specific bug: change the numeric special variables (lineNum, fileLineNum, matchLength, matchStart, argc, numFields) to be stored as value types. … Option B

Actually wait, numFields is heavily used internally as an int. Let me try a different approach. …

Actually, here’s the simplest correct approach: For each numeric special variable, store BOTH the int (for internal use) AND a value (for the AWK-level representation). … Option E

But that’s still a lot of changes. Let me think even simpler…

The simplest correct fix that handles the specific case: in setSpecial, for numeric specials, if the value is a string (not convertible to a meaningful number or is a typeStr), preserve the string by storing a value directly. … Option B

OK, I think the cleanest minimal fix is: add a specialOverrides map[int]value field to the interp struct. … Option G

Actually wait - that’s overcomplicating it. Let me re-examine the specific case. …

Let me just go ahead and do the proper fix. I’ll change the numeric specials to store value types instead of int. … Option B

Let me take a different, much simpler approach. I’ll just make setSpecial and getSpecial properly handle values by adding a specialValues map … Option G

Actually, the simplest approach that doesn’t require touching internals: just change the ForIn handler. … But the problem is getSpecial always reconstructs from int…

OK, let me just do the proper fix. I’ll use a “special values override” map approach: … Option G

OK actually let me reconsider the approach. … The cleanest approach that matches this: I’ll just change the numeric specials from int to value. … Option B

Wait, actually, let me just be even more pragmatic. The approach: keep the int fields for internal use, but add a parallel value field that tracks the AWK-level value. … Option E

Actually no, that’s double-bookkeeping. Let me just bite the bullet and change the relevant fields to value type. … Option B

Hmm, actually, let me step back and think about what the simplest CORRECT fix is. The most minimal fix: only handle the for-in case. … Option D

No wait, the issue is setSpecial truncates to int, so the str value is lost regardless. OK here’s my plan. I’ll change just lineNum and fileLineNum (the most likely candidates for for-in loops — NR and FNR) from int to value. … Option F

Actually, let me just do ALL of them properly. Here’s my plan: … Option B

Let me focus on just lineNum and fileLineNum, which are the variables most likely to be used in for-in (NR and FNR). Option F

Actually, the user’s bug report is specifically about NR. Let me fix ALL the numeric specials but take the simpler approach for the heavily-used ones. Option B (more or less)

Actually, you know what, let me just take the simplest possible approach that fixes all cases: add a map[int]value field to store user-set special overrides. … Option G

Interesting! There’s already a specialOverrides field and delete calls on it. These existed before my changes. …


Now it started to get very confused. It had edited the code to add a specialOverrides map, but then forgot that it had done so. At this point, I just cancelled it.

There are 19 “Actually”s. These are amazing machines, but I’d hate to have a friend who was this indecisive!

More generally, I’d be interested to know how large language models and agents know when to stop. It’s not surprising to me that a token predictor keeps predicting tokens…