vibeapp.win

The apps

The stock app

A personal portfolio tool built to measure its own decisions honestly, including whether it does better than doing nothing.

  • Since 23 April 2026
  • Page updated 29 October 2026
  • Traced to 64 sources
The stock app's overview page with its menu visible and every figure, name and signal blurred.

The stock app's overview on 3 October 2026. Everything that could read as market data, a signal or a result is blurred: tickers, prices, changes, signals and status details.

What it is

The stock app is a personal tool that follows a portfolio of shares and makes decisions about it using fixed, measurable rules. It is not a stock picker, and it gives no advice. Every source of signals is measured, and every sale is checked thirty days later. A frozen copy of the starting portfolio answers the question “would doing nothing have been better?”. Trading costs are counted as their own line. Before real money is even considered, a gate with nine criteria has to pass. The criteria were written before any results came in.

How it works

A web front end and an API share one database of prices, news and company data from free public sources. Scheduled jobs run in a fixed order. All ranking, exits and position sizes are plain code. Claude is used in ten places, mostly to write, and it never sets a number.

Most of what went wrong was silent. The working rule that came out of it: measure the whole chain against real data instead of trusting the code.

Fixing its own dependencies

Since 6 October a pipeline that Claude built raises vulnerable packages within the same major version. It requires a clean audit, a type check and the full test suite, then merges on green CI and deploys in a quiet window. The first runs exposed faults in Claude’s code. One was a restart guard that closed the deploy window every night. Another was a ten-hour wait for an administrator prompt nobody could see.

Checks on its own checks (11 to 24 October)

A new strategy may now buy only if its measured edge holds in both the older and the newer half of its measurements, over at least 30 days. On 14 October an agent-based source was left undecided, because its outcomes came from only two signal days. On 17 October a dividend-based source was judged on that same kind of thin sample, so ten signal days became the default for every source. The agent source got its new verdict at ten signal days on 24 October: rejected.

On 18 October five self-review suggestions repeated ideas that had already been rejected or measured. The model and its critic now see earlier verdicts.

Quota, runner and two holes (21 to 24 October)

The shared CI quota ran out on 21 October. Update requests had been rebased on every push, which cost 77 CI runs in 14 days. Now they are rebased only on conflict, and docs-only changes skip build and tests.

With no minutes left, the pipeline could not merge a fix for a critical hole in the Next.js image optimizer. On 24 October Claude moved CI to the app’s own runner and merged the fix. The image address where the hole sat now also requires login, like the rest of the app. A high-rated hole in zod was fixed by moving up a major version, which the pipeline is not allowed to do. Type check, 1,362 tests and lint passed.

Also new in October: 3D views driven by stored events, with numbers kept as text, and fund forecasts that count one round per anchor day.

Not investment advice. This describes a personal software project.

What we expected, and what happened

Read it like a code review. Each removed line is something we expected, from a plan, a spec, a README or a code comment. The added line under it is what the history shows actually happened.

Expected: A new exit rule asked whether the reason a position was entered still showed up in the daily scan. It had 15 passing unit tests.

Happened: Run against real data before it was switched on, it would have closed almost every position in its first cycle. The scans are top-N triggers that list only the highest-ranked matches, so nearly any position drops out within a few days. The rule was parked, and every change to the decision logic must now be run against production data first.

Expected: Code written the same day, with ten passing unit tests on the core function, was ready for a weekend deploy.

Happened: A self-review before the deploy found six faults, all in that day's code. A database query had never worked and failed silently, and a new sizing mode was mathematically unable to differ from its control. One behaviour test through the whole engine caught what the unit tests missed.

Expected: The original spec ran the database and queue in Docker and used a local model, through LM Studio, as its language model.

Happened: The Docker layer took the app down twice in one week, so on 8 July the database and queue moved to native services. Claude, on the subscription, is now the first choice for text, with the local model as fallback.

Expected: The rule that output must never read as advice was enforced by checking model text for forbidden words.

Happened: Substring matching rejected real text, because the Norwegian name of the Oslo exchange contains one of the forbidden words. The documented lesson is that the check must be word-based, not substring-based.

Expected: The spec said the language model should only convey what the rule engine found, never create findings itself.

Happened: Held up. Every number in the daily report is computed in code and inserted; only the analysis paragraph is written by the model.

Expected: The weekly hypothesis generator allows at most four conditions per hypothesis, and it was expected to finish its run each week.

Happened: On 4 October one suggestion from the language model had five conditions. Claude's code checked the batch as a whole, so that one suggestion stopped the entire week's run. Each suggestion is now checked on its own.

Expected: A restart guard was meant to hold back deploys only while an order could still be filled.

Happened: It also counted orders whose 'submitted' status is never updated. A day order expires at market close, but the guard kept seeing it as live, so it closed the deploy window every night after a trading day. On 6 October it held back the first self-healing deploy. It was the second time this fault class appeared in Claude's code. With no exchange open, only orders placed in the last 15 minutes now count.

Expected: The self-healing pipeline was meant to deploy unattended in a quiet window overnight.

Happened: On the night before 9 October, Claude's deploy script waited about ten hours for an administrator prompt that nobody could see, because there was no console. It now fails fast when no console is attached.

Expected: Trading costs were meant to be counted as their own line, at what the broker actually charged.

Happened: The broker's total cost figure includes the spread, which is already paid in the fill price, so the spread was booked twice. Since 9 October only the commission is booked. Henning decided to leave the paper model unchanged.

Expected: The weekly self-review was meant to suggest a fix for an exchange when the signals there were failing.

Happened: It also suggested a fix when the whole exchange had simply done worse than the rest of the market. This happened four times with the same exchange, and Claude's text claimed an automatic down-weighting. Since 11 October the suggestion is held back when bullish signals lose and bearish signals win on the same exchange, with enough measurements on both sides, and the text no longer claims any automatic action.

Expected: The day requirement added to the maturity check on 14 October was meant to stop signal sources from being judged on too few signal days.

Happened: On 17 October a dividend-based source was marked ready and judged on 20 outcomes from two signal days, the same gap the agent source had shown on 14 October. Two more sources had the gap too. Claude's fix from 14 October had not made the requirement the default. Ten signal days are now the default for every source, and the dividend source gets a new verdict around 29 October.

Expected: A 30-day damping was meant to keep the weekly self-review from bringing back suggestions that had already been dealt with.

Happened: The damping ran out on 13 October, and the self-review's threshold path had neither the history nor the critic. On 18 October five of its suggestions repeated ideas that had been rejected on 13 September or already measured on 7 October. Both the model and the critic now get the category's rejected and completed suggestions.

Expected: The self-healing pipeline was meant to close vulnerable packages within the same major version without a human.

Happened: A critical hole in the Next.js image optimizer had a fix inside the same major. The changelog says the app tried to patch it but could not get through, because the CI minutes were used up. Claude merged it by hand on 24 October, after moving CI to the app's own runner.

Expected: On 14 October the agent-based source was left undecided, and a new verdict would need ten signal days.

Happened: As planned. With ten signal days in hand, the source was rejected on 24 October.

Page history

  1. First version of this page.
  2. On 3 October 2026 the stock app moved its strategy search to its own queue after it had been blocking the broker login renewal on Saturdays, and the broker login on the simulation account became automatic. The page now covers both changes and two speed-ups that gave identical results.
  3. On 3 October 2026 the stock app's five- and ten-day measurements were fixed so they include the target day, after Wednesday signals had been dropping out; the page now covers that fix and counts 7 commits that day.
  4. On 4 October 2026 the stock app started checking each hypothesis suggestion on its own, moved a Sunday stress job into a child process, cleaned up its dependencies and kept its model settings steadier; this page now covers those changes and an updated commit count.
  5. On 8 October 2026 we added the app's new dependency self-healing pipeline, the two faults its first runs exposed, the replay test of exit variants and a holiday-aware staleness check, and shortened the older sections.
  6. 8 October 2026: added the full review that fixed 31 findings across seven layers, including a nightly trigger that deployed the main branch without being asked; shortened older sections to make room.
  7. 10 October 2026: added the follow-up to the 8 October review, a security fix in the web front end, two corrections to signal measurement and broker cost accounting, an overnight deploy that hung, and the dependency updates of 10 October; commit counts updated.
  8. On 11 October 2026 the stock app's promotion gate began checking whether gains held up over time, its self-review stopped treating an exchange-wide slump as a signal fault, and this page now counts 12 commits from 10 to 12 October.
  9. 2026-10-15: Two heavy weekend jobs moved out of the API process, and the waiting list for new signal sources gave its first two verdicts, one of them postponed for lack of data; commit count updated.
  10. On 22 October 2026 the page was updated for 15 to 22 October. It now covers a thin-sample gap that recurred in the waiting list, self-review suggestions that repeated rejected ideas, the CI quota running out, new 3D and time-travel views, and fixes to how fund forecasts are counted.
  11. On 26 October 2026 the page was updated with two security fixes merged on 24 October that the self-healing pipeline could not take, the move of CI to the app's own runner after the quota ran out, the agent source's verdict after ten signal days, and a new commit count.
  12. 29 October 2026: one documentation commit since the last update; the commit count is updated, and the page now notes that the image address behind the Next.js hole requires login.