View on GitHub

slopstop

Ticket-anchored AI development — stop slop before it goes in

← Index · 1. Design and grill · 2. Tickets and the adversary →


1. Design and grill

10:01:32 – 10:23:24 · 13 questions in 19 minutes · claude-opus-5 (huge tier) Source: Transcript A, turns cited as [n]. Notation key: index §3.

Stage 1 turns a five-sentence description into a PRD and a feature charter, and ends at gate G1. No tickets are cut here and no code is written. What it produces is a set of decisions — and, more interestingly, a record of which decisions collided with each other.

The input it starts from is quoted in full at index §1. Everything below is the process discovering what that description left out.


10:01:49 [22] — Tier gate, before anything else

SLOPSTOP SAYS: “Tier gate passes: [stage_tiers] absent → design runs on huge; [tiers.huge] = opus v5; this session is claude-opus-5. Match.”

Why show it: four seconds of output, and it is the setup for the payoff in §3 — the same gate fails at Stage 3 and hard-stops the run. Showing the pass first makes the later failure legible as a designed mechanism rather than a bug.


10:02:39 [40] — Why it asks at all

SLOPSTOP SAYS: “Greenfield repo — nothing in it but the README and .project-conf.toml, so the codebase can’t answer these for me. Starting at the root of the tree: every other decision (file layout, test framework, how a command module is even shaped) hangs off language choice.”

Why interesting: it states the ordering principle it then follows for 19 minutes — ask the question that constrains the most other questions first. Everything below is downstream of this one sentence.

Note the first clause. On an existing codebase most of these questions would be answered by reading it; the grill asks a human only what the repo cannot tell it.


10:02:43 [41] — Q1 Language · recommendation overridden

SLOPSTOP ASKS: “What language and runtime should the KV CLI be built in?”

  • Python 3 + stdlib (recommended) — argparse, json, pathlib. Zero third-party deps. “The store is literally a JSON file.”
  • Go — single static binary, table-driven tests. “Stronger compile-time gate on parallel agents.”
  • TypeScript + Node — “adds package.json, a lockfile, and a build step — three shared files.”
  • Rust — “best correctness guarantees, worst fit here: Cargo.toml is shared, compile times dominate.”

IAN ANSWERS: Go ⚠

Consequence, immediately, at 10:09:40 [44]:

SLOPSTOP SAYS: “Go. That settles the language branch — and immediately creates the one real tension in this design: go.mod and main.go are shared files that every parallel agent would otherwise touch.”

Why this is worth including despite being Go-specific: it is the turn that makes the run Go-flavored, and the recommendation was Python. Nothing about the process assumed Go; one answer at 10:02:43 did. And the answer did not merely get recorded — it created a new problem (shared files) that becomes the very next question.

Notice also that every option is scored against the same criterion — what does this do to parallel agents? — which comes from the last sentence of the original input, not from anything about key-value stores.


10:09:48 [45] — Q2 Decomposition · caused by the Go answer 8 seconds earlier

SLOPSTOP ASKS: “Five agents writing five commands in parallel all need the same store-load/store-save code and all need to be registered with the CLI dispatcher. How should that shared surface be handled?”

  • Foundation ticket first, then fan out (recommended) — “one sequential ticket lands go.mod, main.go, and internal/store with the dispatch table.”
  • All six in parallel, contract in ticket text — “faster wall-clock, but…”
  • No shared package — each command self-contained — “maximum disjointness, but five copies of the same code.”

IAN ANSWERS: Foundation ticket first, then fan out

SLOPSTOP SAYS (10:10:37 [50]): “Foundation-first. That gives a clean 1-then-5 shape with genuinely disjoint file maps. Now the store contract itself — the foundation ticket has to freeze this, since all five agents code against it blind.”

Consequence at 11:11 (§4): that shape is the fleet plan — Wave 1 solo (#2 Foundation), Wave 2 parallel (#4–#8), Wave 3 solo fan-in (#9).

Why interesting: the load-bearing question of the entire run. One answer at 10:09:48 determines the execution topology two hours later. Note the phrase “all five agents code against it blind” — the agents will never see each other’s work, so anything two of them must agree on has to be frozen before either starts.


10:11:28 [54] — Q3 answered, and the process corrects its own risk assessment

SLOPSTOP ASKS: “Where does the store file live, and how does the user point at a different one?”

  • ./kv.json + KV_STORE env override (recommended)
  • ./kv.json + global --file flag
  • XDG user dir
  • Both env var and flag — “flag beats env beats default. Maximum flexibility, but it’s three-source precedence logic in a tutorial toy.”

IAN ANSWERS: Both env var and --file flag ⚠

SLOPSTOP SAYS: “Both, with --file > KV_STORE > ./kv.json. Note that this reduces risk rather than adding it under the foundation-first shape: main.go resolves the path once and hands the resolved path to the command, so no agent ever implements precedence.”

Why interesting: the option’s own stated downside was invalidated by the answer to Q2 one minute earlier. The process noticed the interaction and said so instead of silently keeping its original objection. The cleanest small example of answers compounding rather than accumulating.


10:12:26 [59] — Q5 CLI contract · recommendation overridden (idempotent delete)

SLOPSTOP SAYS (10:12:20 [58], framing the question): “Now the contract that matters most for blind parallel agents: five separate files must agree on stdout/stderr/exit codes with no coordination between them.”

SLOPSTOP ASKS: “What are the output and exit-code conventions every command must follow?”

  • Silent success, 0/1/2, both get and delete fail on missing key (recommended)
  • Same, but delete is idempotent (missing key = exit 0) — “matches rm -f… costs you the symmetry with get, which means it’s a special case every agent must remember.”
  • Chatty confirmations on success

IAN ANSWERS: idempotent delete

SLOPSTOP SAYS (10:13:12 [65]): “Idempotent delete it is — the asymmetry with get is now the single most likely thing for a blind agent to get wrong, so I’ll make it an explicit, test-backed acceptance criterion in that ticket rather than a line of prose.

And it follows through, at G1 (10:23:24 [122]), as one of “three things worth your eye”:

GATE: “That’s your call from the grill and it’s specified — but it’s the most likely thing for an agent to ‘fix’ unprompted.”

Why interesting: the mechanism by which a human preference becomes a red test. The process does not argue with the choice; it identifies the failure mode the choice creates and converts it into a test the implementing agent cannot quietly route around. “An agent will think this is a bug and helpfully repair it” is a real risk, and prose in a ticket does not prevent it — a failing test does.


10:14:37 [75] — Q9 Store robustness · the first half of the time bomb

SLOPSTOP ASKS: “How should the store package handle a missing file, a corrupt file, and crash-safety on write?”

  • Missing = empty store; corrupt = hard error; atomic write (temp file + rename); mode 0600 (recommended)
  • Same, but plain os.WriteFile — “gives up crash-safety on the one file the whole tool exists to protect.”
  • Same, but corrupt file is backed up and reset — “converts a loud, fixable error into silent data loss.”
  • Missing file is an error until kv init is run

IAN ANSWERS: the recommendation. This becomes decision D8.

Why flag it now: nothing looks wrong. Temp-file-plus-rename is the correct, conventional answer, and it was taken on the recommendation without argument. Remember the timestamp — 10:14:37 — it matters in 24 minutes.


10:17:16 [87] — The question it declined to ask

SLOPSTOP SAYS: “Layout and toolchain — let me check what’s actually installed rather than ask.”

Runs go version, checks for golangci-lint, lists git remotes.

SLOPSTOP SAYS (10:17:24 [92]): “Go 1.26.4, golangci-lint present, single remote origin. Module path is determined by the remote.”

Why interesting: a 13-question interview that refuses to ask a 14th it can answer itself. Worth one caption as the counter to “these skills just interrogate you.” It also silently resolves the module path, which an adversary later checks against the real remote.


10:17:31 [93] — Q11 Layout · the second half of the time bomb

SLOPSTOP ASKS: “Repo layout and dependency policy… What structure?”

  • cmd/kv + internal/{store,command}; stdlib flag; zero deps (recommended)
  • Flat: main.go at repo root
  • Use cobra — “it adds go.sum — a shared, agent-touchable file.”
  • Single package, no internal/

IAN ANSWERS: the recommendation — zero dependencies.

Why flag it: the zero-dep policy is adopted at 10:17:31. It has 2 minutes to live.


10:18:41 [97] — Q12 Concurrency · recommendation overridden — this is the pivot

SLOPSTOP SAYS (10:18:35 [96]): “One genuine correctness gap left, then I’ll close out.”

SLOPSTOP ASKS: “Two kv set processes running at once can lose a write — both load, both save, last writer wins. Address it now or defer?”

  • Defer — document last-writer-wins (recommended) — “the atomic temp+rename already guarantees the file is never left corrupt or truncated; the only exposure is a lost update.”
  • Add advisory file locking to the store package now — “closes the gap properly. It lives entirely in the foundation ticket.”
  • Compare-and-swap on file modtime

IAN ANSWERS: add advisory file locking now ⚠ · This becomes decision D13.

Why interesting: everything from here to 10:53 exists because of this one override. Had the recommendation stood, the run would have been simpler and the adversary in §2 would have had nothing serious to find. It is also worth noting that the human is choosing the more rigorous option against advice — the override is not laziness, and the process’s own recommendation was the one that would have shipped a documented known limitation.


10:19:36 [102] — The collision, detected 2 minutes after it was created

SLOPSTOP SAYS: “That decision collides with the zero-dependency policy — Go’s stdlib has no portable file lock, and the usual answer (golang.org/x/sys) would create the go.sum we just eliminated. Resolving that dependency before I close:”

Caused by: Q11 at 10:17:31 (zero deps) vs. Q12 at 10:18:41 (locking) — 70 seconds apart.

Why interesting: the grill catches a contradiction between two of its own just-answered questions and reopens rather than papering over it. This is the concrete argument for interviewing before ticketing: neither answer is wrong alone, and no amount of care on either individual question would have surfaced the conflict.


10:19:44 [103] — Q13 Lock mechanism · recommendation overridden

SLOPSTOP ASKS: “How should the lock be implemented, given zero-deps was chosen?”

  • syscall.Flock, unix-only build tag (recommended) — “stdlib, so go.sum still never exists.”
  • syscall.Flock on unix + LockFileEx on Windows — “the Windows path can’t be built or tested on this machine, so it ships as unverified code.”
  • Sidecar lockfile via O_CREATE|O_EXCL — “pure portable stdlib with no build tags at all. But it reintroduces exactly what flock avoids: a crashed process leaves a lock nobody releases, so you need staleness timeouts and PID checks.”
  • Accept golang.org/x/sys as a dependency — “the conventional, well-tested answer. go.sum would exist, but only the foundation ticket creates it.”

IAN ANSWERS: accept golang.org/x/sys ⚠ — i.e. flock, on the store file, with a real dependency.

Remember the rejected sidecar option. It comes back in 20 minutes wearing a different hat (§2).


10:20:22 [106] — Q14, generated by the Q13 answer

SLOPSTOP SAYS: “Locking changes the store API shape — a load→modify→save sequence must hold one lock across both halves, so Load/Save as separate calls would let an agent hold it wrong. Final question:”

SLOPSTOP ASKS: “What API should internal/store expose so the five agents can’t misuse the lock?”

  • Transactional View/Update closures (recommended)
  • Open() handle with Load/Save/Close
  • Keep Load/Save; document that callers must lock — “makes correct locking a per-agent responsibility.”

IAN ANSWERS: transactional closures.

Why interesting: a third-order consequence. Q12 (override) → forced Q13 (collision) → forced Q14 (API shape). Three questions that exist only because one recommendation was declined at 10:18:41. And the resulting API is defensive by construction — at 10:21:44 [110]:

SLOPSTOP SAYS: “the store API is transactional closures, so no agent can write a locking or save-forgetting bug even in principle; and the dispatch table ships pre-wired with stubs, so the parallel agents edit files that already exist rather than racing to create them.”

That is the design principle of the whole stage in one sentence: do not ask five blind agents to each get something right — make it impossible for them to get it wrong.


10:23:24 [122] — G1 gate

GATE:

G1 — design complete for run kvstore-20260725-1001
PRD:      scratch/runs/kvstore-20260725-1001/prd.md      (15 decisions, 2 assumptions, 5 deferrals)
Charter:  scratch/runs/kvstore-20260725-1001/charter.md  (12 rules)

Shape that came out of the grill — 1 sequential foundation ticket → 5 fully parallel command tickets (two files each, zero overlap) → 1 fan-in integration ticket.”

Two decisions had to be reconciled after the fact. Locking collided with the zero-dependency policy, and then made a plain Load/Save API unsafe.”

Assumption A1: unix-only. Cheap to overturn now, expensive later.”

“Go ahead with ticket breakdown?”

Why interesting as a closing beat: the gate surfaces the design’s own scar tissue rather than presenting a clean façade. The human is being asked to approve a design and told which two parts of it were patched mid-interview and which assumption is cheapest to reverse right now.


Section summary

Question Time Recommendation Answer Downstream
Q1 Language 10:02:43 Python 3 Go shared-file tension → Q2
Q2 Decomposition 10:09:48 foundation-first taken the entire wave plan
Q3 Store path 10:11:34 env only both risk reduced by Q2
Q4 JSON shape 10:11:34 flat string→string taken
Q5 CLI contract 10:12:26 symmetric idempotent delete test-backed criterion
Q6 list format 10:13:16 sorted keys taken README bugs at 12:52
Q7 export 10:13:58 overwrite, no mkdir taken
Q9 Store robustness 10:14:37 atomic temp+rename taken D8 — half the bomb
Q10 Validation 10:16:14 strict per-command taken
Q11 Layout 10:17:31 zero deps taken collides with D13
Q12 Concurrency 10:18:41 defer lock now D13 — the pivot
Q13 Lock mechanism 10:19:44 flock, unix tag x/sys flock on the store file
Q14 Store API 10:20:29 View/Update closures taken agents can’t misuse the lock

⚠ = human overrode the recommendation. Five of thirteen. Every one of them generated downstream work; the eight that were taken mostly did not. Two of them (Q12, Q13) produced the defect that §2 is about.

Cost of this stage: 19 minutes of human attention, 13 questions, zero lines of code.


← Index · 1. Design and grill · 2. Tickets and the adversary →