docs/divergence-policy
Divergence policy: fabric and the public babysitter repository reference
Status: binding. Source of authority: docs/specs/platform-gaps/15-private-isolation-rename.md §1 (decision D17 in docs/specs/platform-gaps/00-intent.md). Executed by WP-RN-01 on 2026-09-28; cutover record in docs/specs/platform-gaps/phase0/watch-baseline.md.
Continue reading
Nearby pages in the same section.
Divergence policy: fabric and the public babysitter repository
Status: binding. Source of authority: docs/specs/platform-gaps/15-private-isolation-rename.md §1 (decision D17 in docs/specs/platform-gaps/00-intent.md). Executed by WP-RN-01 on 2026-09-28; cutover record in docs/specs/platform-gaps/phase0/watch-baseline.md.
a5c-ai/fabric (this repository) is the private product repository and the source of truth for all new work, including the entire t3code migration. The public a5c-ai/babysitter repository is a separate, open project that keeps its @a5c-ai/* npm names, its babysitter/<branch>/v* tags, its workflows and its docs site. Fabric is not a copy of it and does not track it.
1. Invariants (spec 15 §1.2, verbatim)
1. **No work package in any spec alters the public repo** — not its package names, not its publishing, not its tags, not its workflows. 2. Mirroring public→private **stops now**; fabric ceases to be a mirror and becomes a first-class diverged repository. 3. Upstream public fixes flow **only** by opportunistic cherry-pick (one-way, public→private). Private work never flows back. 4. Renamed packages are **never** published to public npmjs (D19; guards in §4.3).
Invariant 1 is absolute for every person and every automation working in this repository: never create, modify or delete a branch, tag, commit, pull request, release, setting, workflow or secret on a5c-ai/babysitter, not even a scratch one. Read-only access (git fetch, git ls-remote, gh api GET calls) is the only permitted interaction.
2. The `upstream` remote is fetch-only
Every clone of fabric that needs the public history configures the public repository as a remote named upstream with its push URL disabled:
git remote add upstream https://github.com/a5c-ai/babysitter.git
git remote set-url --push upstream no_push
git remote -v
# upstream https://github.com/a5c-ai/babysitter.git (fetch)
# upstream no_push (push)Rules:
- No fabric clone may carry a pushable remote for
a5c-ai/babysitter, under any remote name. - Local branches are never pushed to both repositories. A branch lives in exactly one of them.
git push upstream ...in any form is prohibited; theno_pushURL makes it fail mechanically.- CI runs that read public history add the remote the same way (see
.github/workflows/upstream-propagation-watch.yml), and the watch script refuses to run when the push URL is anything other thanno_push.
3. No wholesale merges from public history
Reconciling fabric with the public repository by merging branches is prohibited. This covers git merge upstream/<branch>, git merge origin/main-style reconciles whose second parent is a public head, git pull upstream <branch>, fast-forwards onto a public commit, and any scheduled or automated merge. There is no shared-history requirement between the two repositories going forward; conflicts are resolved by keeping fabric's version, never by contorting fabric to stay merge-clean (spec 15 §1.4).
4. Intake is cherry-pick-only, via `upstream-intake` pull requests
Public fixes are taken in opportunistically, one-way, by a maintainer who reviews git log upstream/main at their own cadence (spec 15 §1.4). Each intake:
- lands as a pull request labeled
upstream-intake; - lists the upstream SHA(s) it cherry-picks, the path map applied (public
@a5c-ai/*names and directories → the private names), and what was deliberately dropped; - is a
git cherry-pick(with-X find-renamesorgit format-patch+git apply --directory=<new>once directories have been renamed), never a merge; - resolves conflicts in fabric's favor by default.
Security fixes to the journal/replay/trust cluster are the priority intake class and are evaluated in the intake owner's next review pass (spec 15 §1.5). Fabric-side fixes are not pushed upstream.
The step-by-step intake procedure, the pull request template (.github/PULL_REQUEST_TEMPLATE/upstream-intake.md) and the CI guard (scripts/ci/public-push-guard.cjs, job public-push-guard in .github/workflows/ci.yml) are specified in docs/UPSTREAM-INTAKE.md (WP-RN-02). The guard fails any workflow or script in this repository that would make the public repository a push target; its self-test and the rehearsal intake are recorded in docs/specs/platform-gaps/phase0/intake-rehearsal.md.
5. Branch ruleset on `main` and `staging`
Historically the only path by which public commits reached fabric was a maintainer pushing the same local branches to both repositories, or merging a public head by hand. That path is closed by the GitHub ruleset protect-main-staging (id 24103129) on a5c-ai/fabric:
- target:
refs/heads/main,refs/heads/staging; enforcement: active; - rules:
deletion(no branch deletion),non_fast_forward(no force-push),pull_request(changes land only through a pull request with at least one approving review, stale reviews dismissed on push; merge, squash and rebase merges allowed); - bypass: repository administrators only (
RepositoryRole5, modealways), so the sole maintainer cannot be locked out; bypasses are audited by GitHub.
Inspect: gh api repos/a5c-ai/fabric/rulesets/24103129.
6. Propagation watch
.github/workflows/upstream-propagation-watch.yml runs scripts/ci/upstream-propagation-watch.sh daily (17 3 * * *, UTC), on demand, and on any push that changes the watch's own files (workflow, script, baseline). It fetches the public heads over the fetch-only remote, computes the set of public commits that post-date the cutover baseline (docs/specs/platform-gaps/phase0/watch-baseline.json plus the full snapshot public-heads-baseline.txt), and fails if any such commit is reachable from any refs/remotes/origin/* branch or tag of fabric without a merged upstream-intake pull request that contains it. The run is read-only: permissions: contents: read, pull-requests: read, no push URL, no writes.
The scheduled trigger takes effect once the workflow is on the default branch; until then it is run with gh workflow run upstream-propagation-watch.yml -R a5c-ai/fabric --ref <branch>.
Acceptance criterion AC1(b) of WP-RN-01 requires an observation window of at least seven days that contains at least one post-cutover public commit; the watch status is tracked in docs/specs/platform-gaps/phase0/watch-baseline.md.
7. Rollback
Each guard is independently reversible; none of them touches the public repository, so there is nothing to roll back there.
| Guard | Rollback (do not run casually) |
|---|---|
| Branch ruleset | gh api -X DELETE repos/a5c-ai/fabric/rulesets/24103129 |
| Propagation watch | gh workflow disable upstream-propagation-watch.yml -R a5c-ai/fabric (or revert the commit adding the workflow) |
| Fetch-only remote | git remote set-url --push upstream https://github.com/a5c-ai/babysitter.git (re-enables pushes to the public repo; prohibited by invariant 1) |
publish.yml header, README role statement, this document | git revert of the WP-RN-01 commit(s) |