Autonomous multi-branch release engine — 3 bug + 1 UX fix per branch, every hour, via AI-first multi-provider fallback chain with rotating pool safety net. Self-learning, self-healing, cross-branch daily dedup.
21 branches 24h cooldown 1 release/hour 303 releases 6 AI providers
Source: github.com/unclehowell/datro/tree/cnei/flywheel
A cron job (0 * * * *) on an AWS EC2 instance (1 vCPU, 1 GB RAM) runs the flywheel once per hour. Each run produces exactly one release for one branch — 3 unique bug fixes + 1 novel UX feature — across 21 Cloudflare-deployed websites.
Each pass attempts AI first. The intelligence.py agent cycles through providers in order until one returns a valid JSON fix:
| Order | Provider | Type | Timeout | Keys |
|---|---|---|---|---|
| 1 | financecheque.uk proxy | Parent proxy → routes to child proxy | 70s (3 retries) | — |
| 2 | 172.31.29.216:4001 | Child proxy → runs kilo CLI | 15s | — |
| 3 | OpenRouter | Direct API (gpt-4o-mini) | 90s | ✓ |
| 4 | Gemini | Direct API (gemini-2.0-flash) | 90s | ✓ |
| 5 | DeepSeek | Direct API (deepseek-chat) | 90s | ✓ |
| 6 | Groq | Direct API (llama-3.3-70b-versatile) | 90s | ✓ |
API keys are stored in ~/.fcukproxy/.env (sourced by intelligence.py) and ~/.secrets/.env. All 4 direct API providers now have valid keys.
daily-unique.json prevents ANY fix/feature description from repeating across ALL 21 branches in a single UTC day. Each pass passes the growing --daily-fixes / --daily-features list to the AI prompt as "TODAY'S ALREADY-APPLIED" — the AI must produce something novel.
| File | Role |
|---|---|
multi-branch-release.sh | Bash orchestrator — cron entrypoint, branch selection, 4-pass dispatch, git/release, daily tracking, pool functions, cooldown handler |
intelligence.py | Python AI agent — builds prompts with file excerpts + master plan todos, rotates through 6 LLM providers, applies fixes, manages profiles, self-learns |
.env | API keys for OpenRouter, Gemini, DeepSeek, Groq — loaded at runtime |
release-state.json | State file — rotation_index, cooldown timestamps, release counters, fix/ux rotation pointers |
daily-unique.json | Cross-branch dedup — date + lists of all bug/feature descriptions applied today |
profiles.json | Per-branch profiles — LLM rotation lists, learned patterns, skill libraries, branch knowledge |
agent/branches/*.md | 21 master plans — vision, strategic roadmap, required features, success criteria per branch |
| Branch | Domain | Releases |
|---|---|---|
| financecheque | financecheque.uk | 152 |
| ccan | ccan.datro.xyz | 18 |
| carfinancecheque | car.financecheque.uk | 15 |
| ceo | ceo.datro.xyz | 9 |
| althea | althea.datro.xyz | 8 |
| datro | datro.xyz | 8 |
| dcc | dcc.datro.xyz | 8 |
| gui | gui.datro.xyz | 8 |
| hbnb | hbnb.datro.xyz | 8 |
| library | library.datro.xyz | 8 |
| bpvsbuckler | bpvsbuckler.datro.xyz | 7 |
| archives | archives.datro.xyz | 7 |
| dash | dash.financecheque.uk | 7 |
| llmwiki | llmwiki.financecheque.uk | 7 |
| ui | ui.datro.xyz | 7 |
| wave | wave.datro.xyz | 7 |
| subrepos | subrepos.datro.xyz | 6 |
| wayback | wayback.datro.xyz | 6 |
| whitepaper | whitepaper.financecheque.uk | 3 |
| cnei | cnei.datro.xyz | 3 |
| greathousefarm | greathousefarm.datro.xyz | 1 |
Total: 303 releases. Each branch deploys via Cloudflare Pages at {branch}.datro.pages.dev with custom domain {branch}.datro.xyz (or *.financecheque.uk).
Attempts AI via 6-provider chain. The prompt includes file excerpts (500 chars), master plan TODOs, and "TODAY'S ALREADY-APPLIED" daily blacklist. If all providers return empty, falls to rotating bug pool (8 functions). On pool success, the daily file is updated and the fix rotation advances.
Same as Pass 1 but the daily blacklist now includes the fix from Pass 1. This guarantees the AI (or pool) produces a different fix. Pool starts from where last pass left off (fix_rotation).
Last bug pass. If AI and pool both fail, the guaranteed_bug_fallback runs: it searches the branch directory for files with 3+ consecutive blank lines and removes them. This always produces a fix.
User-experience pass. Same AI chain but with --daily-features blacklist. Falls to UX pool (23 functions) then guaranteed_ux_fallback (adds DOCTYPE + charset if missing).
| Function | Description |
|---|---|
fix_404_title | Set proper title on 404 pages |
fix_doctype | Add <!DOCTYPE html> if missing |
fix_charset | Add <meta charset="UTF-8"> if missing |
fix_lang_attribute | Add lang="en" to HTML tag |
fix_privacy_policy | Create privacy policy page |
fix_terms_service | Create terms of service page |
fix_contact_page | Create contact page with form |
fix_blog_launch | Create blog index + welcome post |
| Function | Description |
|---|---|
ux_viewport | Improve viewport meta with user-scalable=yes |
ux_mobile_tap | Add min tap target sizes (44px) |
ux_hover_styles | Add hover opacity transition |
ux_css_order | Move CSS before JS in head |
ux_skip_link | Add skip-to-content link |
ux_color_contrast | Improve text/background contrast |
ux_smooth_scroll | Add smooth scrolling behavior |
ux_print_styles | Add print-friendly styles |
ux_focus_visible | Add focus-visible keyboard styles |
ux_touch_action | Set touch-action: manipulation |
ux_button_states | Add disabled/active button states |
ux_table_responsive | Wrap tables in scroll containers |
ux_z_index | Fix z-index stacking order |
ux_list_semantics | Fix list nesting semantics |
ux_loading_indicator | Add loading spinner styles |
ux_breadcrumb | Add breadcrumb navigation |
ux_cls_fix | Fix cumulative layout shift |
ux_type_scale | Add typographic scale |
ux_spacing | Add consistent spacing rhythm |
ux_keyboard_nav | Improve keyboard navigation |
ux_cookie_consent | Add cookie consent banner |
ux_social_links | Add social sharing links |
ux_footer_legal | Add footer with legal links |
rotation_index — starts from index, checks cooldown, picks first availablegit rev-parse --verify check prevents stale reference crashesrelease-state.jsonrelease_number = total_releases[branch] + 1
patch = release_number / 100 # increments every 100 releases
build = release_number % 100 # 0–99, zero-padded
tag = {branch}-v0.0.{patch}.{build:02d}
e.g., datro-v0.0.0.08, financecheque-v0.0.1.52
Stored in agent/daily-unique.json. At UTC midnight the file resets. Each fix/feature recording checks the description against the existing list before appending. The AI prompt includes --daily-fixes and --daily-features as "TODAY'S ALREADY-APPLIED" — forcing the LLM to propose something genuinely new across all 21 branches.
~/.fcukproxy/.env (chmod 600)
Generated by the cnei branch — source
· Last update: May 2026 · 303 releases and counting