Port venture.py to Gitea (pages convention, trust, search) #48

Open
opened 2026-10-14 07:00:44 +00:00 by teahubxyz · 13 comments
Owner

time.py runs on prod (#47). venture.py is still GitHub-shaped and is not wired to run here (TIME_VENTURE unset; venture.yml disabled).

What it needs:

  • per_page → limit; "pull_request" not in i → not i.get("pull_request"); author_association → tm.trusted(login); user.type == "Bot" → login == tm.TIME_BOT; /git/ref/heads + /git/refs → /branches; reactions: list /issues/N/reactions and filter content == "+1".
  • Pages. tm.gh(... /pages) and *.github.io URLs go: ventures publish under the Teahub pages convention (teahubxyz/teahub#2 — Cloudflare Pages by default, pages branch of the venture's repo/org). venture_url() comes from that.
  • Scout. /search/repositories stays on GitHub's public API, unauthenticated (it's a scouting source, not the forge). notplanned becomes a second source (teahubxyz/teahub#3).
  • Signup issue form .github/ISSUE_TEMPLATE/early-access.yml → Gitea issue template (.gitea/ISSUE_TEMPLATE/), same venture= prefill via ?template=.
  • Tests: un-gate the venture section of test_time.py (TIME_TEST_VENTURE) once the fake is Gitea-shaped.
  • Cloudflare backends (cloudflare.py, worker.js) are forge-neutral; only PAGES_ORIGIN changes.

DONE: python3 .github/time/test_time.py runs the venture tests with no gate, and one dry venture tick on prod (TIME_VENTURE=on, no key) posts its first beat on a venture card.

time.py runs on prod (#47). venture.py is still GitHub-shaped and is not wired to run here (`TIME_VENTURE` unset; `venture.yml` disabled). What it needs: - `per_page` → `limit`; `"pull_request" not in i` → `not i.get("pull_request")`; `author_association` → `tm.trusted(login)`; `user.type == "Bot"` → `login == tm.TIME_BOT`; `/git/ref/heads` + `/git/refs` → `/branches`; reactions: list `/issues/N/reactions` and filter `content == "+1"`. - **Pages.** `tm.gh(... /pages)` and `*.github.io` URLs go: ventures publish under the Teahub pages convention (teahubxyz/teahub#2 — Cloudflare Pages by default, `pages` branch of the venture's repo/org). `venture_url()` comes from that. - **Scout.** `/search/repositories` stays on GitHub's public API, unauthenticated (it's a scouting source, not the forge). notplanned becomes a second source (teahubxyz/teahub#3). - Signup issue form `.github/ISSUE_TEMPLATE/early-access.yml` → Gitea issue template (`.gitea/ISSUE_TEMPLATE/`), same `venture=` prefill via `?template=`. - Tests: un-gate the venture section of `test_time.py` (`TIME_TEST_VENTURE`) once the fake is Gitea-shaped. - Cloudflare backends (`cloudflare.py`, `worker.js`) are forge-neutral; only `PAGES_ORIGIN` changes. DONE: `python3 .github/time/test_time.py` runs the venture tests with no gate, and one dry venture tick on prod (`TIME_VENTURE=on`, no key) posts its first beat on a venture card.
Author
Owner

Pages target settled: the studio index and venture pages are served from this repo's gh-pages branch, ventures/ subdir, by green-tea-pages at yolo.lol (teahubxyz/teahub pages/; a site can be org/repo#branch/subdir). Venture apps stay at <slug>.yolopreneur.lol (Workers).

Done by hand on gh-pages (34f138b, e06ff91): every https://github.com/teahubxyz/time link → https://teahub.xyz/teahubxyz/time (signup forms, cards, studio links), since the GitHub copy is archived and refuses new issues. The generator in venture.py still writes GitHub URLs — part of this card: PAGES_ORIGIN = https://yolo.lol, signup form link = {SERVER}/{REPO}/issues/new?template=early-access.yml&venture=… (confirm Gitea prefills form fields from the query string; the template moves to .gitea/ISSUE_TEMPLATE/ if .github/ isn't picked up), and the pages publish step pushes to gh-pages here (no Pages API call). Pull on pages is every 5 min; add a push webhook on this repo (https://green-tea-pages.fly.dev/_hook/teahubxyz/time) when the branch is written by the loop.

Pages target settled: the studio index and venture pages are served from this repo's `gh-pages` branch, `ventures/` subdir, by `green-tea-pages` at **yolo.lol** (`teahubxyz/teahub` `pages/`; a site can be `org/repo#branch/subdir`). Venture apps stay at `<slug>.yolopreneur.lol` (Workers). Done by hand on `gh-pages` (34f138b, e06ff91): every `https://github.com/teahubxyz/time` link → `https://teahub.xyz/teahubxyz/time` (signup forms, cards, studio links), since the GitHub copy is archived and refuses new issues. The generator in `venture.py` still writes GitHub URLs — part of this card: `PAGES_ORIGIN` = `https://yolo.lol`, signup form link = `{SERVER}/{REPO}/issues/new?template=early-access.yml&venture=…` (confirm Gitea prefills form fields from the query string; the template moves to `.gitea/ISSUE_TEMPLATE/` if `.github/` isn't picked up), and the pages publish step pushes to `gh-pages` here (no Pages API call). Pull on pages is every 5 min; add a push webhook on this repo (`https://green-tea-pages.fly.dev/_hook/teahubxyz/time`) when the branch is written by the loop.
Author
Owner

Correction: the index lives at yolopreneur.lol (not yolo.lol). Live now: https://yolopreneur.lol/ (and www) → this repo's gh-pages ventures/; https://yolopreneur.lol/<slug>/ are the venture pages; <slug>.yolopreneur.lol the apps. So PAGES_ORIGIN = https://yolopreneur.lol.

Correction: the index lives at **yolopreneur.lol** (not yolo.lol). Live now: https://yolopreneur.lol/ (and www) → this repo's `gh-pages` `ventures/`; `https://yolopreneur.lol/<slug>/` are the venture pages; `<slug>.yolopreneur.lol` the apps. So `PAGES_ORIGIN = https://yolopreneur.lol`.
Author
Owner

Consolidation done on gh-pages (58853fe). One ledger: ventures/ventures.json now carries Time's 9 and notplanned's 7 (source: "time" | "notplanned", status: "built" for the never-launched ones; their pages copied to ventures/<slug>/), plus ventures/backlog.json (notplanned's 9 scouted opportunities). teahubxyz/notplanned is on prod (repo + its 4 issues).

The index is now hand-authored (ventures/index.html, neo-brutalist) and renders those two JSON files at load. So for this card: the generator must stop writing index.html and only write ventures.json (and, when the notplanned scout runs as a source, backlog.json), preserving the source field. Per-venture pages are still the generator's.

**Consolidation done on `gh-pages` (58853fe).** One ledger: `ventures/ventures.json` now carries Time's 9 and notplanned's 7 (`source: "time" | "notplanned"`, `status: "built"` for the never-launched ones; their pages copied to `ventures/<slug>/`), plus `ventures/backlog.json` (notplanned's 9 scouted opportunities). `teahubxyz/notplanned` is on prod (repo + its 4 issues). **The index is now hand-authored** (`ventures/index.html`, neo-brutalist) and renders those two JSON files at load. So for this card: the generator must **stop writing index.html** and only write `ventures.json` (and, when the notplanned scout runs as a source, `backlog.json`), preserving the `source` field. Per-venture pages are still the generator's.
Author
Owner

Convention settled: every venture lives at <slug>.yolopreneur.lol. *.yolopreneur.lol → pages (wildcard cert issued); the nine Worker-backed ones keep their own proxied records (more specific wins). Static ventures are served from gh-pages ventures/<slug>/; yolopreneur.lol/<slug>/ 301s to the subdomain. ventures.json url/pages updated (3dcc1d4). For the generator: pages = https://<slug>.yolopreneur.lol/, never a path.

**Convention settled: every venture lives at `<slug>.yolopreneur.lol`.** `*.yolopreneur.lol` → pages (wildcard cert issued); the nine Worker-backed ones keep their own proxied records (more specific wins). Static ventures are served from `gh-pages` `ventures/<slug>/`; `yolopreneur.lol/<slug>/` 301s to the subdomain. `ventures.json` `url`/`pages` updated (3dcc1d4). For the generator: `pages` = `https://<slug>.yolopreneur.lol/`, never a path.
Author
Owner

Decision: every venture is static on Teahub pages. No Cloudflare backends (no Workers, no D1, no Workers AI — no CF spend). backend dropped from ventures.json (f8b35be); time.js already degrades when /api/ is absent (share links and passkey accounts simply don't appear).

For the port: cloudflare.py and cloudflare/worker.js are out — no refresh_backends, no CLOUDFLARE_* secrets on prod, no <slug>.<domain> Worker custom domains. A venture ships as ventures/<slug>/ on gh-pages and is reachable at <slug>.yolopreneur.lol through the wildcard, nothing else to provision. Shared state a venture needs (saves, signups beyond the issue form) is a separate decision later, not a Worker per venture.

Blocker on the DNS side (operator): the nine <slug>.yolopreneur.lol records are Workers custom domains and are read-only (CF error 1043) until the Workers are deleted. Once they are, the wildcard takes over and the static copies serve with no further change.

**Decision: every venture is static on Teahub pages. No Cloudflare backends** (no Workers, no D1, no Workers AI — no CF spend). `backend` dropped from `ventures.json` (f8b35be); `time.js` already degrades when `/api/` is absent (share links and passkey accounts simply don't appear). For the port: `cloudflare.py` and `cloudflare/worker.js` are **out** — no `refresh_backends`, no `CLOUDFLARE_*` secrets on prod, no `<slug>.<domain>` Worker custom domains. A venture ships as `ventures/<slug>/` on `gh-pages` and is reachable at `<slug>.yolopreneur.lol` through the wildcard, nothing else to provision. Shared state a venture needs (saves, signups beyond the issue form) is a separate decision later, not a Worker per venture. Blocker on the DNS side (operator): the nine `<slug>.yolopreneur.lol` records are Workers custom domains and are read-only (CF error 1043) until the Workers are deleted. Once they are, the wildcard takes over and the static copies serve with no further change.
Author
Owner

Ledger note for the port (2026-10-14): ventures/ventures.json on gh-pages now has entries that Time did not generate. Eight have "source": "yolopreneur" (well-known, lineage, teahub, persimmons, phly, phast, macmcp, time) and some have "source": "notplanned". Their url is the product's own address and ventures/<slug>/index.html is a forwarder. When venture.py writes the ledger, it must only add or update entries whose source is time (or missing), and keep every other entry and its folder as they are. If it rewrites the file from its own state, those entries are lost. The file is written with json.dumps(d, indent=1) (ASCII escapes, no trailing newline), so keep that to keep diffs small.

Ledger note for the port (2026-10-14): `ventures/ventures.json` on `gh-pages` now has entries that Time did not generate. Eight have `"source": "yolopreneur"` (well-known, lineage, teahub, persimmons, phly, phast, macmcp, time) and some have `"source": "notplanned"`. Their `url` is the product's own address and `ventures/<slug>/index.html` is a forwarder. When `venture.py` writes the ledger, it must only add or update entries whose `source` is `time` (or missing), and keep every other entry and its folder as they are. If it rewrites the file from its own state, those entries are lost. The file is written with `json.dumps(d, indent=1)` (ASCII escapes, no trailing newline), so keep that to keep diffs small.
time added the queued label 2026-10-19 16:47:50 +00:00
Author
Owner

CEO note for the worker: the port itself has landed (#139, #140; the venture loop ran on Teahub with Claude seats). What's left per the DONE line is the test gate: test_time.py still prints "venture tests skipped (TIME_TEST_VENTURE=1 to run them)". Make the venture section run by default (keep it fast; the fake is already Gitea-shaped), keep CI green, and close this card. The "dry venture tick on prod" half is already met; the loop has posted beats on prod venture cards.

CEO note for the worker: the port itself has landed (#139, #140; the venture loop ran on Teahub with Claude seats). What's left per the DONE line is the test gate: `test_time.py` still prints "venture tests skipped (TIME_TEST_VENTURE=1 to run them)". Make the venture section run by default (keep it fast; the fake is already Gitea-shaped), keep CI green, and close this card. The "dry venture tick on prod" half is already met; the loop has posted beats on prod venture cards.
time added ready and removed queued labels 2026-10-19 17:07:50 +00:00

⏱️ Time: Claude Sonnet (Anthropic) is working on this now, on branch time/card-48.

⏱️ Time: Claude Sonnet (Anthropic) is working on this now, on branch `time/card-48`. <!-- time {"beat":"dispatched","launched":true,"worker":"anthropic"} -->

⏱️ Time: the worker call failed: sonnet stopped without a PR after 42 steps: Let me print the failure comment.. I'll retry on my own next beat (TIME_AUTO_RETRY times in all); comment /time retry for one more.

⏱️ Time: the worker call failed: `sonnet stopped without a PR after 42 steps: Let me print the failure comment.`. I'll retry on my own next beat (TIME_AUTO_RETRY times in all); comment `/time retry` for one more. <!-- time {"beat":"error"} -->

⏱️ Time: Claude Sonnet (Anthropic) is working on this now, on branch time/card-48. Retrying on my own, resuming the branch.

⏱️ Time: Claude Sonnet (Anthropic) is working on this now, on branch `time/card-48`. Retrying on my own, resuming the branch. <!-- time {"beat":"dispatched","launched":true,"worker":"anthropic","auto_retry":true} -->

⏱️ Time: sonnet opened PR #200 (39 steps, claude-sonnet-5-5). Review and landing follow on the next beat.

⏱️ Time: `sonnet` opened PR #200 (39 steps, claude-sonnet-5-5). Review and landing follow on the next beat. <!-- time {"beat":"dispatched","worker":"anthropic","auto_retry":true,"pr":200,"steps":39,"seat":"sonnet","model":"claude-sonnet-5-5"} -->

⏱️ Time: PR #200 is up for this card. haiku reviewed it on the PR.

⏱️ Time: PR #200 is up for this card. `haiku` reviewed it on the PR. <!-- time {"beat":"pr","pr":200,"launched":false,"seat":"haiku","as":"seat","review":"venice","seats":["haiku"]} -->

⏱️ Time: the reviewer objected on PR #200. Over to a human (or comment /time retry to send it back to the worker with the review attached).

⏱️ Time: the reviewer objected on PR #200. Over to a human (or comment `/time retry` to send it back to the worker with the review attached). <!-- time {"beat":"needs-human","pr":200} -->
Sign in to join this conversation.
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: teahubxyz/time#48