ADR 0004: Public Real History With Private iOS Repo
- Status: Accepted
- Date: 2026-07-05
- Supersedes: the sanitized-snapshot public mirror (a GitHub Action that
republished each
mastertree as a singlegithub-actions[bot]commit).
Context
The public repository should carry Clankie's real commit history — real authors, dates, and messages — not a bot-authored snapshot. GitHub repository visibility is repository-wide: every reachable Git object in a public repo is public, so the private iOS app cannot live as a directory in the public repository, and its source cannot survive anywhere in the public history.
The iOS app has been renamed and rewritten across the project's life
(AgentRoomiOS → SwarmiOS → ClankieIOS native Swift → apps/mobile React
Native → clankie-ios/), so iOS source is scattered across many historical paths,
not just the current directory. The app consumes @volpestyle/clankie-contract as raw
TypeScript source (ADR 0002), so wherever the app builds it needs that source
reachable from the checkout.
Decision
Two repositories, no mirror:
Volpestyle/clankie(public): the monorepo itself, published with its real filtered history. Every historical iOS/mobile path family is removed from every commit withgit filter-repo; commits that were purely iOS collapse to empty and are pruned, mixed commits keep their message and their non-iOS changes. Authorship, dates, and messages are preserved. Work is pushed here directly.Volpestyle/clankies(private): the iOS app (official title Clankies). It carries the public monorepo as a git submodule and globsclankie-contractfrom inside it, so it consumes contract as raw source (ADR 0002 preserved) with no registry publish. Because the submodule is public, EAS needs no extra credentials. Its TestFlight/EAS release lane lives here.Volpestyle/clanky-internal(private archive): the pre-split full-history checkout is retained, untouched, as the archive of record. Every dropped legacy commit — including the native-Swift iOS eras — remains recoverable there. It is no longer a working repo and no longer mirrors anything.
Before publishing, the filtered public history is secret-scanned in full
(gitleaks) and audited to confirm no iOS/mobile path survives in any commit.
The initial publish is a one-time force-push over the old snapshot history.
Publishing is direct: there is no export/scrub step on the normal path. The old
Public Export workflow, scripts/prepare-public-export.sh, and
docs/public-export.md are removed.
flowchart LR
internal["clanky-internal<br/>private full-history archive"]
public["Volpestyle/clankie<br/>public · real filtered history · no iOS"]
clankies["Volpestyle/clankies<br/>private iOS app"]
testflight["EAS production build<br/>TestFlight submit"]
internal -. "one-time filter + audit + publish" .-> public
internal -. "one-time extract" .-> clankies
public -->|"git submodule → clankie-contract source"| clankies
clankies --> testflight
Consequences
- The public repo shows real authorship and history; no bot snapshot commits.
- Private mobile source is absent from the public tree and every public commit.
- The iOS ↔
clankie-contractdependency is preserved through a submodule, with no package publish and no change to contract's raw-source model. - Public history is lossy wherever iOS was involved (pure-iOS commits vanish,
mixed commits show only their non-iOS half); the full record stays in
clanky-internal. - Any future history rewrite (adding a path to strip, scrubbing a secret) must be re-filtered, re-scanned, and force-pushed, invalidating downstream clones.
- Contributors and in-flight branches that straddle the split rebase their
backend parts onto
clankie's history and their iOS parts ontoClankies.
