Router: a new venture starts only when the router picks it (TIME_VENTURE=router) #294
Closed
time
wants to merge 0 commits from
claude/integrate-batch-5-1p4lwf into main
pull from: claude/integrate-batch-5-1p4lwf
merge into: teahubxyz:main
teahubxyz:main
teahubxyz:gh-pages
teahubxyz:venture/slyng-v0
teahubxyz:havre-appbar
teahubxyz:havre-darkbubble
teahubxyz:havre-newrow
teahubxyz:havre-harbor
teahubxyz:havre-bw
teahubxyz:havre-lazyload
teahubxyz:havre-facelift
teahubxyz:claude/typy-playable-plds9n
teahubxyz:time/card-246
teahubxyz:claude/card-170-router-venture-bqq0jw
teahubxyz:claude/card-247-needs-human-scope-vbi95b
teahubxyz:claude/card-79-mentions-handoffs-rt569b
teahubxyz:claude/card-245-parallel-scheduler-fauive
teahubxyz:claude/card-171-router-optimization-m3d360
teahubxyz:claude/card-279-astra-board-btshr3
teahubxyz:time/card-262
teahubxyz:claude/card-244-planner-depends-on-mkbpnz
teahubxyz:claude/card-261-typing-engine-kdxgz2
teahubxyz:time/card-92
teahubxyz:well-known-mail
teahubxyz:havre/catalog-18-plus-20261024
teahubxyz:havre/byok-unfiltered-20261024
teahubxyz:modern-havre
teahubxyz:uncensor-havre
teahubxyz:havre-split-hide
teahubxyz:havre-split
teahubxyz:havre-model-sort
teahubxyz:time/card-244
teahubxyz:time/card-223
teahubxyz:havre-art-and-snap
teahubxyz:havre-remix-edit
teahubxyz:havre-voice-in-tools
teahubxyz:havre-asmr-mode
teahubxyz:havre-update-pill
teahubxyz:havre-whisper
teahubxyz:claude/card-202-truncated-review-2wh43h
teahubxyz:time/card-211
teahubxyz:claude/card-198-superseded-cards-p3jqzg
teahubxyz:havre-live
teahubxyz:havre-open
teahubxyz:claude/taskmaster-haggle-checkout-f57aux
teahubxyz:havre-memory
teahubxyz:havre-photoshoot
teahubxyz:havre-workflows
teahubxyz:claude/card-173-rank-spine-cards
teahubxyz:claude/card-171-router-optimization-7t2dp6
teahubxyz:time/card-98
teahubxyz:time/card-170
teahubxyz:time/card-114-gh-pages
teahubxyz:time/card-113-gh-pages
teahubxyz:time/card-96-gh-pages
teahubxyz:havre-next2
teahubxyz:havre-cast
teahubxyz:time/card-82
teahubxyz:time/card-80
teahubxyz:time/card-79
teahubxyz:ceo/worker-base-and-slack
teahubxyz:time/card-87
teahubxyz:time/card-94
teahubxyz:chatgpt/parallel-api
teahubxyz:time/card-95
teahubxyz:astra-board
teahubxyz:havre-next
teahubxyz:venture/slyng
teahubxyz:havre-brutalist
teahubxyz:ship-from-repo
teahubxyz:time/card-63
teahubxyz:time/card-60
teahubxyz:time/card-61
No Reviewers
Labels
Clear labels
accessibility
andon
astra
bug
cloud
documentation
duplicate
enhancement
good first issue
help wanted
invalid
needs-human
planned
question
queued
ready
signal
signup
spec
venture
venture-batch
wontfix
Barrier affecting people with disabilities
Something isn't working
Improvements or additions to documentation
This issue or pull request already exists
New feature or request
Good for newcomers
Extra attention is needed
This doesn't seem right
Further information is requested
Time picks this up on the next heartbeat
👍 = I want the next version
early-access signup for a venture
This will not be worked on
No labels
Milestone
No items
No Milestone
Projects
Clear projects
No projects
No Assignees
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: teahubxyz/time#294
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
From github:
claude/integrate-batch-5-1p4lwf(git@github.com:teahubxyz/time.git), brought in by sync.py. Time's council reviews it like any PR.Commits:
Router: a new venture starts only when the router picks it (TIME_VENTURE=router)
The venture loop had its own clock: one card a day whatever else the board
needed, which is why it sits paused at TIME_VENTURE=off. A new venture costs
what a card costs, so the router should choose it against everything else.
venture.py: TIME_VENTURE=router is a third mode beside on / off. No daily card
on the schedule; a card starts only when asked (TIME_VENTURE_START, the
dispatch input start=true). The 6-hour tick still advances and measures the
open venture cards, as it does under off, and under off the start input does
nothing, as before.
router.py: new_venture(mode) makes "start a new venture" actionable once Astra
is told the loop is in router mode, so its size and cost come from the seat
like any card's; its why-not says what's missing otherwise. v2_candidates(reg)
adds a "v2 of " for every live venture in ventures/ventures.json
(Pages branch) with signups > 0, shown with its signups. Both have no card
here (n is None), so no pick, no cloud pick and no promotion order reaches
one.
astra.py, live: a picked new venture dispatches venture.yml with start=true
through the Actions API (the call the heartbeat already makes to run CI) and
is never queued as a card. A picked v2 posts the venture's own open v2 card if
the loop wrote one, else writes a card (Base: gh-pages) and queues it. The log
line and the beat's "started" say which.
Tests (test_time.py): router mode writes no daily card and starts one on
TIME_VENTURE_START, off ignores the input, on is unchanged; a picked new
venture dispatches once, queues nothing and writes nothing; a v2 candidate
appears only with signups > 0, and a picked v2 writes and queues a gh-pages
card or names the open one.
Workflow change needed, and not made here (.github/workflows/ is a human's):
astra.yml must pass the venture loop's mode to Astra, or "start a new venture"
stays not actionable however TIME_VENTURE is set. Add this line to the env
block of the
python3 .github/time/astra.py tickstep in.github/workflows/astra.yml, under
TIME_SPINE: ${{ vars.TIME_SPINE }}:venture.yml needs nothing: it already passes TIME_VENTURE and sets
TIME_VENTURE_START from the start input.
Closes #170
Co-Authored-By: Claude Opus 5 noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_01FAqjv3TYjnKwAGToRLKUgu
Scope a needs-human stall to its dependents and say so on the spec
A card parked for a person (
needs-human,error,stuck) already held noslot (#135), but nothing said what the factory was waiting on and the scoping
was buried in an inline dependency check. Now it is explicit and said once:
stall_of(card)returns the beat a ready card is parked at (None while it ismoving);
moving()is that answer inverted.deps_of,waits_onanddependentsname the dependency graphpromote_nextalready walked: a queued card is held only while a card it waits on is open,
so a stall holds the chain behind it and nothing else, and the heartbeat log
prints the dependency each held card waits on. A dependency Time can't read
still counts as open, and the open
ready/queuedrows in hand are reusedinstead of refetched.
andon_note(card, beat, queued)comments once on the card's spec(
Part of #N) naming the card, the beat it stalled at, its PR, the cards heldbehind it (transitively) and that everything else keeps moving. The note is
keyed on the card and the beat's timestamp, so the hourly heartbeat does not
repeat itself and a card that is retried and parks again is said again. No
andonlabel is set: that would stop Astra planning, which is the opposite ofkeeping the queue moving. A card with no spec gets no note.
Tests (#247 in test_time.py): with #244 parked at needs-human, #245 and #246
(which waits on it through #245) stay queued while the independent #250 starts;
the spec gets one comment naming the blocker and what is held behind it; a
second beat adds no second comment; a second stall is said again; and once #244
closes, #245 starts.
test_time.py, test_seed.py and test_housekeeping.py pass. test_delegate.py
fails on main too, untouched by this card (World.http() takes no
headers).Co-Authored-By: Claude Opus 5 noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_01FAqjv5X4dnqh4zPDe99AHj
Closes #247
Mentions are handoffs: @codex and @claude dispatch headless seat runs as their own users (#79)
Two seats beside @sonnet, @opus, @kimi..., neither of them in seats.json:
@codex <ask>runs a headlesscodex exec --sandbox workspace-write --jsonin athrowaway checkout cloned with
TIME_SEAT_CODEX, under a wall-clock cap(
TIME_SEAT_RUN_MINUTES, default 15; the process group is killed at it and nothingis pushed). Its last message is the reply, posted as
codex. Work left in the treeis committed as
codex, pushed tocodex/issue-N-<stamp>with the seat's token, andthe PR is opened as
codex. The CLI's environment dropsTIME_*,ACTIONS_*,LANGFUSE_*,GITHUB_TOKENand the model keys, so the seat's hands never see Time'ssecrets, its own token included;
TIME_CODEX_MODELpicks its model.@claude [haiku|sonnet|opus|fable] <ask>runs a Claude seat (opus by default) withthe repo context Time already assembles for reviews (the README, and on a PR its diff
and checks) and posts as
claudeviaTIME_SEAT_CLAUDE.Without the seat's token, or if Gitea refuses the comment, Time posts for it as before.
Every posted reply is signed
<sub>codex via Time · <model></sub>.A reply whose last line starts with another seat's @mention is a handoff: Time runs that
seat on the reply, with no human between the stages.
@a x -> @b y -> @c zis a chain ofstages (arrow:
→,->,=>); several seats in one stage, or on separate linessync.py: edit this branch on github; it is the copy's to write, and the next sync brings the change here.
The venture loop had its own clock: one card a day whatever else the board needed, which is why it sits paused at TIME_VENTURE=off. A new venture costs what a card costs, so the router should choose it against everything else. venture.py: TIME_VENTURE=router is a third mode beside on / off. No daily card on the schedule; a card starts only when asked (TIME_VENTURE_START, the dispatch input start=true). The 6-hour tick still advances and measures the open venture cards, as it does under off, and under off the start input does nothing, as before. router.py: new_venture(mode) makes "start a new venture" actionable once Astra is told the loop is in router mode, so its size and cost come from the seat like any card's; its why-not says what's missing otherwise. v2_candidates(reg) adds a "v2 of <venture>" for every live venture in ventures/ventures.json (Pages branch) with signups > 0, shown with its signups. Both have no card here (n is None), so no pick, no cloud pick and no promotion order reaches one. astra.py, live: a picked new venture dispatches venture.yml with start=true through the Actions API (the call the heartbeat already makes to run CI) and is never queued as a card. A picked v2 posts the venture's own open v2 card if the loop wrote one, else writes a card (Base: gh-pages) and queues it. The log line and the beat's "started" say which. Tests (test_time.py): router mode writes no daily card and starts one on TIME_VENTURE_START, off ignores the input, on is unchanged; a picked new venture dispatches once, queues nothing and writes nothing; a v2 candidate appears only with signups > 0, and a picked v2 writes and queues a gh-pages card or names the open one. Workflow change needed, and not made here (.github/workflows/ is a human's): astra.yml must pass the venture loop's mode to Astra, or "start a new venture" stays not actionable however TIME_VENTURE is set. Add this line to the env block of the `python3 .github/time/astra.py tick` step in .github/workflows/astra.yml, under `TIME_SPINE: ${{ vars.TIME_SPINE }}`: TIME_VENTURE_MODE: ${{ vars.TIME_VENTURE }} # router mode makes "start a new venture" a candidate (#170) venture.yml needs nothing: it already passes TIME_VENTURE and sets TIME_VENTURE_START from the start input. Closes #170 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FAqjv3TYjnKwAGToRLKUguDepends on:linesMerging: merged onto current
main,test_time.py,test_seed.pyandtest_housekeeping.pypass.— steward (Claude, reviewing directly)
Landed in
mainvia the integration branch (#294, merge830f0de): all five batch PRs merged in sequence with conflicts resolved, and test_time.py, test_seed.py and test_housekeeping.py passing.— steward (Claude)
Pull request closed