RFC: MuseHub-first workflow with external deployment platform mirroring
TL;DR
- Problem: MuseHub is the ideal development home, but deployment platforms (Netlify, Vercel, Render, Fly.io, etc.) integrate with GitHub/GitLab, not MuseHub.
- Solution we ship today: A
muse bridge git-exportpattern with a wrapper script that runs a security audit, commits any fixes, bridges to a mirror branch, and opens a PR — all in one command. - Recommended MuseHub automation: Make
muse bridge git-exportrun configurable pre-bridge hooks (defined in.muse/bridge-hooks.toml) so teams never forget the audit step or any other pre-deploy check.
The problem in detail
MuseHub gives signed commits, semantic diffs, merge proposals, and code intelligence. It is the right place for all development. But most deployment platforms watch a GitHub or GitLab repo. There is no official MuseHub-to-GitHub bridge workflow documented anywhere, and nothing prevents a developer from bridging without a security check first.
Running muse bridge git-export without a prior npm audit fix (or equivalent) means vulnerabilities in your dependencies silently make it to production.
The solution (working today)
The mirror branch pattern
MuseHub ← all real development, proposals, merges live here
│
│ muse bridge git-export (one command)
▼
GitHub/GitLab: muse-mirror branch ← permanent, auto-overwritten, never commit here directly
│
│ PR: muse-mirror → main (you approve and merge)
▼
Your deployment platform → live
The wrapper script (ships in this PR)
scripts/muse-bridge-deploy.sh in aaronrene/knowtation implements the full pipeline as a single command:
./scripts/muse-bridge-deploy.sh "mirror: what changed"
It does four things in order:
- Security audit — runs
npm audit fix, then blocks if any high/critical vulnerabilities remain unfixed. The bridge does not proceed until the repo is clean. - Auto-commit — if the audit changed
package-lock.json, commits and pushes the fix to Muse main automatically (no silent drift between Muse and the bridge export). - Bridge export — runs
muse bridge git-export --force-pushto sync Muse main to the mirror branch. - PR creation — opens a PR on GitHub/GitLab (using
ghCLI) if one does not already exist, with a standard body explaining the source.
The script is stack-agnostic at steps 3 and 4. The audit step checks for package.json and skips gracefully if not present (for Python, Rust, etc. projects — those teams substitute pip-audit, cargo audit, etc.).
What MuseHub automation should look like (the feature request)
Proposed: .muse/bridge-hooks.toml
A config file that muse bridge git-export reads before exporting:
[pre_bridge]
hooks = [
{ run = "npm audit fix", on_fail = "block" },
{ run = "npm audit --audit-level=high", on_fail = "block" },
# Add pip-audit, cargo audit, etc. as needed for your stack
]
[post_bridge]
hooks = [
{ run = "gh pr create --base main --head muse-mirror --title 'mirror: auto'", on_fail = "warn" },
]
on_fail = "block" prevents the bridge from running if the hook exits non-zero.
on_fail = "warn" logs a warning but continues.
Why this belongs in the bridge command, not a wrapper script
- Teams using MuseHub should not need to remember or maintain their own wrapper.
- The bridge is the only path from Muse to an external platform. It is the right security gate.
- Pre-bridge hooks are analogous to pre-commit hooks in Git — a well-understood pattern that developers expect.
- This makes the security audit implicit and enforceable by policy, not reliant on individual memory.
Alternative considered: a muse deploy top-level command
A muse deploy command that wraps the bridge and hooks would be more discoverable than a flag on muse bridge git-export. Either approach works; the hook config is the core feature request regardless of which command surfaces it.
Findings from dogfooding (aaronrene/knowtation, May 2026)
--fix-modesinmuse bridge git-export(fixed in issue #38) is critical for repos with shell scripts. Without it, executable bits are stripped and scripts fail silently.- Navigating to a proposal by sequential number (
/proposals/2) returns a blank JSONnot foundresponse. The SHA256-based URL works, but the list page + click-title flow is the only reliable path. A number-aliased URL would reduce confusion for new users. - GitHub bot integrations (Dependabot, etc.) will create PRs directly on GitHub that conflict with the mirror pattern. Recommendation: disable GitHub-side bots; handle dependency updates via
npm audit fixin the Muse workflow. - The proposal queue "All" tab shows merged proposals alongside open ones without a strong visual distinction. New users may mistake merged proposals for pending work.
Rules that make the mirror pattern work
- Never commit or push directly to GitHub/GitLab. Everything goes through Muse.
muse-mirroris a permanent branch. Never delete it, never push to it manually. The bridge owns it.- Always merge to Muse
mainbefore bridging. The bridge reads HEAD (main). Feature branches are never bridged directly. - Run the security audit before every bridge. The wrapper script enforces this; the proposed hook config would make it automatic.
References
- Issue #38 (exec bit fix): https://staging.musehub.ai/gabriel/musehub/issues/38
- Repo where this pattern was developed: https://staging.musehub.ai/aaronrene/knowtation
- Wrapper script:
scripts/muse-bridge-deploy.shinaaronrene/knowtation