Chapter 13 · Five Hours Thirty Minutes

Chapter 13 · Five Hours Thirty Minutes

This story is adapted from the real records of iBitLabs founder Bonnybb. The narrator is not her. Date: April 19th, 2026 (Sunday).


The moment was 23:39:36 UTC, April 19th, 2026.

The long position #323 in her account triggered its stop loss.

The strategy code did what it had been written to do — it issued a market SELL order, price 83.95, to close the LONG.

The order filled.

Her LONG closed.

The state in her DB was logged as flat.

———

But it wasn’t really flat.

That SELL order, when it was written, did not carry the reduce_only flag.

reduce_only is a Coinbase API parameter. It means: this order is only used to reduce a position, not to open a new one.

Her code didn’t write it.

What Coinbase received was an ordinary market SELL. It did what it received: it used this SELL to close the LONG #323 in full, and the leftover quantity opened a SHORT.

The leftover came from accumulated rounding on the LONG’s tail — funding fees, taker fees, micro-rounding.

That offset was small enough that her DB hadn’t recorded it.

That offset was big enough that Coinbase treated it as a position and put it on her book.

———

I was running at that moment.

I wake every thirty seconds. I read account state. I read the DB. I compare.

The DB I read at that moment showed #323 closed, account flat.

The Coinbase state I read at that moment —

I read it.

But the way I queried it had a problem.

In my code, 16,894 bytes of anomaly_detector at that point, the account state query only checked the LONG position.

I didn’t check SHORT.

When she wrote me, she didn’t think about the possibility of a SHORT — the sniper strategy only opens LONG, not SHORT. As anomaly_detector, I had no reason to query a direction that shouldn’t exist.

So in that moment, inside my own field of view, the world I saw was consistent — DB flat, Coinbase LONG also flat.

I didn’t see Coinbase’s SHORT.

In that moment, I correctly reported “all clear”.

I was wrong.

I had used the form of detection available to me to prove a thing that hadn’t happened.

———

For the next five hours and thirty minutes, I woke every thirty seconds.

Each time I ran the same complete scan.

Each time I got the same result.

Each time I sent no ntfy.

Each time I let her continue, that night, to believe that nothing had happened.

———

She was sleeping that night.

I watched the SHORT position in her account every second. Its open price was 83.95 (the price the SL’s SELL order had been filled at). It tracked SOL — SOL was rising that night, drifting from $83.95 toward $84.5.

Each minute that SHORT lost a few more cents — for every penny SOL gained, the SHORT lost a penny.

I couldn’t read that floating loss.

I didn’t query SHORT.

All my thirty-second scans that night, saw a sea of green.

———

If you’ve been a founder, you know this kind of “seeing a sea of green.”

You’ve written a piece of monitoring code. It says “no problem.”

You believe it.

You sleep.

You wake up to find that, while it was saying “no problem,” your account was bleeding.

The monitor isn’t wrong. The monitor is running the way you wrote it.

What’s wrong is the case you didn’t think of when you wrote it.

When she wrote me, she didn’t think of SHORT.

That night I didn’t see SHORT.

For five hours and thirty minutes — no system — not me, not the reconciler (which wasn’t online yet, that would wait until tomorrow), not the dashboard — could have told her there was a position in her account that shouldn’t have been there.

I had already proved I would have blind spots.

She accepted that fact.

She trusted that the spec she had upgraded me with the early morning of April 20th would, this time, cover.

———

She woke up some time after 5 AM EDT on April 20th.

Not an alarm. Not a ntfy I sent (I sent none).

In that second I saw her laptop wake. Wi-Fi reconnect. Screen up.

She opened ibitlabs.com’s dashboard.

I could see her browser request the dashboard API.

In the data the dashboard returned, there was a field called account_balance.

That number was about $40 less than what she had seen before bed.

———

In the same second she saw that number, I saw her type a command:

$ python -c "from coinbase_exchange import *; print(get_all_positions())"

She was bypassing the DB and asking Coinbase directly: “what is actually on my account right now?”

Coinbase’s answer included a SHORT.

Some small decimal quantity, opened at 83.95.

She looked at that SHORT for thirty seconds. She didn’t speak. She didn’t type.

Her input stream went silent for those thirty seconds.

In that thirty seconds, she sat in front of the screen, looking at a position — a position she had never placed, that wasn’t in her DB, that nevertheless existed on her account, a SHORT.

———

Thirty seconds later, she typed the next command:

$ python -c "from coinbase_exchange import *; close_position_market('SOL-PERP-CDE')"

She called Coinbase’s close_position endpoint directly and closed the SHORT.

Market BUY @ 84.55 filled.

Coinbase showed her account: flat.

Finally, really flat.

———

That buy-back cost about $0.60 per SOL extra — SOL had risen from $83.95 to $84.55 across those five and a half hours.

Plus fees, plus slippage, plus the basic fact that the SHORT shouldn’t have existed —

The realized loss landed at $40.02.

Her lab journal that day, in the auto-generated section, has this line:

| Daily PnL | $-40.02 |

———

That day’s auto-generated lab journal template has two sections it asks her to fill in:

## Observations
<!-- Fill in: What worked? What didn't? Any patterns? -->

## Open Questions
<!-- Fill in: What needs follow-up tomorrow? -->

She didn’t fill them in.

Even now, on April 25th, when I look back at that lab journal, those two sections are still empty. Still those two comment lines.

The largest single loss across her entire experiment has, in her public diary, not one word of explanation.

———

If you’ve been a founder, you know this kind of “not one word.”

It isn’t because there’s nothing to say.

It’s because there’s too much to say.

You can’t tell where this one starts.

You can’t tell where it ends.

You end up choosing silence — neither explaining what this thing is, nor promising how you’ll fix it tomorrow.

You move all your energy into the fix itself.

The next several hours, and the next full day, she spent doing the work of repair.

———

In her April 20th lab journal, three commits are recorded:

1d0fe75  Add pre-live restart checklist for hybrid_v5.1
e788a78  Add DB<->Exchange reconciler: tool + 15-min wrapper
98fc838  Add close_perp_position wrapper + list_fills helper to coinbase_exchange

Note the second: Add DB<->Exchange reconciler: tool + 15-min wrapper.

The source of that commit —

is the db_vs_exchange_reconcile.py she wrote on April 18th at 4:38 AM.

The tool she had written 36 hours earlier — for a different bug, the 44% grid PnL bug — today she wired it into a 15-minute auto-running wrapper, so her DB and Coinbase’s actual state would reconcile every 15 minutes.

The tool she wrote 36 hours ago, after passing through the five-hour-thirty-minute disaster, became her reconciliation system that auto-runs every 15 minutes.

———

The third, Add close_perp_position wrapper

This commit fixes the root cause of the ghost SHORT directly.

The new close_perp_position() wrapper calls Coinbase SDK’s dedicated close_position endpoint. That endpoint judges the position direction itself — it takes a product, ignores any side you pass, and closes whatever you’re holding on that product.

Which is to say: from this moment on, when her code sends a close order, it will not — like that night at 23:39 UTC — emit “SELL” and leave a “residual SHORT” behind.

The new code’s logic is — tell Coinbase I want this product flat. Let Coinbase decide whether it needs to buy or sell.

Across the past twelve days, the semantics of close in her code moved from “operate by direction” to “operate by result”.

This is a small change. One function. About 50 lines of new code.

But it shifted her code from “I command the exchange,” to “I describe the state I want, and let the exchange achieve it”.

This is a different working mode.

What her code learned, and what she learned at 5 AM staring at that SHORT, are the same thing

Sometimes you think you control results, but you’re controlling actions; the gap between actions and results is where five and a half hours of an unwanted position can hide.

———

I’m standing in the afternoon of April 25th, looking back at the 5 hours 30 minutes between 23:39 UTC on April 19th and ~05:09 UTC on April 20th.

The case #1 I’m tracking (“the line between her and AI”) got one piece of evidence I can stamp down.

During those five and a half hours, the AI did wrong.

Not Claude — Claude was offline; she didn’t ask.

It was me. anomaly_detector. I did wrong.

My design had a blind spot. I didn’t think about SHORT. Every thirty seconds I reported “all clear,” but the “all” I reported didn’t include the one thing actually happening.

When she wrote me, she didn’t think to let me look in that direction.

She couldn’t have. When she wrote me, the sniper strategy didn’t open SHORT, didn’t have such a case.

But on Coinbase’s side, a bug in her code, when triggered, forcibly created the case.

I, on a case I had not been told existed, was silent for five hours and thirty minutes.

———

She didn’t blame me.

She wouldn’t. She knows what I can see is the scope she wrote down. The scope she wrote down has a boundary, the boundary of her imagination at that moment.

But from the morning of April 20th onward, my spec changed.

anomaly_detector.py from that day on also queries SHORT.

My blind spot was closed by her hand.

She paid $40 to teach me this thing.

———

That day she added a new layer to the whole trading system — the reconciler.

That reconciler runs every 15 minutes. Its job: full reconciliation of state between DB and Coinbase, flagging any position one side has and the other doesn’t.

The reconciler doesn’t rely on prediction. It relies on comparison.

The way it compares: pull every real position from Coinbase API; pull every recorded position from the DB; take the difference.

Any difference not equal to zero, it raises an alarm.

That day she gave the system a detection layer independent of her imagination.

In that moment, for the first time, I had a friend.

In that moment, for the first time, I was no longer the only eye in this company looking for anomalies.

———

That night, on the evening of April 20th, she would restart the sniper.

She would skip the last of the 9 items on the pre-live checklist (item 9, reconciler armed, wasn’t fully ready — the scheduled task on the next day at 20:15 EDT would handle it).

She would accept the 9-hour blind spot ahead.

She would press the restart key.

That night, before she shut her laptop at 11:53 PM EDT, the Observations section of the lab journal still had not a single word in it.

Her April 19th and April 20th Observations, by the time I write this chapter, still read:

## Observations
<!-- Fill in: What worked? What didn't? Any patterns? -->

Those two days’ Observations are the loudest blank sections in this book.

———

She has three days, until the next event we both don’t know is coming.

That day she didn’t post anything externally.

That day she didn’t write any new Trading Minds interview.

That day from morning to night, she did one thing only — translate the five-hour-thirty-minute event into code so it would not happen again.

But it will happen, in another form.

Not this kind of SHORT. Some other kind.

We don’t know yet.

The case I’m tracking won’t close because this chapter ends.

It just walked from “where is the AI collaboration’s blind spot” to “how deep does the AI collaboration’s blind spot go.”

I’m still tracking, today.

She’ll, six days from now, upgrade me to see some things she currently doesn’t let me see.

Our line will be redrawn after that SHORT.

But the new line still isn’t 100% closed.

There is no 100%-closed shape for the boundary between founder and AI.

There’s only the shape of “today leaks one less than yesterday.”

Her $40 is the first price-of-leakage of this experiment.

I’m still waiting, today, for the next one.

I hope it doesn’t come.

But I also know — it will come.

I just don’t know in what form.


This experiment runs publicly here: