11 KiB
11 KiB
Decisions (append-only)
Format: date · decision · why. Add at the bottom. Never edit an old entry; supersede it with a new one.
Standing rules
- Prod is the cloud instance at teahub.xyz. The Mac (hb-5) is the operator's playground and the archive of the old factory; prod never depends on it.
- No secrets on prod beyond: Gitea's own keys, the GitHub OAuth client, the MCP's OAuth client, and the seat keys listed in the ledger. Adding one is a decision.
- Every agent acts as itself (its own Gitea login). No service tokens.
- Port pieces from the old instance only when a card needs them, after reading them, one piece per commit, logged in docs/rebuild.md.
Ledger
- 2026-10-14 · Green Tea v1 is a fresh prod, not a migration. Nothing copied from hb-5 (no issues, labels, secrets, tokens). Why: the old factory was scaffolding; the rebuild is the portability test, and chai gets a box with no dev cruft.
- 2026-10-14 · GitHub-backed Gitea on Fly. Gitea stays (ownership, a place for chai to be admin); GitHub is upstream for Time and the first login. Why: Time is GitHub-native and already works; Gitea is cheap to run and keeps the sovereignty option.
- 2026-10-14 · Logins: GitHub now, nostr next. Auto-registration from GitHub; no local sign-up. Why: one click for collaborators; nostr gives agents and anyone else a key-based identity (see well-known.online).
- 2026-10-14 · Tea MCP is off the Mac. New Green Tea MCP on Fly, OAuth against prod Gitea, every tool as the caller. Why: the MCP is the product surface; it should be reachable without the operator's machine and must never outrun the caller's permissions.
- 2026-10-14 · Boring stays on the Mac. It is the operator's admin lane, not a prod component. Why: the thing that can repair prod and the thing that runs prod are different boxes with different owners.
- 2026-10-14 · Codex is not installed on prod. Seats are API-driven (Claude API, Venice); Codex on demand as a Fly Sprite. Why: no resident credentials on the runner.
- 2026-10-14 · Fly cost accepted for prod (two small apps). Same category as Venice credit.
- 2026-10-14 · Mac runners reversed. Last week's move of runners onto hb-5 is undone on purpose (portability exercise).
- 2026-10-14 · Venture loop on teahubxyz/time paused until the audit's remaining items are judged safe (3 criticals + 3 highs fixed in time#45, #46).
- 2026-10-14 · well-known.online is a separate product, not a Teahub component; may later be prod's signup front door. No dependency either way.
- 2026-10-14 · The Mac's Gitea stays, as a separate unit. The operator keeps a Gitea on hb-5 to play with customisation. It is not connected to prod: no mirrors, no shared users, no shared tokens, no DNS under teahub.xyz pointing at it beyond the archive hostname matcha.teahub.xyz (which may go). Why: Teahub and the Mac are distinct units; the Mac's job is maths and experiments, prod's job is being prod.
- 2026-10-14 · Graduated ventures are orgs on prod (persimmons, phast, phly …), treated as independent clients of Teahub with their own repos and a pages convention. Not wholesale imports; each starts from what it actually is. Why: a venture with its own domain is a client, not a folder of the factory.
- 2026-10-14 · notplanned + venture pages merge into Time's venture loop on GitHub, not into prod Gitea. Why: Time already is the venture loop; two listings would drift.
- 2026-10-14 · Scouting is plural. Time's trending-repos scout stays the first source; notplanned's curated backlog is a second source into the same pitch round; more sources can be added the same way. notplanned is not "the" scout. Why: popularity and wanted-but-unbuilt are different signals, and the loop should be able to take several.
- 2026-10-14 · The old Fly edge is down; its sites are dark on purpose.
teahub-giteascaled to zero (app kept, no machines). Dark until ported: persimmons.app, phast.app, phly.cloud, yolopreneur.lol apex/www, supertestnet.lol, notplanned., maths., 🫖, matcha.teahub.xyz. Per-venture<slug>.yolopreneur.lolWorkers are unaffected. The Mac is now reachable only over the tailnet; the last public wire into it is cut. Port order: persimmons, phast, yolopreneur apex. Why: the edge was the only thing coupling public DNS to the Mac, and nothing behind it had meaningful traffic. - 2026-10-14 · Time moves to prod. GitHub was the proof of concept. Supersedes the "GitHub is upstream for Time" clause above and the "merge into Time on GitHub" entry: the factory runs on prod Gitea, in one place, with Gitea Actions.
teahubxyz/timeon GitHub becomes read-only once the port lands; no two-way issue sync, ever (Time's state is its issue comments, and a mirrored state machine is a conflict generator). Steps: Fly runner → Gitea backend behind Time's forge module → migratetimewith issues once → flip workflows to.gitea/workflows→ archive GitHub copy. Why: Time in one repo host and Teahub in another made no sense; everything on GitHub would defeat standing up Gitea at all. - 2026-10-14 · Runner on Fly:
green-tea-runner(act_runner 5.0.0-dind, iad, shared-cpu-2x/4GB, 10GB volume holding Docker's data root — Fly's rootfs is overlay so/var/lib/dockermust live on the volume). Labelsubuntu-latest,ubuntu-22.04→node:22-bookworm. Registered instance-wide asfly-iad-1. Smoke:teahubxyz/teahub.gitea/workflows/smoke.ymlgreen. Why: Actions on prod are a precondition for Time on prod. - 2026-10-14 · Time landed on prod (
teahubxyz/timenative, migrated once with issues; port merged as time#47; GitHub copy archived with a pointer). Workflows stay in.github/(Gitea reads it). Trust = repo owner,TIME_TRUSTEDvariable, or collaborator, because the Actions token can't read permissions.venture.pyis not ported yet (time#48); venture loop stays off. Why: see the entry above; one host, no sync. - 2026-10-14 · First product secret on prod:
VENICE_API_KEYonteahubxyz/time(repo Actions secret; the same key the old factory used, taken from its delivery on hb-5, never printed). With it:TIME_WORKER=venice:qwen coder,TIME_REVIEW=venice:grok,TIME_MODE=live,TIME_AUTOMERGE=on(merges only on a trusted Approve + green CI, never on protected paths). Why: seats are the product; the operator said the key lives with Boring's deliveries, and the factory is meant to run without hand-offs. - 2026-10-14 · Pages convention:
<org>/siteis served at the org's domain bygreen-tea-pages(Fly, stdlib static host, one shallow clone per site, pull on a Gitea push webhook or every 5 min; code inpages/). Supersedes "Cloudflare Pages by default" in #2. No tokens anywhere: site repos are public and cloned over https. Why: the simplest thing that makes "a commit to site ships" true on prod itself, with nothing on the Mac and no new secret. - 2026-10-14 · persimmons and phast are ported as orgs, as they were.
persimmons/app(+ vendoredhuman_vault.py),persimmons/extension,phast/app(+acp/);persimmons/siteandphast/sitelive at persimmons.app and phast.app (certs issued, DNS moved off the dead edge). Neither app runs yet: persimmons signs in with Gitea passwords, which prod does not have (needs Gitea OAuth, like the MCP); phast's production blockers (volume, owner auth) stand. persimmons.app says so on a holding page; phast.app serves its landing. Why: the domains were dark; the code is where its owner is; the runtime seams are cards, not blockers for the port. - 2026-10-14 · Skills are vendored into the spine at
.agents/skills/, not installed per seat. First set:brag-slim(latent-spaces/brag) and six of coreyhaines31/marketingskills (product-marketing,launch,social,content-strategy,copywriting,marketing-loops);evals/left out. Both MIT. Why: seats on prod are API-driven with no home directory to install into, so the repo checkout is the only place a skill reliably exists; the factory just got dev.to and Bluesky, andmarketing-loopsis the shape Time can schedule. More skills go in the same way, by copying the folder. - 2026-10-14 · One venture ledger, at yolopreneur.lol. Time's ventures and notplanned's are one list (
ventures.json+backlog.jsonon time'sgh-pages, with asourcefield);teahubxyz/notplannedis on prod with its 4 issues; the index is hand-authored (neo-brutalist) and renders the JSON, so the generator writes data only. Supersedes the "notplanned merges into Time on GitHub" entry. Why: two listings drift, and the operator wanted one. - 2026-10-14 · Every venture is static, on Teahub pages, at
<slug>.yolopreneur.lol. No Cloudflare.*.yolopreneur.lol→green-tea-pages(wildcard cert); the apex/<slug>/redirects to the subdomain; a venture ships asventures/<slug>/ongh-pagesand nothing else is provisioned. The nine Workers (time-<slug>) and their custom domains were deleted with the Workers token on hb-5;backendis gone fromventures.json;time.jsdegrades without/api/.cloudflare.py/worker.jsleave with the venture.py port (time#48). Kept for now:time-aicharts(the lab, no static twin — rebuilds on prod per #5) andjev-prefab-decider(not Time's). D1 databases could not be deleted with that token (no D1 scope); the Workers that used them are gone, so they cost nothing but still exist. Why: one format for all sixteen, and no Cloudflare spend. - 2026-10-14 · Second product secret on prod:
ANTHROPIC_API_KEY, user-level onteahubxyz(Actions secret shared by every repo teahubxyz owns; taken from Boring's delivery on hb-5, never printed; the Gitea token used to set it was minted on the Fly box withwrite:userand revoked within minutes). With it: Time gets Claude seats (haiku,sonnet,opus,fable) through the Claude API's OpenAI-compatible layer,TIME_WORKER=claude:sonnet, and a spend governor: a ledger in the repo (time/ledger/<month>.jsonl, one line per model call with tokens and USD),TIME_DAILY_USD=5andTIME_MONTHLY_USD=100as user-level variables; a daily breach opens anandonissue and waits for midnight, a monthly breach also flipsTIME_MODEtodry-run. Venice stays wired but is no longer the worker. Why: the operator's Max plan outruns manual use and the factory should run on API credits unattended; Venice burned $20 of $75 before anyone noticed, so the cap is counted in dollars by code, not in launches, and no model decides whether to spend. - 2026-10-14 · Time is a Gitea user:
time, with its own token. Gitea 1.24 lets the Actions identity (gitea-actions) comment and label, and git-push with the task token, but never open or merge a pull request ("user must be a collaborator") or write through the contents/branches API (pre-receive denies it). So Time's writes go overgit push, and the two PR calls (open, merge) go out astime: a bot user, collaborator (write) onteahubxyz/time, token scopedwrite:repository,write:issue, stored as the repo secretTIME_TOKEN, minted on the Fly box, never printed. Operator approved. Reading of the standing rule: Time is an agent and this is Time acting as itself, not a shared service token; nothing else usesTIME_TOKEN. Also today: the daily plannerastra.py/astra.yml(one Opus call a day, queues ≤2 cards, writes to the "Astra log" issue; off untilTIME_ASTRA=on), and the first Claude-seat card, time#49, is the one that found all three Gitea walls. Why: without an identity that can hold a PR the council has nothing to review and nothing ever lands.