brink/docs/PUBLISHING.md at main · JavaDerek/brink · GitHub
Skip to content

Latest commit

 

History

History
137 lines (106 loc) · 5.68 KB

PUBLISHING.md

File metadata and controls

137 lines (106 loc) · 5.68 KB

Publishing

This project lives in more than one repository, and which one you are looking at changes what you may do with it. This is the map.

The repositories

  private/brink ─────────── the workshop. Where work happens.
       │                    Agent config, playtest databases, drafts.
       │                    Never published as-is.
       │
       ├── tree copy ────►  public/brink ──── the game. MIT, issues, stars.
       │  (scripts/publish.sh)                Standalone: NOT a GitHub fork,
       │                                      so it stays discoverable and
       │                                      owns its own issue tracker.
       │
       └── push offer/* ─►  <you>/dmcp ────►  shawnrushefsky/dmcp
                            a real GitHub     upstream. Receives PRs.
                            fork. Exists only
                            to carry offer/*
                            branches and open
                            pull requests.

Four repositories, two routes out, and they do not touch each other.

Why the public repo shares no history

The public repo starts from a single squashed commit. It is not a branch of this one and never will be — git push public main cannot work and is not meant to.

That is a deliberate trade. It gives up the commit history, which in this repository is unusually good documentation: most messages carry the playtest that prompted the change, what was measured, and why a test was reversed rather than loosened. What it buys is that nothing in the private history can ever leak, which matters because a great deal of it predates anyone thinking about publication. A scrub can miss something. An absent history cannot.

Practically: publishing copies a tree and makes a commit. History accumulates in the public repo from its first release forward, so the archaeology starts there.

Why offer/* cannot go through the public repo

Two independent reasons, either of which is sufficient:

  1. The history is wrong. The offer/* branches are cut from upstream/main and carry DMCP's own history. Pushing them into a repo whose root is a squashed commit would either drag all of DMCP's history in beside the squash, or be unmergeable.
  2. GitHub will not allow the pull request. Pull requests are only possible between repositories in the same fork network. A standalone repo — however much history it shares — cannot target shawnrushefsky/dmcp. It has to be an actual GitHub fork.

So generic work travels private → your fork of DMCP → PR, and the public repo is not on that path. See IMPROVEMENTS-TO-DMCP.md for what is on those branches and why each one is generic.

What stays in the workshop

Short on purpose. A long exclude list means the published tree drifts from the one that is actually tested, and then a release breaks in a way no test saw.

Path Why
.claude/ Agent plugin configuration and worktrees. Tooling, not project.
scripts/publish.sh Publishing the publisher is just confusing.
data/, .env, dist/ Already gitignored, so git archive cannot see them.

Everything else git tracks is published, including CLAUDE.md and the design brief — both are good documentation and both have been scrubbed of anything machine-specific.

The guard is a test, not a checklist

src/__tests__/publishHygiene.test.ts fails CI if a private machine name, a home directory, an account name, a raw LAN address, or the name of an unrelated project appears anywhere in the tracked tree. src/gm/__tests__/repoCredentialHygiene.test.ts does the same for credentials.

This is deliberately not a step in the publish script. A hostname committed on a Tuesday is published on the Thursday, and nobody re-reads a checklist — but everybody notices a red build. When that test was first written it immediately found six files a careful manual sweep had missed, including one written ten minutes earlier by the person doing the sweeping.

Every forbidden pattern carries the reason it is forbidden, so the failure explains itself and a future contributor has something to argue with other than a bare list of words.

One-time setup

# The public repo: create it EMPTY on GitHub -- no README, no licence, no
# .gitignore -- so the first publish is the first commit.
git clone git@github.com:<you>/brink-public.git ../brink-public

# The DMCP fork: use GitHub's fork button on shawnrushefsky/dmcp. It has to be
# a real fork or pull requests are impossible.
git remote add dmcp-fork git@github.com:<you>/dmcp.git

Publishing a release

./scripts/publish.sh ../brink-public "release: what changed" --dry-run   # look first
./scripts/publish.sh ../brink-public "release: what changed"
cd ../brink-public && git log -1 --stat && git push

The script refuses to run on a dirty tree, and runs the full suite, lint and typecheck before copying anything. It uses git archive, so only tracked files can reach the public tree, and rsync --delete, so a file removed here is removed there.

Offering something upstream

git fetch upstream
git checkout -b offer/<topic> upstream/main
# ... generic mechanism only. No geopolitical content in code, tests or
#     comments -- use neutral fixtures ("grain", "treasury", "population").
git push dmcp-fork offer/<topic>
# then open the PR from <you>/dmcp against shawnrushefsky/dmcp

Before pushing, check the branch really is clean:

git diff upstream/main...offer/<topic> | grep -icE "defcon|prestige|flashpoint|crisis|seat"

Zero is the only acceptable answer, and all four existing offer/* branches return it.