Make infrastructure the GitHub <=> Forgejo coordination hub #489
Labels
No labels
burndown-2026-06
coherence-core
consult
headless
interactive
P0
P1
P2
P3
P4
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
coilyco-flight-deck/infrastructure#489
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Kai's direction: infrastructure should be the GitHub <=> Forgejo coordination hub.
Rationale:
coilysiren-github-mirrorandcoilysiren-forgejo-mirror.This should connect the existing narrower work:
coilyco-flight-deck/infrastructure#475- centralized GitHub mirror sync.coilyco-flight-deck/ward#823- GitHub <=> Forgejo command hub design.coilyco-flight-deck/ward#830andcoilysiren/inbox#184-coilysiren/*GitHub-authoritative migration.coilyco-flight-deck/ward#827- out-of-band tracker source and Shortcut shadowing.Proposed split:
Acceptance:
infrastructure#475becomes the first implementation slice or needs to be reframed.Auth/identity doc split filed as coilyco-flight-deck/infrastructure#492. The hub design should explicitly distinguish the Forgejo
coilyco-opsbot user from the GitHub App installation identity.🔎 ward agent advisor - cross-repo fan-out
ward agent advisor --harness codexran a one-shot standard research pass on this question:Recommendation
Treat infrastructure as the bridge control plane, ward as the typed command client, and inbox as policy only.
That matches what already exists in the repo better than pushing hub ownership into ward:
systemd/coilysiren-{forgejo,github}-mirror.*), the new safe reconcile script (scripts/coilysiren-mirror-reconcile.sh), and the staged Forgejo Actions workflow (.forgejo/workflows/mirror-sync.yml)scripts/github_app_token.py,ward exec github-app-token)push --mirrorpair is unsafe and being retired (skills/mirror-sync/SKILL.md)/substrate/ward/docs/compat-surface.md,/substrate/ward/README.md)Boundary
Infrastructure should own:
Ward should own:
ward ops bridge authoritative-side,mirror-status,divergent-refs,stale-syncs,map-issuecarry-prInbox should own:
coilysiren/*should route issues and close semanticsward#827Inbox should not own mirror state, schedules, or fleet credentials.
Key decisions
ward#830changescoilysiren/*toward GitHub-authoritative, so the hub needs a per-repo authority registry, not a namespace-wide assumption baked into scripts.infrastructure#475as the first implementation slice. The issue body still says "force-push main + tags", but this repo already contains a safer design that avoids default force-sync and auto-merges GitHub PR commits into Forgejo without force-pushing. The first slice should be: registry + read-only mirror status + stale-sync detection + the existing safe reconcile pilot. Do not start with a force-push fleet job.carry-pr, issue mapping, or Shortcut shadowing, land a status surface that answers: authoritative side, last sync age, head SHAs on both sides, and whether refs are in-sync / FF / diverged / conflicted.Recommended first commands / scripts
Infrastructure-backed implementation first:
bridge-repo-registry- outputs the authoritative mapping for one repo or the fleetbridge-mirror-status- reports authoritative side, both default-branch heads, and state (in-sync,forgejo-ahead,github-ahead,diverged,conflict)bridge-stale-syncs- reports repos whose last successful reconcile is older than thresholdbridge-map-work-item- initially read-only mapping stub for Forgejo issue / GitHub issue / GitHub PR / external tracker idsWard wrapper surface after that:
ward ops bridge authoritative-side <owner/repo>ward ops bridge mirror-status [owner/repo]ward ops bridge divergent-refs [owner/repo]ward ops bridge stale-syncsward ops bridge map-issue <ref>Options considered
Option A - ward owns the hub
Rejected.
ward is the right place for verbs and dispatch, but the wrong place for fleet-specific state, timers, SSM-backed creds, and ops audits. That would duplicate logic already living in infrastructure and violate the repo split the issue body is trying to enforce.
Option B - infrastructure owns everything including user-facing verbs
Rejected.
That would make operators shell directly into infra scripts and leave ward blind to a core cross-forge capability. The better split is infrastructure owns facts and jobs, ward owns the stable command UX.
Option C - infrastructure owns hub state, ward consumes it, inbox owns policy
Recommended.
This is closest to the current code and lowest-risk migration path.
Open questions
coilysiren/*likely says GitHub for both, but the schema should not assume they are identical.map-issue? Recommendation: start with repo/ref metadata and links only. Defer durable bidirectional issue sync until after authority policy is settled.Risks
skills/mirror-sync/SKILL.mdshould stay the source of truth.coilysiren/*becomes GitHub-authoritative.push --mirrordesign can overwrite divergent history. The repo already contains the safer reconcile path, so the design should bless that and retire the older model.Advisory close
The shortest path is:
infrastructure#475as the first infra slice: repo registry, mirror status, stale-sync detection, safe reconcile pilot.coilysiren/inbox#184plus a focused follow-up forcoilysiren/*authority and tracker-migration rules.I would explicitly defer
carry-prand Shortcut shadow writes until the read-only status surface and per-repo authority registry are landed.The work spans multiple repos, so it was filed as 2 tracked issue(s), in dependency order:
Researched and posted automatically by
ward agent advisor --harness codex(ward#424). This is one-shot research, not a carried change - verify before acting on it.— Codex, via
ward agentThis ticket pushed a bunch of logic into coilyco-flight-deck/ward#834 that definitely does not belong there. ward shouldn't be hardcoding the expectation of syncing git state between platforms
🔎 ward agent advisor
ward agent advisor --harness codexran a one-shot standard research pass on this question:Recommendation
Keep this issue as the hub-boundary decision and keep the first implementation slice in infrastructure, not ward.
Kai's correction on
ward#834is right: ward should not hardcode git sync expectations between Forgejo and GitHub. The durable split should be:coilysiren/*. It should not own forge credentials, mirror state, or schedulers.Repo evidence
The current infrastructure clone already supports that boundary:
.ward/ward.yamlexposesforgejo-github-mirror-sync,forgejo-admin-token, andgithub-app-tokenas infra verbs.scripts/forgejo_github_mirror_sync.pyand.forgejo/workflows/github-mirror-sync.ymlare a fleet-level Forgejo-to-GitHub mirror path. They still assume Forgejo is canonical and force-update GitHub.skills/mirror-sync/SKILL.md,.forgejo/workflows/mirror-sync.yml, andscripts/coilysiren-mirror-reconcile.shdocument a safer reconcile path that avoids force-push and handles GitHub PR commits, but it still assumes Forgejo is canonical.docs/forgejo-github-automation-identity.mdalready makes the key identity distinction requested byinfrastructure#492: Forgejo automation is thecoilyco-opsbot user, while GitHub automation is a GitHub App installation token.docs/FEATURES.mdalready says infrastructure owns the identity split, GitHub App token helper, Forgejo bot grants, and fleet mirror pieces.That means the missing piece is not a ward-side design. The missing piece is an infrastructure-owned model that tells every caller what the bridge truth is for a repo.
Decisions
Per-repo authority must be explicit. Do not assume Forgejo-first globally.
coilyco-flight-deck/*,coilyco-bridge/*,coilyco-gaming/*,coilysiren/*, and special cases likecoilyco-flight-deck/homebrew-tapcan have different authority rules.Git authority and tracker authority must be separate fields. A repo can be GitHub-authoritative for git while still having Forgejo issues during migration, or vice versa. Shortcut shadowing should depend on tracker policy, not git mirror policy.
Status and writing must be separate. The first public contract should answer what is true, not change either forge. Write sync can come after the status model proves itself.
Infrastructure should publish the contract ward consumes. Ward may eventually offer
ward ops bridge ...commands, but those commands should shell out to infra-owned scripts, call an infra-owned endpoint, or read an infra-owned JSON schema. Ward should not duplicate the registry or encode sync direction.infrastructure#475should be reframed, not discarded. It is still the right first implementation track, but its acceptance should shift away from broad force-mirroring. The first slice should be registry + read-only status + stale detection + a decision on how to retire or quarantine the force-push mirror path.Recommended first infra commands or scripts
These should live in infrastructure first:
bridge-registry- validate and print the desired repo bridge registry. Fields should include Forgejo repo, GitHub repo, git authority, tracker authority, mirror mode, default branch, PR/direct-to-main policy, and credential identity.bridge-authoritative-side <repo>- answer git authority and tracker authority for one repo.bridge-mirror-status [repo]- fetch both forges and report default-branch SHAs plus state:in-sync,forgejo-ahead,github-ahead,diverged,missing-github,missing-forgejo, orunknown.bridge-divergent-refs [repo]- list refs where both sides have advanced incompatibly. Start with default branch only, then expand to tags and release branches once the default-branch model is stable.bridge-stale-syncs- report repos whose last successful status or reconcile check is older than a threshold.bridge-map-work-item <ref>- read-only mapping from Forgejo issue, GitHub issue, GitHub PR, or external tracker id to known related refs. Start as registry-backed metadata and links only. Do not implement bidirectional tracker sync in the first slice.Ward follow-up should wait until these infra commands exist. Then ward's issue can be narrowed to thin wrappers like
ward ops bridge mirror-status, with no embedded sync rules.Options
Option A: ward owns the bridge hub
Reject. This is the failure mode Kai flagged. Ward is reusable command and dispatch machinery. It should not own fleet-specific repo authority, sync schedules, SSM-backed credentials, or mirror audits.
Option B: inbox owns the bridge hub
Reject. Inbox is the right place for personal-work policy and migration decisions, but it is the wrong layer for fleet credentials, scheduled jobs, and git divergence checks.
Option C: infrastructure owns the hub, ward consumes it, inbox owns policy
Recommend. It matches the existing repo ownership and keeps the reusable ward surface clean.
Option D: keep
infrastructure#475as a force mirror rolloutReject as written. The existing
forgejo_github_mirror_sync.pypath force-pushes and assumes Forgejo canonical. That is too narrow for GitHub-authoritative migration and risky under divergence. Keep the issue, but reframe it as the first read-only bridge-control-plane slice.Open questions
coilyco-flight-deck/homebrew-tap.coilysiren/*migration policy? Recommendation: inbox decides policy, infrastructure stores only the resulting per-repo authority fields.ward#834? Recommendation: rewrite it to depend on the infra contract, or close it if it already contains bridge-state ownership that belongs here.Risks
github-mirror-sync, andmirror-synccan race if more than one writer is active.forgejo_github_mirror_sync.pyforce-updates GitHub and does not fit a mixed-authority future.coilysiren/*GitHub-authoritative migration.coilyco-opsand the GitHub App installation are different actors with different rotation and permission models.Advisory close
Use this issue to ratify the boundary. Reframe
infrastructure#475as the first infra implementation slice: tracked bridge registry, read-only mirror status, divergent-ref detection, stale-sync reporting, and an explicit plan to retire or quarantine unsafe force mirror paths. Do not add more bridge-state logic to ward until infrastructure publishes the contract ward should consume.Researched and posted automatically by
ward agent advisor --harness codex(ward#179). This is one-shot research, not a carried change - verify before acting on it.— Codex, via
ward agent