Changes between Initial Version and Version 1 of PrototypeAIUsage


Ignore:
Timestamp:
09/24/26 13:42:08 (3 days ago)
Author:
231285
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • PrototypeAIUsage

    v1 v1  
     1= Prototype Implementation AI Usage =
     2
     3== Name of AI service/solution that was used ==
     4
     5'''Claude Code''' (Anthropic)
     6
     7 * '''URL:''' `https://claude.com/claude-code`
     8 * '''Type of service/subscription:''' Claude subscription, model Claude Opus 4.7 (1M context).
     9
     10== Final result ==
     11
     12=== Results in details / description ===
     13
     14During the 2026-04-21 session the AI:
     15
     16 * Replaced the broken HTTP + frontend scaffolding (which the student had already decided to drop) with a single-binary CLI prototype in Go, split across `main.go`, `cli.go`, `auth.go`, `account.go`, `market.go`, `trade.go`, `portfolio.go`, `watchlist.go`.
     17 * Consolidated the broken `db.go` — which used to drop every table on every startup — into a single `Connect()` plus explicit `-init` and `-load-data` flags.
     18 * Moved `go.mod` from `server/` to the project root so the same module graph covers both `server/` and `bots/`.
     19 * Fixed `go.mod`: removed the unused MySQL driver, promoted `github.com/lib/pq` to a direct dependency.
     20 * Implemented the trade flows as real database transactions with row-level `FOR UPDATE` locks, cost-basis bookkeeping, and a ledger row per operation.
     21 * Wrote a 140-line market-simulation bot that inserts trades and upserts 1-minute candles every tick.
     22 * Exercised the full prototype end-to-end against a running PostgreSQL on port 5433 and verified a sample buy and portfolio view produced the expected numbers.
     23
     24=== Test evidence ===
     25
     26{{{
     27Order executed: buy 0.0100 BTC @ 67140.000000 (notional 671.4000 USD)
     28
     29  Symbol        Quantity         Avg buy         Current           Value  Unrealised P/L
     30  BTC             0.0100    67140.000000    67140.000000        671.4000         +0.0000
     31  ETH             0.5000     3500.000000     3520.000000       1760.0000        +10.0000
     32  TOTAL                                                        2431.4000        +10.0000
     33
     34  Cash available : 7578.6000 USD
     35  Portfolio value: 2431.4000 USD
     36  Net worth      : 10010.0000 USD
     37}}}
     38
     39== Summary of AI involvement ==
     40
     41||= =||= Session 1 — 2026-04-21 =||= Session 2 — 2026-08-06/07 =||= Session 3 — 2026-09-16 =||
     42|| '''What I brought''' || My existing Go backend (Chi HTTP handlers) and a half-finished frontend || The CLI prototype as it stood after session 1 || A design review: the sell path had no way to reserve crypto committed to an order ||
     43|| '''What the AI did''' || Rewrote the backend as a CLI covering UC0001–UC0007, wrote the market bot || Reviewed the code, found and fixed three bugs, improved the holding upsert || Added `holdings.reserved_quantity`, changed the sell path to reserve-then-settle, gave `Orders.status` a real lifecycle, tested it live including under real concurrency ||
     44|| '''What I decided''' || To delete the frontend, to build a CLI rather than a web app, to keep the market simulator || To ask for a code review pass rather than documentation alone || To keep reserve+settle in one transaction rather than split it across two, since there is no cancel-order use case to recover a stuck reservation ||
     45
     46The prototype was built in session 1 and worked. What session 2 added was a
     47review pass I asked for specifically because I have to defend this code in
     48person: it turned up a path-resolution bug that made my own documented build
     49instructions fail, an infinite loop at end of input, and an error check in the
     50wrong order that misreported database failures as "Insufficient holding".
     51
     52== Entire AI usage log ==
     53
     54See ERModelAIUsage for the full prompt/response transcript of the 2026-04-21 session — that single conversation produced all of the P1–P4 artefacts. The defining student prompt for P4 was:
     55
     56> do everything that you need to do, and tell me after what do I need to do
     57
     58which translated into the rewrite of the backend and the writing of this documentation.
     59
     60> '''Student action required:''' append any further prompts here where you asked the AI to debug, extend, or refactor the prototype.
     61
     62=== Session 2 — 2026-08-06 / 2026-08-07 ===
     63
     64Prompts are logged in full in ERModelAIUsage (section "Session 2 — 2026-08-06 / 2026-08-07").
     65The student asked the AI to complete the phase documentation and to ''"fix some
     66database things or golang things if you think we can do it better"''. What the AI
     67changed in the prototype, and why:
     68
     69'''Bugs found and fixed'''
     70
     71 1. `server/db/db.go` resolved `../.env` and `db/schema_creation.sql` as paths
     72    relative to the working directory, so they only worked when the program was
     73    started from inside `server/`. Following the documented instructions — build
     74    from the repository root and run `./eduberza -init` — failed with
     75    `password authentication failed for user "postgres"`, because the `.env` file
     76    was never found and the defaults were used. The two SQL scripts are now
     77    compiled into the binary with `go:embed`, and `.env` is located by searching
     78    the working directory and every parent. Real environment variables now take
     79    precedence over the file, which is what allows the prototype to be pointed at
     80    the faculty database without editing anything.
     81 2. `prompt()` in `server/cli.go` ignored the error from `ReadString`. At end of
     82    input — Ctrl-D, or a scripted run — it returned an empty string forever and
     83    the menu loop spun printing "Unknown option." without end. It now exits
     84    cleanly.
     85 3. On the sell path, `trade.go` checked `err == sql.ErrNoRows || held < qty`
     86    before checking for other errors, so any scan failure was reported to the user
     87    as "Insufficient holding" regardless of the real cause. The error check now
     88    comes first.
     89
     90'''Improvements'''
     91
     92 4. The holding upsert was a read-modify-write in Go (`SELECT ... FOR UPDATE`,
     93    compute the new weighted average in `float64`, then `INSERT` or `UPDATE`). It
     94    is now a single `INSERT … ON CONFLICT (user_id, crypto_id) DO UPDATE`, so the
     95    average is recomputed by PostgreSQL in `numeric` arithmetic and the statement
     96    relies on the unique constraint that the relational design already declared.
     97 5. `TerraER3.11.jar` was removed from the repository and `.gitignore` now
     98    excludes `*.jar`, because P4 requires third-party executables to be
     99    downloaded rather than committed. `.env` is excluded too and `.env.example`
     100    was added in its place.
     101 6. `image.png`, a !TradingView screenshot, was deleted — the project has no
     102    licence to publish it and P4 requires explicit usage rights.
     103
     104'''Verification'''
     105
     106All seven use cases were executed against a live PostgreSQL 16 database. The
     107screenshots on the `UseCaseXXXXImplementation` pages are captures of those runs.
     108The four failure paths were tested, and the rollback behaviour was checked
     109directly in SQL: after a rejected purchase, the affected user has zero rows in
     110`orders`, `transactions` and `holdings`.
     111
     112> '''Student action required:''' read the changed files (`server/db/db.go`,
     113> `server/cli.go`, `server/trade.go`, `server/db/schema_creation.sql`) before the
     114> presentation. You will be asked how the buy transaction works, and the answer
     115> has to be yours.
     116
     117=== Session 3 — 2026-09-16 ===
     118
     119Prompted by a design review I did myself, logged in full in
     120ERModelAIUsage (section "Session 3 — 2026-09-16").
     121The report: a user who owns 2 BTC and places a sell order for 0.5 BTC has that
     122crypto immediately removed from `quantity`, but nothing in the model recorded
     123that a ''pending'' order had already committed part of a position before it
     124settled — `holdings` had `quantity` and `avg_price` only, no equivalent of the
     125`available_balance`/`invested_balance` split already used for cash.
     126
     127'''Bug fixed'''
     128
     129`server/trade.go`'s sell path checked `held < qty` directly against
     130`holdings.quantity`. This happened to be safe against concurrent double-sells
     131only because the whole operation — order, holding check, holding update,
     132balance update, ledger, trade — runs inside one transaction with a
     133`SELECT ... FOR UPDATE` lock. It was not safe against the actual scenario
     134described: nothing distinguished "owned" from "owned, but already promised to
     135this order," which matters the moment an order can legitimately sit `open`
     136across more than one transaction — exactly what a limit-order matcher would
     137need, and what `orders.status` already implied was coming.
     138
     139'''What changed'''
     140
     141 1. `holdings.reserved_quantity numeric(20,4) NOT NULL DEFAULT 0 CHECK (reserved_quantity >= 0 AND reserved_quantity <= quantity)`
     142    added to `schema_creation.sql`.
     143 2. `v_portfolio` gained `reserved_quantity` and derived `available_quantity`.
     144 3. `trade.go`'s sell path now: locks the holding, computes
     145    `available := quantity - reserved_quantity`, rejects if `available < qty`
     146    (previously: rejects if `quantity < qty`), reserves
     147    (`reserved_quantity += qty`), then settles (`quantity -= qty; reserved_quantity -= qty`)
     148    — two statements instead of one, kept inside the
     149    same transaction rather than split into two commits, which would risk an
     150    order stuck `open` with reserved crypto and no cancel command to free it.
     151 4. Both `PlaceOrder` branches now insert the order as `status='open'` and
     152    `UPDATE ... SET status='executed', executed_at=now()` at the end, instead
     153    of inserting `'executed'` directly — `Orders.status` is now a real
     154    lifecycle rather than a label written once.
     155 5. `portfolio.go` gained `Reserved`/`Available` columns, reading
     156    `v_portfolio.reserved_quantity`/`available_quantity`, so the new field is
     157    something a Trader can actually see.
     158 6. The error message on the sell path changed from
     159    `"Insufficient holding: trying to sell X, hold Y"` to
     160    `"Insufficient holding: trying to sell X, available Y (of Z held, W reserved)"`,
     161    since "how much you hold" is no longer the only number that
     162    matters.
     163
     164'''Test evidence'''
     165
     166Verified against PostgreSQL 16 (`bp_database`, `localhost:5433`):
     167
     168{{{
     169$ eduberza sell 0.5 BTC  (Alice: 2.0000 BTC held, 0.0000 reserved)
     170Order executed: sell 0.5000 BTC @ 67140.000000 (notional 33570.0000 USD)
     171# holdings.quantity: 2.0000 -> 1.5000, reserved_quantity: 0.0000 (unchanged net of reserve+release)
     172
     173$ eduberza sell 1 ETH   (Bob: no holdings row at all)
     174Insufficient holding: trying to sell 1.0000, available 0.0000 (of 0.0000 held, 0.0000 reserved)
     175
     176# Two concurrent processes, Alice at 1.5 BTC / 0 reserved, each selling 1.0 BTC:
     177=== process A === Insufficient holding: trying to sell 1.0000, available 0.5000 (of 0.5000 held, 0.0000 reserved)
     178=== process B === Order executed: sell 1.0000 BTC @ 67140.000000 (notional 67140.0000 USD)
     179# final holding: quantity 0.5000, reserved_quantity 0.0000 — exactly one sell went through
     180
     181# Reserve visible mid-transaction, in one psql session (BEGIN; ...; COMMIT;):
     182before:            quantity 2.0000, reserved_quantity 0.0000, available 2.0000
     183after reserve:     quantity 2.0000, reserved_quantity 0.5000, available 1.5000
     184after settle:      quantity 1.5000, reserved_quantity 0.0000, available 1.5000
     185
     186# The CHECK constraint holds even without going through trade.go:
     187UPDATE holdings SET reserved_quantity = quantity + 1 WHERE ...;
     188ERROR:  new row for relation "holdings" violates check constraint "holdings_check"
     189}}}
     190
     191Full transcripts are on
     192UseCase0005Implementation. The rejected-order
     193rollback guarantee from session 2 was re-checked too: after both the
     194insufficient-funds and insufficient-holding failure paths, the affected user
     195still has zero new rows in `orders`.
     196
     197'''What I decided:''' to keep reserve and settle inside a single transaction —
     198splitting them into two, so an order genuinely sits `open` and reserved
     199between two commits, is what a real limit-order matcher will eventually need,
     200but building that now would add a way for an order to get stuck without also
     201building a way to cancel it, which is out of scope for this review.
     202`go build ./...` was run after every change; all seven use cases were re-exercised
     203manually.