Once repo_create (#13) and repo_mirror_push (#16) are implemented, they should be tested together end-to-end to verify the full Gitea → GitHub mirror flow before implementing the composite project_create tool in hyperguild.
Delete from GitHub manually (repo_delete only covers Gitea).
Success criteria
GitHub repo created automatically via mirror, no manual GitHub API call needed
Commits sync within 60s
Flow works end-to-end from claude.ai chat session
Dependency
Requires #13 (repo_create) and #16 (repo_mirror_push) to be implemented first.
Also requires #11 (repo_delete) for cleanup step.
Why this matters
This is the foundation of hyperguild new-project — the entire project creation flow
depends on this mirror mechanism working reliably from claude.ai.
## Summary
Once repo_create (#13) and repo_mirror_push (#16) are implemented, they should be tested together end-to-end to verify the full Gitea → GitHub mirror flow before implementing the composite `project_create` tool in hyperguild.
## Test sequence (from claude.ai chat)
**Step 1: Create test repo on Gitea**
```
repo_create(owner=mathias, name=test-mirror-flow, private=true, auto_init=true)
```
Expected: repo appears at gitea.d-ma.be/mathias/test-mirror-flow
**Step 2: Configure push mirror to GitHub**
```
repo_mirror_push_add(
owner=mathias,
name=test-mirror-flow,
remote_address=https://github.com/mathiasb/test-mirror-flow.git,
remote_username=mathiasb,
remote_password=<PAT>,
sync_on_commit=true
)
```
Expected: mirror configured in Gitea settings
**Step 3: Verify GitHub repo appears**
- Wait up to 60s
- Check github.com/mathiasb/test-mirror-flow exists
- Verify initial commit is present
**Step 4: Test sync on commit**
```
file_write_branch(name=test-mirror-flow, path=TEST.md, content="mirror test", message="test: verify mirror sync", branch=main)
```
Expected: commit appears on GitHub within 60s
**Step 5: Cleanup**
```
repo_delete(owner=mathias, name=test-mirror-flow, confirm=test-mirror-flow)
```
Delete from GitHub manually (repo_delete only covers Gitea).
## Success criteria
- [ ] GitHub repo created automatically via mirror, no manual GitHub API call needed
- [ ] Commits sync within 60s
- [ ] Flow works end-to-end from claude.ai chat session
## Dependency
Requires #13 (repo_create) and #16 (repo_mirror_push) to be implemented first.
Also requires #11 (repo_delete) for cleanup step.
## Why this matters
This is the foundation of `hyperguild new-project` — the entire project creation flow
depends on this mirror mechanism working reliably from claude.ai.
Parked for now — capturing prerequisites so this is ready to run later.
GitHub PAT scope needed
The PAT is the push credential for the Gitea → GitHub push-mirror (passed as remote_password).
Classic PAT: repo scope — simplest single choice. Covers git-push to the target repo (private or public) AND creating the repo via the GitHub API. (public_repo alone suffices only if the mirror target is always public.)
Fine-grained PAT equivalent: target repo(s) → Contents: Read and write (push); add Administration: Read and write only if the PAT must also create repos.
Secret handling: consume the PAT only inside op run/env vars — never in argv, logs, or a committed file.
Correction: mirror does NOT auto-create the GitHub repo
Step 3's success criterion ("GitHub repo created automatically via mirror, no manual GitHub API call needed") is incorrect. git push does not create repositories on GitHub — a Gitea push-mirror pushes to an existing remote. If github.com/<user>/<repo> doesn't exist, the mirror push fails.
So the corrected flow needs a pre-create step before configuring the mirror:
Step 1b (new): create the GitHub repo first — e.g. POST https://api.github.com/user/repos {"name":"test-mirror-flow","private":true} with the repo-scoped PAT (or create it manually in the GitHub UI). Only then does Step 2 (repo_mirror_push_add) have a target to push into.
Updated test sequence
repo_create on Gitea (already works — verified #33).
1b. Create the empty GitHub repo via API (or UI) — the mirror won't create it.
file_write_branch on Gitea → commit appears on GitHub within ~60s (sync-on-commit).
Cleanup: repo_delete (Gitea) + delete the GitHub repo manually (repo_delete only covers Gitea).
Still blocked on
A repo-scoped GitHub PAT for mathiasb, provisioned into the environment (1Password → env). Once that's available this is runnable end-to-end.
Parked for now — capturing prerequisites so this is ready to run later.
## GitHub PAT scope needed
The PAT is the **push credential** for the Gitea → GitHub push-mirror (passed as `remote_password`).
- **Classic PAT: `repo` scope** — simplest single choice. Covers git-push to the target repo (private or public) AND creating the repo via the GitHub API. (`public_repo` alone suffices only if the mirror target is always public.)
- **Fine-grained PAT equivalent:** target repo(s) → **Contents: Read and write** (push); add **Administration: Read and write** only if the PAT must also create repos.
Secret handling: consume the PAT only inside `op run`/env vars — never in argv, logs, or a committed file.
## Correction: mirror does NOT auto-create the GitHub repo
Step 3's success criterion ("GitHub repo created automatically via mirror, no manual GitHub API call needed") is **incorrect**. `git push` does not create repositories on GitHub — a Gitea push-mirror pushes to an **existing** remote. If `github.com/<user>/<repo>` doesn't exist, the mirror push **fails**.
So the corrected flow needs a **pre-create step** before configuring the mirror:
**Step 1b (new): create the GitHub repo first** — e.g.
`POST https://api.github.com/user/repos {"name":"test-mirror-flow","private":true}` with the `repo`-scoped PAT (or create it manually in the GitHub UI). Only then does Step 2 (`repo_mirror_push_add`) have a target to push into.
## Updated test sequence
1. `repo_create` on Gitea (already works — verified #33).
1b. **Create the empty GitHub repo** via API (or UI) — the mirror won't create it.
2. `repo_mirror_push_add(..., remote_password=<PAT>, sync_on_commit=true)`.
3. Verify commits appear on GitHub within ~60s.
4. `file_write_branch` on Gitea → commit appears on GitHub within ~60s (sync-on-commit).
5. Cleanup: `repo_delete` (Gitea) + delete the GitHub repo manually (repo_delete only covers Gitea).
## Still blocked on
A `repo`-scoped GitHub PAT for `mathiasb`, provisioned into the environment (1Password → env). Once that's available this is runnable end-to-end.
Pre-created GitHub mathiasb/test-mirror-flow (private) via POST /user/repos — required, see finding #1.
Configured push-mirror via gitea REST (POST .../push_mirrors, sync_on_commit=true) — see finding #3. → 200.
Triggered POST .../push_mirrors-sync → initial commit appeared on GitHub (count=1, "Initial commit"). ✓
Wrote TEST.md on Gitea main → auto-propagated to GitHub within 30s via sync_on_commit (count=2, "test: verify mirror sync-on-commit", TEST.md 200 on GitHub). ✓
Cleanup: Gitea repo deleted. GitHub repo delete → 403 (PAT lacks delete_repo) → left for manual deletion.
Findings (correct the original assumptions):
Mirror does NOT auto-create the GitHub repo (as flagged earlier) — the GitHub repo must be pre-created; git push to a non-existent GitHub repo fails.
Existing commits don't push on mirror-add — configuring the mirror does not retroactively push the current HEAD; you must trigger push_mirrors-sync once (or make a new commit). sync_on_commit then handles subsequent commits automatically.
repo_mirror_push MCP tool takes remote_password as a plain arg → the PAT would land in the tool-call transcript (→ claudewatcher → brain). I deliberately used the gitea REST API inside op run instead so the PAT stayed in the subprocess. Filed a separate security issue to fix the tool's secret handling.
GitHub repo cleanup needs delete_repo scope (this PAT has read:org, repo, workflow).
Manual cleanup for you: delete github.com/mathiasb/test-mirror-flow (my PAT couldn't — no delete_repo).
Closing — mirror flow proven.
✅ **Verified end-to-end 2026-07-04** with a valid `repo`-scoped PAT. The Gitea → GitHub push-mirror works.
**What ran (all cleaned up):**
1. `repo_create` → Gitea `mathias/test-mirror-flow` (private, auto-init). ✓
2. **Pre-created** GitHub `mathiasb/test-mirror-flow` (private) via `POST /user/repos` — required, see finding #1.
3. Configured push-mirror via gitea REST (`POST .../push_mirrors`, `sync_on_commit=true`) — see finding #3. → 200.
4. Triggered `POST .../push_mirrors-sync` → initial commit appeared on GitHub (`count=1, "Initial commit"`). ✓
5. Wrote `TEST.md` on Gitea `main` → **auto-propagated to GitHub within 30s** via `sync_on_commit` (`count=2, "test: verify mirror sync-on-commit"`, `TEST.md` 200 on GitHub). ✓
6. Cleanup: Gitea repo deleted. GitHub repo delete → **403** (PAT lacks `delete_repo`) → left for manual deletion.
**Findings (correct the original assumptions):**
1. **Mirror does NOT auto-create the GitHub repo** (as flagged earlier) — the GitHub repo must be pre-created; `git push` to a non-existent GitHub repo fails.
2. **Existing commits don't push on mirror-add** — configuring the mirror does not retroactively push the current HEAD; you must trigger `push_mirrors-sync` once (or make a new commit). `sync_on_commit` then handles subsequent commits automatically.
3. **`repo_mirror_push` MCP tool takes `remote_password` as a plain arg** → the PAT would land in the tool-call transcript (→ claudewatcher → brain). I deliberately used the **gitea REST API inside `op run`** instead so the PAT stayed in the subprocess. Filed a separate security issue to fix the tool's secret handling.
4. GitHub repo cleanup needs `delete_repo` scope (this PAT has `read:org, repo, workflow`).
**Manual cleanup for you:** delete `github.com/mathiasb/test-mirror-flow` (my PAT couldn't — no `delete_repo`).
Closing — mirror flow proven.
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.
Summary
Once repo_create (#13) and repo_mirror_push (#16) are implemented, they should be tested together end-to-end to verify the full Gitea → GitHub mirror flow before implementing the composite
project_createtool in hyperguild.Test sequence (from claude.ai chat)
Step 1: Create test repo on Gitea
Expected: repo appears at gitea.d-ma.be/mathias/test-mirror-flow
Step 2: Configure push mirror to GitHub
Expected: mirror configured in Gitea settings
Step 3: Verify GitHub repo appears
Step 4: Test sync on commit
Expected: commit appears on GitHub within 60s
Step 5: Cleanup
Delete from GitHub manually (repo_delete only covers Gitea).
Success criteria
Dependency
Requires #13 (repo_create) and #16 (repo_mirror_push) to be implemented first.
Also requires #11 (repo_delete) for cleanup step.
Why this matters
This is the foundation of
hyperguild new-project— the entire project creation flowdepends on this mirror mechanism working reliably from claude.ai.
Parked for now — capturing prerequisites so this is ready to run later.
GitHub PAT scope needed
The PAT is the push credential for the Gitea → GitHub push-mirror (passed as
remote_password).reposcope — simplest single choice. Covers git-push to the target repo (private or public) AND creating the repo via the GitHub API. (public_repoalone suffices only if the mirror target is always public.)Secret handling: consume the PAT only inside
op run/env vars — never in argv, logs, or a committed file.Correction: mirror does NOT auto-create the GitHub repo
Step 3's success criterion ("GitHub repo created automatically via mirror, no manual GitHub API call needed") is incorrect.
git pushdoes not create repositories on GitHub — a Gitea push-mirror pushes to an existing remote. Ifgithub.com/<user>/<repo>doesn't exist, the mirror push fails.So the corrected flow needs a pre-create step before configuring the mirror:
Step 1b (new): create the GitHub repo first — e.g.
POST https://api.github.com/user/repos {"name":"test-mirror-flow","private":true}with therepo-scoped PAT (or create it manually in the GitHub UI). Only then does Step 2 (repo_mirror_push_add) have a target to push into.Updated test sequence
repo_createon Gitea (already works — verified #33).1b. Create the empty GitHub repo via API (or UI) — the mirror won't create it.
repo_mirror_push_add(..., remote_password=<PAT>, sync_on_commit=true).file_write_branchon Gitea → commit appears on GitHub within ~60s (sync-on-commit).repo_delete(Gitea) + delete the GitHub repo manually (repo_delete only covers Gitea).Still blocked on
A
repo-scoped GitHub PAT formathiasb, provisioned into the environment (1Password → env). Once that's available this is runnable end-to-end.✅ Verified end-to-end 2026-07-04 with a valid
repo-scoped PAT. The Gitea → GitHub push-mirror works.What ran (all cleaned up):
repo_create→ Giteamathias/test-mirror-flow(private, auto-init). ✓mathiasb/test-mirror-flow(private) viaPOST /user/repos— required, see finding #1.POST .../push_mirrors,sync_on_commit=true) — see finding #3. → 200.POST .../push_mirrors-sync→ initial commit appeared on GitHub (count=1, "Initial commit"). ✓TEST.mdon Giteamain→ auto-propagated to GitHub within 30s viasync_on_commit(count=2, "test: verify mirror sync-on-commit",TEST.md200 on GitHub). ✓delete_repo) → left for manual deletion.Findings (correct the original assumptions):
git pushto a non-existent GitHub repo fails.push_mirrors-synconce (or make a new commit).sync_on_committhen handles subsequent commits automatically.repo_mirror_pushMCP tool takesremote_passwordas a plain arg → the PAT would land in the tool-call transcript (→ claudewatcher → brain). I deliberately used the gitea REST API insideop runinstead so the PAT stayed in the subprocess. Filed a separate security issue to fix the tool's secret handling.delete_reposcope (this PAT hasread:org, repo, workflow).Manual cleanup for you: delete
github.com/mathiasb/test-mirror-flow(my PAT couldn't — nodelete_repo).Closing — mirror flow proven.