Autonomous multi-branch release engine — 3 bug + 1 UX fix per branch, every hour, self-learning, self-healing.
21 branches 24h cooldown 1 release/hour 253+ releases
Full source: github.com/unclehowell/datro/tree/cnei/flywheel
A cron job (0 * * * *) on an AWS EC2 instance selects one branch via round-robin rotation, runs 4 automated fix passes against its working tree, commits and tags, and publishes a GitHub release with structured notes. An executive-coach meta-review runs separately at 00:00 UTC daily on a command machine, reviewing AWS output and self-improving the flywheel code.
| File | Role |
|---|---|
multi-branch-release.sh | Bash orchestrator — cron entrypoint, branch selection, pass dispatch, git/release |
intelligence.py | Python intelligence pipeline — builds LLM prompts, applies fixes, manages profiles, self-learns |
gather_review_data.py | Log parser — extracts fix source ratios (AI vs Pool vs Fallback) from AWS logs for meta-review |
meta-review.sh | Executive coach — fetches AWS state, runs intelligence.py --type meta, syncs profile learnings |
release-state.json | State file — rotation index, cooldowns, release counters, fix/ux rotation pointers |
profiles.json | Per-branch profiles — LLM rotation lists, learned patterns, skill libraries, branch knowledge |
agent/branches/*.md | Branch context files — soul/manifest/memory per branch, category, cornerstone mission |
Each branch deploys independently via Cloudflare Pages at {branch}.datro.xyz:
| Branch | Category | Domain | Releases |
|---|---|---|---|
| financecheque | E-commerce | financecheque.uk | 150 |
| ccan | Community | ccan.datro.xyz | 16 |
| althea | Community | althea.datro.xyz | 7 |
| bpvsbuckler | E-commerce | bpvsbuckler.datro.xyz | 5 |
| carfinancecheque | E-commerce | carfinancecheque.datro.xyz | 5 |
| ceo | Platform | ceo.datro.xyz | 7 |
| dash | Platform | dash.datro.xyz | 5 |
| datro | Meta | datro.xyz | 6 |
| dcc | Community | dcc.datro.xyz | 6 |
| gui | Platform | gui.datro.xyz | 6 |
| hbnb | E-commerce | hbnb.datro.xyz | 6 |
| library | Documentation | library.datro.xyz | 6 |
| llmwiki | Documentation | llmwiki.datro.xyz | 5 |
| subrepos | Platform | subrepos.datro.xyz | 4 |
| ui | Platform | ui.datro.xyz | 5 |
| wave | Platform | wave.datro.xyz | 5 |
| wayback | Archive | wayback.datro.xyz | 4 |
| whitepaper | Documentation | whitepaper.datro.xyz | 3 |
| archives | Archive | archives.datro.xyz | 5 |
| cnei | Meta | cnei.datro.xyz | — |
| greathousefarm | Advocacy | greathousefarm.datro.xyz | 1 |
All content lives under static/{branchname}/ in the repo. Cloudflare Pages root_dir is set per project to that prefix.
The original loop (for pass in 1 2 3) always let the AI win, resulting in 105/105 console.log removals. The strategy was redesigned into individually-controlled passes:
| Pass | Source | Purpose |
|---|---|---|
| 1 (Bug) | AI → Rotating Pool → Fallback | AI finds professional improvements (SEO, structured data, accessibility). If AI fails, pool rotates through 32 fix functions. Last resort: guaranteed fallback. |
| 2 (Bug) | Rotating Pool only | Guarantees pool diversity — skips AI entirely so the rotating pool always gets a turn. |
| 3 (Bug) | Guaranteed Fallback | Always runs — catches triple-blank-lines via rg -U multiline matching. |
| 4 (UX) | AI → Rotating Pool → Fallback | User-experience improvements (viewport, tap targets, hover styles, skip links, print styles, etc.). |
| Category | Fix Functions |
|---|---|
| SEO | fix_meta_description, fix_canonical_url, fix_og_tags, fix_twitter_card, seo_structured_data, seo_keywords_meta |
| Accessibility | fix_lang_attribute, fix_aria_label, fix_label_for, fix_button_type, fix_heading_hierarchy |
| HTML Standards | fix_doctype, fix_charset_meta, fix_viewport_meta, fix_self_closing, fix_br_syntax, fix_http_equiv, fix_form_charset, fix_bom |
| Security/Performance | fix_link_noopener, fix_script_defer, fix_img_dimensions, fix_inline_handlers |
| Code Quality | fix_console_log, fix_commented_code, fix_trailing_whitespace, fix_blank_lines, fix_tabs_vs_spaces, fix_duplicate_ids, fix_404_title |
| Category | Fix Functions |
|---|---|
| Mobile | ux_viewport, ux_mobile_tap, ux_touch_action, ux_table_responsive |
| Interaction | ux_hover_styles, ux_button_states, ux_smooth_scroll, ux_focus_visible, ux_keyboard_nav |
| Layout | ux_css_order, ux_z_index, ux_spacing, ux_type_scale, ux_cls_fix |
| Accessibility/UX | ux_skip_link, ux_breadcrumb, ux_print_styles, ux_loading_indicator |
Each pool function:
find or rg to locate matching files in the branch checkoutPOOL_DESC and POOL_FILE globals on successfix_rotation / ux_rotation) so the next run picks up where the last left offInstead of telling the AI to "find a bug", the system prompts it to "Benchmark this site against professional standards for its category." Each branch has a category (ecommerce, community, platform, documentation, advocacy, archive, meta) with a custom checklist:
| Category | Focus Areas |
|---|---|
| E-commerce | JSON-LD Product/Offer, OG tags, cookie consent, payment security, trust signals, GDPR privacy policy, returns policy, sitemap.xml, robots.txt, checkout UX, search filter |
| Community | JSON-LD DiscussionForum, signup/login flow, moderation tools, privacy policy, member profiles, notifications, search, pagination, onboarding |
| Platform | JSON-LD WebApplication, API docs, status page, rate limiting, auth flows, dashboard UX, error pages, changelog |
| Documentation | JSON-LD TechArticle, table of contents, search, breadcrumbs, code copy buttons, dark mode, version selector, last-updated timestamps |
The --constraint CLI parameter injects blacklist rules: the AI is told what NOT to do (no console.log removal, no whitespace cleanup, no comment deletion — those belong to the pool).
Every branch has a profile in profiles.json with:
After every fix, learn_from_fix() updates the profile atomically. The AI prompt dynamically injects recent reflections, successful patterns, branch knowledge, and the skill library so each run builds on prior context.
intelligence.py loads the branch context (branch.md + category checklist), profile (history + skills + reflections), and builds a prompt with the Cornerstone Missionfile_path, bug_description, tool, new_str or sed old_str)intelligence.py --apply applies the fix to the working treepackage.json exists, npx eslint runs on the changed file for build validationgit checkout -- file) and the error is fed back for up to 3 self-correction attemptsRuns daily at 00:00 UTC on a separate command machine via meta-review.sh:
release-state.jsongather_review_data.py to parse log for fix source classification (AI vs POOL vs FALLBACK, unique fix types per session)intelligence.py --type meta --branch aws to analyze AWS performance and suggest improvementsTags follow {branch}-v0.0.{patch}.{build:02d}:
release_number = total_releases[branch] + 1
patch = release_number / 100 # increments every 100 releases
build = release_number % 100 # 0–99, zero-padded
version = 0.0.{patch}.{build:02d}
Each GitHub release contains:
## [{tag}] - YYYY-MM-DD
### Fixed
- fix(branch): Add JSON-LD structured data for SEO
- fix(branch): Add meta description tag for SEO
- fix(branch): Remove duplicate blank lines (guaranteed fallback)
### Changed
- ux(branch): Add skip-to-content link for keyboard accessibility
After release, the system:
{branch}.datro.pages.dev (up to 5 retries, 10s apart)24-hour cooldown per branch, enforced by comparing last GitHub release timestamp against current time. Selection is round-robin via rotation_index in state file. If all branches are on cooldown, the script finds the branch closest to expiry and sleeps up to 1 hour. A FORCE_BRANCH env var bypasses rotation for manual targeting.
Every branch has a Cloudflare Pages project with:
root_dir set to static/{branchname}/{branch}.datro.xyz (CNAME to {branch}.datro.pages.dev)root_dir constraint (serves from repo root)# Ubuntu 24.04 EC2 (t3.small+)
sudo apt update && sudo apt install -y git python3 ripgrep nodejs npm
npm install -g wrangler
sudo apt install -y gh && gh auth login
git clone https://github.com/YOUR_USER/YOUR_REPO.git ~/repo
mkdir -p ~/.fcukproxy
cp multi-branch-release.sh intelligence.py profiles.json ~/.fcukproxy/
# Edit BRANCHES array and GITHUB_REPO in multi-branch-release.sh
# Add 24h cron:
0 * * * * /home/ubuntu/.fcukproxy/multi-branch-release.sh >> ~/logs/multi-branch-release.log 2>&1
~/.fcukproxy/multi-branch-release.sh — main orchestrator~/.fcukproxy/intelligence.py — AI pipeline + profile management~/.fcukproxy/agent/profiles.json — per-branch profiles with LLM rotation lists~/.fcukproxy/agent/branches/{branch}.md — per-branch context files (soul, manifest, memory, cornerstone mission)~/.fcukproxy/agent/aws-supervisor.md — executive coach context for meta-reviewtimeout guards (60s AI, 30s apply, 10s learn)/tmp/multi-branch-release.lock) prevents concurrent cron runsgh CLI OAuth{
"rotation_index": 1,
"total_releases": { "financecheque": 150, "archives": 5, ... },
"last_release": { "financecheque": 1779506355, "archives": 1779500752, ... },
"fix_rotation": 23,
"ux_rotation": 0
}
MIT — use freely, adapt for your own repos. Source at github.com/unclehowell/datro/tree/cnei/flywheel.
Generated by the cnei branch — source
· Last update: May 2026