oll.am · Overnight Autonomous Run · 2026-06-28 → 2026-06-30 night

Core is Live. Now Every Product Lives on Core.

An autonomous overnight execution ledger. What's true, the one action that unlocks the first stranger dollar, the bigger multi-product plan, and a record of every decision made while you slept — all on feat/ branches for your morning review. Nothing deployed without you.

🌙 Tonight · 2026-06-30 night shift — both products run on local Ollama, end-to-end

The bundled-Ollama path (oll-model feat/oll-model-ollama-bundle, PR #55) is proven end-to-end for humaniz AND specview — real completions through a local model, in the browser, with Groq still the default. All in local Docker dev-test; nothing in production was touched.

What I proved (local Docker, no prod):

  • Gateway + bundled Ollama up. The oll-model gateway plus an ollama/ollama container, model qwen2.5:0.5b (397 MB) pulled. GET /api/text/health{default_provider: groq, providers: {groq: ok, ollama: ok, claude: skipped}}. Baseline direct calls: provider=ollama → a real completion on qwen2.5:0.5b; no provider → Groq (llama-3.3-70b-versatile). Groq stays the default.
  • humaniz e2e. The real humaniz backend (feat/textops-gateway-client) booted in Docker, pointed at an Ollama-default gateway, with a stub Core for auth. POST /api/v1/text/rewrite returned provider="ollama", modelUsed="qwen2.5:0.5b" — a real rewrite. Made browser-clickable at http://localhost:8090/editor (Next.js frontend, same-origin build, a dev auth-inject proxy supplies the backend Bearer, the login gate neutralized for local).
  • specview e2e. The real specview api (feat/oll-model-gateway-provider) booted against a local throwaway Postgres + the Ollama gateway (CHAIN_PROVIDER=gateway, SKIP_AUTH). The anonymous bootstrap (POST /api/ai/text/anonymous/bootstrap-project) completed through the web nginx proxy at http://localhost:8095 → api → ollama (3 gateway calls), producing real spec docs.
  • Regression — graceful. With the Ollama container stopped, Groq is still the default and works; an explicit Ollama call fails gracefully (a clean 502 {code,message,request_id} envelope, no crash). ⚠️ Worth noting: health's ollama: ok is config-based (OLLAMA_BASE_URL is set), not a live probe.

🧩 The gap this opened — neither product lets a USER pick the model yet ("any model, pay once")

Both products today default to whatever provider the gateway is configured with — a user can't choose Ollama (or any model) per request:

  • humaniz — the low-level text_client supports a provider override, but the rewrite route / humanizer / DTO never plumb it through.
  • specview — the chain gateway adapter sends only {"messages"} and drops the model param that generate() already accepts.

A user-facing model switch needs a small additive change in each. Two PRs are open for morning review (open, not merged, nothing deployed): (a) humaniz PR #14 (feat/textops-provider-select) — user-selectable provider/model through the rewrite path; 78 tests pass, ruff clean; base feat/textops-gateway-client. (b) specview PR #125 (feat/chain-provider-forward) — forward model/provider through the chain gateway adapter; 61 chain tests pass, ruff clean; base feat/oll-model-gateway-provider.

🚀 Deploy prep — the gateway needs only 2 secrets at deploy. A run-it-top-to-bottom deploy card is ready for when you ship the gateway (see the platform architecture). Code-verified — a default (groq) deploy needs exactly two secrets (OLL_MODEL_SERVICE_TOKEN + GROQ_API_KEY); everything else has a prod-correct default and stays unset. Coolify app config + the one-time deploy gate + three curl smoke tests are all in the card.
🌃 Night-shift note. A self-firing cloud cron isn't viable for this work — the only available environment is anthropic_cloud, which has no access to the local ~/Projects repos. So the night shift runs in-session as PR-only work: every change lands on a feat/ branch as a PR for morning review, nothing deployed.
☀️ Morning brief — through Jun 30 (night shift). Both products advanced + verified by running this shift; the gateway is LIVE. What's left for the first franc is a short list of merge / console actions (mine to build + verify, yours to click). Sections below are the historical record.
✅ Done + verified this shift (all reversible — every change is a feat-branch PR, nothing I deployed):
  • humaniz Core-lift Phase 2 VERIFIED — the Next.js frontend's Core migration (magic-link + Bearer + nginx auth-split) was already merged (PR #7); I closed the verify-by-running gate with a full GUI round-trip in Docker (nginx :8099 → backend → oll-model gateway 200 → model → rewrite; /editor loginless).
  • foto real LoRA pipeline → PR #48 (CI green) — lifted verbatim from wardrobai: pinned ostris trainer hash, per-order destination model, sample the trained version directly. The empty-TODO model ids are now real. Verified no-spend (45 pytest + mocked-SDK wiring, docker boot, ready:true). Re-verified deploy-ready (06-30, fresh build+run): 47 pytest green · docker build + boot → /api/foto/health 200 · checkout & fulfill return clean {code,message,request_id} envelopes (no crash) · container stays healthy. The live round-trip pinpoints the one blocker: foto checkout → core.oll.am/api/billing/guest-checkout-session = 404 ⇒ foto's code is done; it just needs PR #21 (Core guest-checkout) merged + deployed to Core. No new build needed on foto.
  • Honest provider on humaniz — the response no longer hardcodes ANTHROPIC; it reports the gateway's real provider/model (verified: the round-trip returns ollama/llama3.2). On both humaniz branches (cleanly on the mergeable #9).
  • oll-model gateway LIVE at model.oll.am (you deployed; verified groq:ok, authed /complete, 401) · humaniz #9 GREEN + mergeable · foto results-email #46 merged · deploy control #45 + oll-model CI gate #47 ready (both green).
🔀 Merge-queue checked (Jun 30): the franc PRs are clean + mergeable — oll-am #48 (foto LoRA), #21 (Core guest checkout), #45 (gated deploy), #47 (oll-model CI gate), and humaniz #9 (gateway client + honest-provider). ⚠️ Only oll-am #30 (Core billing /status self-heal, off the critical path) has gone conflicting as main advanced — it needs a rebase before merge.
⛳ Your queue (ordered, dependency-aware) — the first franc:
  1. Writing franc (humaniz): set OLL_MODEL_SERVICE_TOKEN on the humaniz backend (base defaults to model.oll.am) → merge humaniz #9 (it now also carries the honest-provider fix) → redeploy. This runs humaniz keyless on Groq AND un-breaks the 503 (the deployed #8 crash-loops on the removed ANTHROPIC_API_KEY; #9 needs no key). Then frontend build var NEXT_PUBLIC_API_URLempty + rebuild.
  2. specview api:specview #122 is now MERGED (the reactive-billing fix greened its CI — no admin-override needed). Remaining: set OLL_MODEL_BASE_URL=https://model.oll.am + the token on the specview api app → redeploy → kills the claude CLI error. ✅ #122 is admin-merge-safe (now confirmed by running): its red is a pre-existing test-isolation flake — the billing self-heal test passes 25/25 in isolation and only fails in CI's full-suite order; the gateway code is unaffected (evidence on the PR). Follow-up (CI-env only): make that test hermetic.
  3. Headshot franc (foto, product #2): create the LIVE Stripe webhook (core.oll.am/api/billing/webhook + STRIPE_WEBHOOK_SECRET) · review+merge Core guest-checkout #21 · merge foto #48 (real LoRA, CI green) · set a real REPLICATE_API_TOKEN for one true train+sample · a .ch domain + deploy foto. ⚠️ Still to build (next fire): a foto photo-intake/upload endpoint — checkout currently takes input_photo_urls directly, so a guest has no way to upload selfies yet (the one real code gap before foto can take a dollar).
  4. Deploy hygiene: Coolify Watch Paths per app + merge #45/#47 with the secrets/flags. Steps.
  5. Distribution: the franc surface is built — submit the directory kit · post · decide pricing.
Live picture: Control Room · gateway runbook · Timeline.
📜 Historical (2026-06-28 overnight run): this page is the original status ledger. Goal ordering: Goal 1 = lift the Core out of existing products so they depend on core.oll.am like specview does — humaniz.me (now done). Goal 2 = a new oll.am photo service built FROM trendfy's pipeline (not a repoint). speedback removed from scope.

🌙 What shipped tonight — 2026-06-30 night shift

"Any model, pay once" is now user-selectable on the money-path product, end to end — built, tested, and adversarially reviewed = all ship.

🧩 Product feature — model picker, end to end (3 PRs):

  • humaniz PR #14 (feat/textops-provider-select) — backend threads an optional provider/model through the rewrite path; 55 tests. Base feat/textops-gateway-client.
  • humaniz PR #15 (feat/textops-provider-select-ui) — editor UI: a "Model:" dropdown (Default cloud / Cloud Groq / Local Ollama); tsc + lint + build + vitest green (16 tests). Stacked on #14.
  • specview PR #125 (feat/chain-provider-forward) — forwards model/provider through the chain gateway adapter; 29 tests. Base feat/oll-model-gateway-provider.
  • specview PR #127 (feat/chain-provider-select, base feat/chain-provider-forward, stacked on #125) — adds the gateway-only guard (closes the latent non-gateway TypeError edge) AND exposes optional provider/model on both bootstrap routes (authed + anonymous) with an allow-list {groq, ollama, claude} and a clean 400 on unknown; 332 tests pass, ruff clean, OpenAPI valid. spec-gen RETRY-path threading deferred as a noted follow-up.
  • Merge order: humaniz bottom-up — feat/textops-gateway-client#14#15; then specview's own stack bottom-up — feat/oll-model-gateway-provider#125#127.
  • Net — both products are now SYMMETRIC on "any model, pay once" / user-selectable provider: humaniz (#14 backend + #15 UI), specview (#125 adapter + #127 routes+guard).

🧪 Dev-tested gate — oll-am PR #56 (feat/e2e-model-path, base stage): scripts/e2e-model-path.sh + docker-compose.e2e.yml. A repeatable harness that boots gateway + Ollama in isolation and asserts the full contract — health (groq + ollama) · ollama completion on qwen2.5:0.5b · groq default · auth 401/403 · ollama-down → groq still serves + explicit ollama → clean 502. Ran twice: 16 passed / 0 failed → DEV-TESTED GATE: PASS. This is the candidate automated gate for the stage→main auto-promote plan. Caveat: based on PR #55, so its diff rides #55 until #55 lands on stage (#55 already auto-merged to stage).

🔍 Adversarial merge-readiness review on all three feature PRs returned ALL SHIP, no blockers: default/omit paths byte-for-byte unchanged, validation correct, backward-compatible signatures, no secret / SDK-boundary / error-envelope regressions. One carry-forward → now CLOSED: specview's adapter.generate(provider=…) would TypeError if a route passed provider while CHAIN_PROVIDER is non-gateway — the follow-up landed as specview PR #127 (the gateway-only guard) in the same change that exposes provider/model on both bootstrap routes.

🚀 Deploy prep — the oll-model live deploy card (documented in the platform architecture) stands: the gateway needs only 2 secrets at deploy; live smoke-test curls included. 📣 Distribution (P1) — a DRAFT build-in-public share kit is ready for review (not posted).

The night-shift milestone is complete to the autonomous boundary — everything buildable/testable as PR-only work is built, tested, reviewed, and stacked. What remains is yours: console moves (merges + deploy) and a few greenlight calls.

⛳ Waiting on Sam (console): merge the stacks bottom-up (humaniz: feat/textops-gateway-client → #14 → #15; specview: feat/oll-model-gateway-provider → #125 → #127) · arm the oll-model deploy gate (DEPLOY_MODEL_ENABLED + COOLIFY_HOOK_MODEL) + set the 2 secrets · run the deploy-card smoke tests · ship · and decide the auto-promote trigger (label vs button) + whether merge-to-main auto-deploys armed services.
🟢 Greenlight queue (your call, then I execute): wire oll-am #56 as a CI dev-tested gate · extend the e2e harness to the humaniz product path · build the specview UI provider picker + thread provider/model through the spec-gen retry path.

⛳ The morning path to the first stranger dollar — two reviews, both teed up

1 · Create the LIVE Stripe webhook at core.oll.am/api/billing/webhook + set STRIPE_WEBHOOK_SECRET (console, ~3 min) → unlocks the existing CHF 9 Pro link.

Why: Core is live and the price is set, but without the webhook a payment succeeds while the plan never flips to pro — the customer pays and gets nothing.

Exact setup (avoids the wrong-events footgun): in Stripe → Developers → Webhooks → add endpoint https://core.oll.am/api/billing/webhook, select these 6 events Core actually handles — checkout.session.completed · customer.subscription.updated · customer.subscription.deleted · invoice.payment_succeeded · invoice.payment_failed · invoice.upcoming — then copy the signing secret into Coolify env STRIPE_WEBHOOK_SECRET and redeploy Core. Verify: curl https://core.oll.am/api/health/stripeok, then send a test event from the Stripe dashboard → expect 200. (Keep the old test-mode webhook until a real live event proves on Core.)

2 · Review + greenlight + merge PR #21 (additive Core guest-checkout) → deploy Core → the CHF 49 headshot (foto-service) can sell with no login.

PR #21 is built, additive (existing routes untouched, 0 deletions), and security-reviewed: a review caught a money-path underpayment bug (product-slug/price-fallback) which is now fixed and tested on the branch — strict product validation + a guest-only price lookup with no Pro fallback; 203 tests, contract + ruff + DTO-drift all green. Documented follow-ups for you (in the PR): set STRIPE_WEBHOOK_SECRET in prod, and the app-wide rate-limiter hardening (ProxyFix + Redis). It's NOT merged — your call.

Also review: PR #20 (this overnight work: foto-service scaffold + de-staled docs) and PR #18 (C2). Branch tangle: merge #18 only — standalone-services + deploy-topology would re-break live Core (see below).

🚧 ACTIVE BUILD — humaniz.me lift-shift (Goal 1, the specview playbook)

Sam's immediate goal: do for humaniz.me what we did for specview — make it a thin client of the live core.oll.am (delete its Supabase auth + Stripe + email; route those to Core; keep the Claude humanizer). It's authed → no PR #21 needed.

✅ CODE-COMPLETE — humanize-me PR #7 (not merged/deployed). Phase 1 (backend): ported services/write/ adapters byte-identical, deleted Supabase auth + Stripe, kept the Claude humanizer, re-aimed prompts. 60 tests · docker build · curl green. Phase 2 (frontend): Next.js swapped to Core magic-link + Bearer (specview's flow in React), nginx auth-split → core.oll.am, pricing→Free+Pro. npm run build exit 0 · eslint clean · vitest 14 · supabase/detector-bypass greps clean.

✅ Local round-trip PASSED (full stack via docker compose, real nginx proxy, both containers healthy): GET / Next.js 200 · GET /api/health → backend 200 · GET /api/auth/me no-token → proxied to live core.oll.am → 401 (the split works over TLS) · product route returns the unified {code,message,request_id} envelope. Each service also independently build+test verified.

✅ FULL magic-link round-trip verified (local). Stood up a local Core with humaniz registered + repointed the running stack at it: via :8099, magic-link {product:"humaniz"}{sent:true}; /login + /auth/verify pages 200; authed routes 401 without a token. Confirmed the INVALID_PRODUCT you hit is purely Core config, not a humaniz code bug — an unregistered product 400s, a registered one passes.

✅ Login UX bug fixed (PR #7, bc83d70). Sam's live test surfaced two real Core-integration bugs in the frontend: after magic-link verify the header needed a manual refresh, and the redirect bounced to /login?redirect=/editor. Root cause: the verify page used a client-side router.replace that served the /editor route prefetched before the cookie existed and didn't re-run useAuth. Fixed with a full-page window.location.replace(dest) (honors ?redirect=). Verified by running: docker build/lint pass; /editor no-cookie → 307→/login, with oll_token → 200, no bounce.

Money loop (in-app) also proven via stripe listen → local Core: checkout.session.completedplan_write free→pro + welcome email.

🐛→✅ BLANK-PAGE-AFTER-PAY FIXED + VERIFIED (2026-06-29). Sam's live test: paying on remote humaniz redirected to http://localhost:8095/upgrade (blank). Two layers, both fixed: (1) host — Core hardcoded success_url={FRONTEND_URL}/upgrade (= specview's :8095); oll-am PR #22 resolves the base per-product. (2) path — humaniz had no /upgrade route; humaniz PR #8 adds a success page that polls Core's live status until the webhook flips the plan. Proven by build+run+curl+docker (PR #22 image on real Neon oll_core + Stripe test): product=humanizsuccess_url=https://humaniz.me/upgrade?session_id=… ✅; product=oll_pro (control) → http://localhost:8095/upgrade unchanged (backward-compat). humaniz already sends product:'humaniz' in its checkout call. Both PRs are CI-green and additive — awaiting Sam's merge + redeploy (then live Stripe price/keys). Item (3) product-route-validates-before-auth (400 vs 401) is a cosmetic follow-up. Rewrite/AI (model 404) parked per Sam.

Decisions awaiting you — each with my recommendation, so it's a one-tap call

DecisionOptionsMy recommendation
foto results-ready email
(the last foto gap)
A) foto-owned Resend sender for the results email · B) a Core guest-results endpoint guarded by a service token A — foto-owned Resend. The results email fires after async generation, which Core's webhook can't carry, and Core's /email/send is deliberately recipient-scoped. Option B widens Core's auth surface (a new service-token path to review) to send mail to arbitrary guests. A keeps Core frozen + as-reviewed; the small "product has email code" exception is justified because this one email is genuinely a product concern. Revisit B only if 2+ products need post-purchase email.
Billing model
(blocks 3 of 4 products)
A) pay-once grants · B) subscriptions · C) both A — pay-once. It matches the public positioning ("pay once, no subscription"), foto's one-time CHF 49, and the landing's CHF 9. Core already supports Stripe mode=payment; entitlement for a one-time buy is a grant, not a recurring plan. the humaniz braindump assumed monthly — start pay-once anyway (simpler, on-brand) and add subscriptions later only if usage/churn data demands it.
photo service from trendfy's pipeline A) new oll.am-native service harvesting trendfy's LoRA engine · B) one-to-one repoint of trendfy.me A — new native service (your call, 2026-06-29). Build oll.am's first native photo service FROM trendfy's pipeline (foto/headshots is its first cut); do NOT repoint the trendfy.me product. trendfy stays alive via PR #16 while its engine is harvested. This is next-next, after the humaniz lift-shift.

These are reversible, low-stakes calls — pick the recommendation (or override) and I'll execute the build. The two irreversible/console actions (live webhook · greenlight PR #21) stay with you.

Where we really are — ground-truth, code-verified tonight

The docs had drifted behind reality. Here is what's actually true, verified against the live service and the git tree.

ThingStatusEvidence
Core deployed at core.oll.amLiveGET /api/health → HTTP 200 {"status":"ok"} over HTTPS (TLS already on)
C2 — specview on the remote CoreProvenspecview nginx.core-split.conf already proxies to https://core.oll.am; PR #18 handover says "C2 proven"
First-dollar money pathNeeds SamLive Stripe webhook missing — see the callout above
Branch tangleDriftedPR #18 (CONFLICTING) + feat/standalone-services (+25) + docs/deploy-topology (+19); local main diverged from origin/main

The drift is just state.json/build-log.html churn colliding across branches — not lost work. The consolidation section below (filled from a recon agent) gives the safe morning merge order. I did not attempt risky git surgery unattended.

✅ Verified green (overnight close-out)

All tests + CI confirmed: foto-service 19/19, write-service 20/20, PR #21 Core 203 (contract + ruff + DTO-drift). Product-services CI green on GitHub (foto · pytest + write · pytest SUCCESS — the scaffolds now gate PR #20). PR state: #21 MERGEABLE, all CI green (hardened) · #20 MERGEABLE, green · #18 CONFLICTING on churn files only (merge first; take origin/main for state.json + build-log.html). Site design gate green (50/50 pages). Core live probe: HTTP 200.

The bigger picture — the thesis, now executable

Core stopped being a plan tonight and became live infrastructure. That flips the whole program: the remaining work is no longer "build Core" — it's "point everything at Core." Every product Sam has shipped carries its own duplicated auth, billing, and email. Core deletes all of that, once.

https://core.oll.am ── FROZEN INFRASTRUCTURE (auth · billing · email · health) ── ▲ ▲ ▲ ▲ │ │ │ │ every product calls Core over HTTP; │ │ │ │ ZERO auth/Stripe/email code of its own ┌────┘ ┌──┘ ┌──┘ └────┐ foto-svc write spec humaniz / trendfy (headshot)(humaniz)(specview.dev) ... NEXT $ then $ then $ then $

Each product becomes ~50–200 lines of product logic. The pattern proven by specview (C2) is now copy-paste for the rest. The sequencing stays revenue-first: the headshot product (foto-service) is the next dollar because it's closest to cash — guest checkout, no login, email delivery. After it, the existing live products migrate one by one.

Overnight execution ledger — updated each wake cycle

This is the live record of the autonomous run. The session re-wakes via workflow completions + a :09/:39 "continue overnight" cron, working this queue until rate limits hit. Everything lands on feat/overnight-multiproduct-core as commits/PRs.

#TaskStatusOutput
0De-drift: verify Core live, sync state.json, capture directive in memoryDonestate/state.json, memory overnight-autonomous-run
1Stand up persistence + self-sustaining loop (3 crons)Donecrons: :47 commit+push · :37 digest · :09/:39 continue
2Recon: per-product Core-migration briefs + branch-consolidation analysisDone5-agent workflow → filled the two sections below (incl. the live-Core regression warning)
3This ledger page (visible decisions)Livesite/oll-am-overnight-plan.html
4Scaffold foto-service (next-dollar headshot) on CoreBuildingservices/foto/ — Core client + Replicate boundary + SQLite jobs + tests (agent in flight)
5Dev test: live Core + guest-checkout feasibilityDoneCore health/neon/stripe all 200; verdict: guest checkout needs a small Core guest-endpoint pair (see foto section)
6Docs cleanup: link every page to the timeline (no orphans)Donerender_index → 46 pages categorized, 0 Unfiled
7Migration playbook (specview reference + skill library)Donesection below — every migration mapped to a house skill
8Scaffold foto-service + run its testsDoneservices/foto/ committed · 12/12 pytest green
9Core guest-checkout PROPOSAL (additive, not merged) → PR #21Readyadditive guest-checkout-session + guest-verify-session + webhook-driven guest email; existing routes untouched; 194 tests (+19), ruff + contract + Schemathesis + GitHub CI all green. Awaiting Sam greenlight.
10Adversarial review of the foto scaffold → fixes applied + testedDonefixed: idempotency race (atomic claim), HTTP error codes, wildcard CORS; 16/16 tests (was 12). 3 blockers are Core-side (guest endpoints). foto-service page
11New skill: guest-checkout-grantDoneno-login one-time-sale pattern + the 4 gotchas, in ~/.claude/skills/
12Core Client Kit standard (frontend half of a Core client)Donepage — generated client + 3 interceptors, grounded in specview's real code; the recipe every product frontend copies
13trendfy 504 diagnosis (read-only)Doneboot-hang on suspended Neon; console revival + crash-proof PR documented above; corrected a false "burned key" claim (nothing committed)
14Doc fact-check → 21 pages de-staled to current realityDonereality banners + fixed "guest-checkout-works-today" residue + api.oll.am→core.oll.am; gate green
15Wire foto-service to the PR #21 guest contractDoneguest endpoints + job_id-via-success_url correlation (dropped fragile cs_-parse), payment gated on paid; 19 tests. Remaining gap: results-ready email (recipient-scoping).
16write-service scaffold (humaniz → authed product pattern)Donethin Core client: Bearer → Core /me → plan-gate → Claude (llm-call-contract); honest-writing positioning enforced; 15 tests. Both Core-client patterns now exist (foto=guest, write=authed).
17Adversarial review of write-service → fail-open auth fixedDonereview found get_me served stale pro on a Core 401 (cancelled user keeps pro). Now fails closed on 401/403 (evict+raise), serves stale only on real outages; +5 tests (20/20).
18Adversarial review of PR #21 → HIGH money-path bug found → FIXEDDoneH1 (underpayment via slug-mismatch + Pro-price fallback) fixed: strict product ^[a-z0-9_]+$ DTO + guest-only price lookup that raises (no fallback). Additive, authed path untouched; 203 tests (+9), contract + ruff + DTO-drift green. M1/L1-L3 documented in the PR for Sam.
19trendfy boot-resilience PR → trendfy PR #16 (crash-proof the 504)Donenon-fatal init_db + connect_timeout(5s) + $PORT + stdlib HEALTHCHECK; migrations gated behind RUN_MIGRATIONS=1. Verified: boots ~11s bounded (not hanging) against an unroutable DB, health 200, degrades. 49 pass / 3 fail (3 pre-existing on master). Additive, not merged. Deploy note: set RUN_MIGRATIONS=1. Still need the console revival (wake Neon + redeploy).
20CI for the product services (gates fail the build)Done.github/workflows/services.yml — matrix runs foto + write pytest on services/** changes, so the scaffolds' tests now gate PR #20 (the house executable-arch-rules pattern).
21Re-review foto (post-rewire) → BLOCKER fixedDoneThe guest rewire was unreviewed; review caught a revenue exploitfulfill trusted only paid, so a CHF 1 waitlist session could fulfil a CHF 79 order (Core's guest-verify has no ownership gate). Fixed: bind session→order by product+plan+guest+amount+currency; +session-reuse guard + IntegrityError recovery (no stuck-job 500); input cap + MAX_CONTENT_LENGTH; conn-leak. 20 tests (+ exploit regression test).
22Sam-gated: spec-service · foto results-email fork · pay-once-vs-subscription · trendfy standalone-vs-bublsAwaiting Samneed your decision/console (recommendations above)
13Morning verification kit + green gate + PRLivechecklist below · PR #20
26ADR-020 pattern promoted to the llm-call-contract skillDoneIdle-budget invested in tooling, not repo churn: encoded the proven provider-switch + provider-aware boot-gate + single-SDK-boundary executable-rule (from PR #29) into the reusable skill so future text products inherit it. No repo PR (skill library only). Re-verified the gated path unchanged (#22 + humaniz #8 OPEN, /upgrade 404).
27humaniz Core-lift GUI round-trip — VERIFIED in Docker (frontier a)DoneFrontend Core migration (magic-link+Bearer+nginx split) was already merged (PR #7) → Phase 2 code-complete; closed the verify-by-running gate. Repaired the bit-rotted keyless devtest stack (removed-worktree + old text-ops name → now self-contained against the current services/oll-model + an in-repo stub). Green end-to-end: nginx :8099 → backend /api/v1/text/rewrite (DEV_AUTH, no login) → gateway POST /api/text/complete 200 → model → marked rewrite; /editor loginless. humaniz feat/dev-auth pushed (ff7d8d9). Found (follow-up): backend hardcodes provider:"ANTHROPIC" though the gateway owns the provider — text_client.complete() should surface the gateway's provider/model.
28foto real LoRA pipeline lifted verbatim from wardrobai (frontier b)DonePR #48. foto's replicate provider was a guessed 3-id shape with EMPTY model ids (spec gap); lifted the working wardrobai/server/services/{training,generation}.py verbatim: pinned ostris/flux-dev-lora-trainer hash, per-order private destination model (idempotent), trainer input byte-for-byte (zip→1024 via Pillow, steps=2000/rank=16/adamw8bit/lr=0.0004/autocaption), and the SAMPLER is the trained version itself (LoRA baked in — no separate base model, the core mis-shape fixed; guidance_scale corrected 7.5→3.5). Guard unchanged (mock default). Verified no-spend: 45 pytest incl. mocked-SDK verbatim-param wiring, ruff clean, docker build (Pillow) + boot healthy tokenless, real provider ready:true. Core untouched. Sam to take the first foto franc: merge PR #21 (guest checkout) + set a real REPLICATE_API_TOKEN for one true train+sample + a .ch domain/deploy.
29Honest provider — humaniz reports the real model, not ANTHROPIC (frontier c)DoneClosed the follow-up from #27: the rewrite/generate response hardcoded provider:"ANTHROPIC" though the oll-model gateway now owns the provider switch. Fixed additively (text_client Completion + complete_meta(); complete() a str shim so streaming is untouched; create_message_meta(); humanize_single/_multipass return the gateway meta; 3 response sites report the real provider/model; cache hit → oll-model/(cached)). Verified by build+run+docker: 74 pytest + ruff green; GUI round-trip now returns provider:"ollama", modelUsed:"llama3.2" (not ANTHROPIC). Landed on both humaniz branches — cherry-picked cleanly onto the mergeable #9 (OllModelError naming, 68 pytest green) + #10.

Decisions I made tonight — clear & visible, per your ask

  1. No risky git surgery unattended. PR #18 is CONFLICTING and three branches overlap. Auto-merging conflicts while you sleep is hard to reverse, so I left it for your review and produced a safe consolidation order instead.
  2. Net-new scaffolds over edits to live/frozen code. All overnight work is new files (services, docs) on a feat branch — Core stays frozen, nothing live is disturbed.
  3. foto-service is the first build target, ahead of migrating existing products — it's the next dollar (guest checkout, no login) and validates the product-on-Core pattern for net-new builds.
  4. Single consolidated HTML deliverable (this page) rather than scattered files, per your stated preference — it doubles as the live ledger.
  5. Self-sustaining loop via crons + workflow notifications so the run keeps consuming rate budget overnight without a human in the loop, but every output is gated (design-audit + CI) and PR'd, not pushed live.

Per-product migration briefs — from a 5-agent recon, code-grounded

Each live product carries its own duplicated auth + billing + email. Core deletes that, once. Below: what's actually in each codebase, what Core replaces, the effort, and the path to its next paying customer. Order = revenue-proximity.

ProductCodeToday (auth · billing · email)EffortNext-$ path
foto-service
headshots (.ch)
landing 85% (Bewerbungsfoto/) + pipeline reused from wardrobai/serverown JWT (dropped — guest) · own Stripe (guest /checkout/public) · own ResendM-LNEXT dollar — landing live → CHF 49 guest checkout via Core → Replicate LoRA → Core emails photos
trendfy.me
AI fashion shoots
local: 2026/wardrobai (remote trendfy.git)— (pipeline donor, not repointed)next-nextits LoRA engine → oll.am's first native photo service (not a one-to-one repoint); kept alive via PR #16 while harvested
humaniz.me
honest writing tool
2026/products/humanize-meSupabase auth · Stripe 4-tier subs · Supabase emailsM-Llargest TAM; free tier → Core checkout unlock; honest-clarity framing only

foto-service — the next dollar (build in progress tonight)

The LoRA pipeline already exists and works (13+ models trained) inside wardrobai/server. The job is mostly delete auth/billing/email + wire 3 Core HTTP calls + guest gating + deploy. Flow: landing → CHF 49 tier → Core checkout → success_url returns to upload → Core verify-session gates it → upload 5-15 selfies → Replicate trains + generates → Core email/send delivers. A background agent scaffolded services/foto/ tonight (thin Core client + Replicate boundary + SQLite job store, all house-pattern).

🚩 Decision you must make — frozen Core needs ONE small addition for the next dollar

A code-level investigation (read core/modules/billing line-by-line) gives a definitive verdict: Core as deployed cannot do guest checkout. Both create-checkout-session and verify-session are @require_auth (401 without a JWT); verify-session is ownership-locked (403 on mismatch) and returns only {plan, payment_status} — no buyer email/metadata; the webhook no-ops when metadata.user_id is absent (a guest has none). Good news: one-time payment mode already works (plan:"one_time" → Stripe mode=payment, price STRIPE_PRICE_HEADSHOT_CHF49_ONE_TIME). The blocker is purely identity.

Minimal fix (bounded, ~1 route pair): add guest variants on a feat/ branch — POST /api/billing/guest-checkout-session (no auth; takes email + per-product-allowlisted success_url/cancel_url; sets customer_email + metadata.guest=true, no client_reference_id) and GET /api/billing/guest-verify-session (no auth/ownership; returns paid, email, amount_total, metadata). Guest email is delivered from the webhook via the email service layer (sidesteps the HTTP route's recipient scoping — no auth surface widened).

✅ Built as PR #21 (additive, NOT merged): 194 tests (+19), ruff + contract + Schemathesis + GitHub CI all green; existing authed routes byte-for-byte unchanged. Your move: review + greenlight + merge PR #21 → deploy Core → foto-service can sell.

trendfy.me — pipeline donor for the photo service (not a repoint)

Decision (Sam, 2026-06-29): we do not repoint trendfy.me one-to-one onto Core. Instead its proven LoRA engine becomes oll.am's first native photo service (foto/headshots is its first cut) — next-next, after the humaniz lift-shift. trendfy.me stays alive via PR #16 while its pipeline is harvested.

trendfy 504 — diagnosed (un-break before anything)

Backend is down with a 504. Most likely a boot hang on a suspended/unreachable Neon DB: create_app() calls init_db() synchronously and psycopg2.connect has no connect_timeout, so against autosuspended free-tier Neon it hangs forever (a hang gives 504, not the 502 a fast crash would). restart: unless-stopped makes it loop, never self-healing.

Console revival (Sam, ~5 min): read the server logs in Coolify; wake/repoint the Neon compute behind DATABASE_URL (update the env if creds rotated); confirm the other env (REPLICATE_API_TOKEN, ANTHROPIC_API_KEY, etc.); redeploy → watch for "DB pool initialised" + a 200 on /api/v1/health. Follow-up PR (crash-proof): non-fatal init_db + connect_timeout, gate migrations out of import, add $PORT + a HEALTHCHECK — the exact hardening already proven on Core. Secrets: nothing is committed (.env is gitignored, never in git history; the local Stripe key is sk_test_, not live) — no rotation forced.

The LoRA pipeline is confirmed clean to port to foto-service: services/{generation,training,profile,prompts,pipeline}.py + storage/ are framework-agnostic ("no Flask"); auth/billing/email stay behind and come from Core.

humaniz.me — biggest TAM · repo found at 2026/products/humanize-me

Repo located: 2026/products/humanize-me (remote humanize-me-clean.git) — a full app (backend + frontend + supabase + contracts + docker-compose), so the migration is fully groundable (Supabase auth, Stripe subs; keep the Flask+Claude rewrite logic → becomes write-service). Hard ethics constraint: the braindump leans on detector-bypass framing (Turnitin/GPTZero); every line of copy must be re-framed to honest writing-improvement only. Next: audit the repo, then apply the write-service template.

Cross-cutting decision you'll need to make

Billing model: Core's entitlement is plan-from-/me (subscription-shaped), but oll.am's public positioning is "pay once." trendfy sells a one-time photoshoot; the humaniz braindump assumes monthly subs. Decide once: does Core express a one-time purchase grant, or do products keep purchase-grant logic while Core owns only checkout/webhook? foto-service hits it first (guest one-time CHF 49).

Branch consolidation — safe morning order — read-only analysis, no merges performed

⚠️ Do NOT merge two of the three branches — they would re-break live Core

feat/standalone-services and docs/deploy-topology forked from old main (pre-PR #10). Merging either would silently revert the deploy fixes that made Core go green: core/Dockerfile loses the $PORT bind + HEALTHCHECK (the Coolify 502 fix, 9ea90a1) and health.py re-adds the stripe Balance.retrieve(timeout=5) kwarg main deliberately removed (34596f2). Their big diffs are mostly illusion — churn + false "deletions" of scripts main added later.

BranchReal unique valueAction
feat/c2-core-split
(PR #18, +12)
3 new doc pages (env-secrets · magic-link-routing · specview-core-cleanup) + a real core/.env.example rewrite. Touches no core/ code — zero regression risk. Forked from recent main.MERGE 1st — resolve 3 churn conflicts (take origin/main for state.json + build-log.html; reconcile handover.html prose)
feat/standalone-services
(+25)
Only ~3 real commits: per-service Dockerfiles, Coolify deploy guide, site/→landing/ rename. The rest is churn or already in main.DON'T MERGE — re-author those 3 commits FRESH on current main during the foto-service phase, then abandon
docs/deploy-topology
(+19)
Exactly ONE unique commit b6d5d82: a deploy-topology brainstorm page. Strict subset of standalone otherwise.ABANDON — optionally cherry-pick b6d5d82 onto a fresh branch if the brainstorm is worth keeping

Safe morning sequence: (1) merge PR #18, resolving the 3 churn conflicts; (2) optionally cherry-pick b6d5d82; (3) abandon docs/deploy-topology; (4) leave standalone-services unmerged, harvest its 3 infra commits fresh later. origin/main (ff20fbe, PR #19) already has the Core lift, contract slice, and all deploy fixes — it is the source of truth.

Migration playbook — specview is the reference, the skills are the steps

We don't invent each migration. specview already became a Core client (C2), and the house skill library encodes every move as a reusable, gated procedure. Every product migration is the same spine: prove the seam the way specview did, applying these skills in order.

Migration concernHouse skill to applyspecview reference (the proof it works)
Carve the slice out of a monolithextract-service-from-monolithCore itself was lifted out of specview; specview became its first HTTP client
The frozen API seam + typed clients + drift gatecontract-first-apicore/openapi.yaml → generated DTOs + TS-Angular client + Schemathesis CI gate
Auth over HTTP (Bearer, not cookies)jwt-bearer-spine + magic-link-authspecview's auth.interceptor.ts + Core @require_auth; trendfy already decodes the same JWT shape
Entitlement = identity in token, plan from /metoken-identity-not-entitlementCore JWT carries only sub+email; plan read live from /me
Billing: checkout + webhook + return pagestripe-billing-wiring · inbound-webhook-handler · checkout-return-pageCore owns Stripe; specview calls create-checkout + verify-session
Transactional email via Coretransactional-email + http-service-adapterCore /email/send (Resend behind one boundary)
Web-vs-native API hostenv-injected-base-urlsame build → same-origin /api on web, absolute origin on Capacitor
The nginx split (product vs Core)(specview pattern)nginx.core-split.conf — auth/billing/email → core.oll.am, product → local API
Uniform errors + observable side-effectserror-envelope + audit-outcome-loggingCore's {code,message,request_id} envelope
A realistic test DB without risking prodneon-fork-for-local-testingCore runs on oll_core, forked from prod
Product LLM calls (e.g. write-service)llm-call-contractClaude is the house LLM; prompts as constants, JSON contract, truncation caps

The foto-service scaffold built tonight already follows this: a single core_client.py boundary (http-service-adapter), a replicate_client.py boundary, an {code,message,request_id} error envelope mirroring Core, and a SQLite job store (local-first/filesystem per the data decision — Neon is Core-only).

Morning verification & dev-testing kit

Work this top-to-bottom when you wake:

  1. Unlock first dollar (console): create the live Stripe webhook → core.oll.am/api/billing/webhook, set STRIPE_WEBHOOK_SECRET in Core's Coolify env, redeploy Core.
  2. Verify Core live: curl https://core.oll.am/api/health → expect {"status":"ok"}.
  3. Smoke the money path: from oll.am, run the CHF 9 Pro link end-to-end with a real card; confirm the plan flips to pro (this is what the webhook enables).
  4. Review overnight PRs: the feat/overnight-multiproduct-core PR (this page + scaffolds) and any service-scaffold PRs.
  5. Resolve the branch tangle using the consolidation order above.
  6. Dev-test foto-service locally against Core once its scaffold lands (run instructions ship with the PR).

Guardrails honored

oll.am · Overnight autonomous run · this page is regenerated as the run progresses · Live status · Build log