Claude 961e8dfa83
ci / test (pull_request) Successful in 44s
heartbeat / tick (pull_request_review) Successful in 10s
Router: rank the spine's cards too, shown and never queued (#173)
Astra reads the open issues of TIME_SPINE (teahubxyz/teahub: Tea MCP, the Pages server, the Gitea look) through the
same API, and every one with a `DONE:` line joins the ranked table as `teahub#N`, judged by the seat like any other
candidate. Those rows carry `why_not` "spine: not queued (Time builds in this repo only)", so the table marks them and
code cannot act on them: `n` is None, as for the new-venture candidate, which keeps them out of `pick`, `pick_cloud`
and the promotion `order`, and they are never labelled from here. Their value is for the owner or the CEO to read:
what the platform needs next, now visible beside Time's own cards instead of invisible.

The spine's rows get the same label check `tm.issues` uses (Gitea ignores a filter on a label a repo does not have and
answers with every issue, #137) and PRs are left out. The spine stays context, not a dependency: a failed read is a log
line and the day's ranking goes up without it.

Checks: a spine card with a `DONE:` line is ranked, never picked, never sent to the cloud lane, never in the promotion
order and never labelled; one without a `DONE:` line is not a candidate; a PR of the spine is not an issue; a label
filter is checked on every row; a read failure prints one line and the tick still queues its two cards.

No workflow change is needed: astra.yml already passes nothing the spine read depends on (TIME_SPINE has a default).

Closes #173

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017E7Qf55mVnHmowgaGseNRh
2026-10-20 00:57:53 +00:00
2026-10-19 23:07:58 +00:00

time

A Gitea-native agent factory, running on Teahub prod (teahub.xyz). The Gitea repo is the ledger, Gitea Actions are the clock (Time), the worker is a Claude or Venice seat with hands or a Cursor cloud agent, and chat is where you plan.

  • Cards: an issue with a DONE: line, labelled ready.
  • Heartbeat (heartbeat.yml, hourly and whenever a card is labelled ready): moves cards forward. In dry-run (default) it only says what it would do; with TIME_MODE=live it dispatches each card to the worker (TIME_WORKER: a seat such as claude:sonnet or venice:kimi, which edits the repo and opens the PR itself, or a Cursor cloud agent), which opens a PR that closes the card. An optional reviewer (TIME_REVIEW) checks the PR. At most TIME_DAILY_CAP launches a day. Spend governor: every model call is booked to time/ledger/<YYYY-MM>.jsonl (tokens and dollars); once today's spend reaches TIME_DAILY_USD (default 5) or the month's reaches TIME_MONTHLY_USD (default 100), Time stops calling models, opens an andon issue, and a monthly breach also sets TIME_MODE=dry-run. No model decides whether to spend.
  • Mentions (mention.yml): @sonnet, @opus, @kimi, @grok 4.7, @qwen max high in any issue, PR or comment gets that seat's reply.
  • Hands-off (TIME_AUTOMERGE=on): label an issue spec and Time splits it into cards that run one at a time. A card's PR merges itself once the reviewer approves and checks are green, then the next card starts. Objections, red checks and protected paths (workflows, deploy, secrets) go to a human.
  • Venture loop (venture.yml, every 20 min once TIME_VENTURE=on): one venture card a day, or one right away from Actions → venture → Run workflow → "Start a new venture now". It scouts the repos that gained the most stars this week; seats pitch; the board votes (Borda, quorum of two); every board seat writes a launch plan (positioning, first users, pricing, channels, 7-day success and kill lines) and one seat synthesizes them into LAUNCH.md; the worker builds the product as the page on gh-pages (the tool fills the first screen under a slim header with the one signup button; pricing, limits and the why sit below); deterministic checks and headless Chrome (phone and desktop) gate it, with two fix rounds before an andon; GitHub Pages ships it at /ventures/<slug>/. Signups go through an issue form (.github/ISSUE_TEMPLATE/early-access.yml), each one thanked on its issue; after 7 days the count of distinct people decides: build v2, kill, or watch a week more. The studio index lives at /ventures/. Launch posts are drafts for a human; nothing is posted outside the repo.
  • Batches (TIME_VENTURE_BATCH=3, or Run workflow → "batch"): one scout pass, a field of pitches, and the board's top k become venture cards in one milestone, built side by side and launched together. A held child gets one batch retry before it's counted dead; a retro compares the cohort once every child is measured.
  • Seed (seed.yml, manual): land a venture that was built somewhere else. Give it a slug, the URL of a .tgz whose top folder is that slug (or of its parts, in order) and the .tgz's sha256, plus a name and a one-liner for a new venture. seed.py checks the bundle, copies it to ventures/<slug>/ on gh-pages in one commit, adds or refreshes its line in ventures/ventures.json, and asks Teahub pages to pull, so it is live at <slug>.yolopreneur.lol within the minute. Nothing in the bundle runs.
  • Refresh (refresh.yml, manual): for a venture that lives on gh-pages and makes some of its own files (fonts, art, screenshots, generated code). It runs ventures/<slug>/tools/build.sh on the runner, in place and without credentials, then commits what changed to gh-pages in one commit and asks Teahub pages to pull. from takes the folder from another branch first, so a reworked venture lands whole.
  • Backends (optional, CLOUDFLARE_API_TOKEN + CLOUDFLARE_ACCOUNT_ID): each venture also gets its own Cloudflare Worker, D1 database and Workers AI, serving its Pages folder at <slug>.<TIME_VENTURE_DOMAIN>. The page talks to it through time.js (share links that save a creation, a rate-limited small model, and accounts with passkeys: no passwords, no email); every call degrades gracefully, so products still work on Pages alone. Code: .github/time/cloudflare.py and cloudflare/worker.js.
  • Doctor (doctor.yml, manual): runs the tests and checks label, settings, keys and today's spend.
  • Update (update.yml, weekly or manual): opens a PR with the latest engine from teahubxyz/time, so every project stays on one Time instead of drifting copies.

Setup

Started on GitHub as a proof of concept (teahubxyz/time, now read-only); ported to Gitea 2026-10-14.

Open this repo in Claude Code or Cursor and say "set up Time": the agent follows .claude/skills/time/SKILL.md. The recommended path needs one secret, ANTHROPIC_API_KEY: Claude seats plan, build and review (TIME_WORKER=claude:sonnet, TIME_REVIEW=claude:haiku; haiku, sonnet, opus, fable are the seats, priced in .github/time/seats.json). With VENICE_API_KEY instead, Venice seats do the same (TIME_WORKER=venice:qwen coder, TIME_REVIEW=venice:grok). A Cursor cloud agent can be the worker instead if you have a Cursor API key. The landing page walks through it: https://teahubxyz.github.io/time/

Status

For changes and release history, see CHANGELOG.md.

S
Description
Time: the clock for the factory. Ported from GitHub (PoC) 2026-10-14.
Readme
34 MiB
0 Stars 1 Watchers 0 Forks
Languages
Python 62%
JavaScript 36.6%
HTML 1.4%