Files
vitya 8d7af3212b feat(private-dev-public-publish): fill skill body + review hardening v0.2.0
Second pass: filled the empty skeleton (When-to-use, Inputs, Steps, Failure
modes, Side effects, What-NOT) from the design archive
(.workshop/.archive/2026-05-29-skill-private-dev-public-publish.md). 0.1.0 -> 0.2.0.

Non-implementer subagent review found 3 findings, all fixed in this same increment:
- Step 5 dev->pub copy had no meta-exclusion -> would leak .wiki/.tasks/CLAUDE.md
  into the PUBLIC fork. Added explicit meta-exclude + .gitignore backstop +
  git-status check, plus a 4th failure mode for the leak.
- pub-folder origin was never established before Step 5 pushed to it -> Step 4 now
  clones the GitHub fork into pub (origin=fork, upstream=canonical).
- Step 3 "same base" was unmechanized -> clone fork, add gitea remote, push base.

Closes review task: all findings filed and resolved; no follow-ups needed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-29 17:07:36 +03:00

5.7 KiB

name, version, description
name version description
private-dev-public-publish 0.2.0 Use when setting up or maintaining a publishable open-source port/fork that should be developed privately but published cleanly — messy development on a PRIVATE Gitea repo (with `.wiki/`+`.tasks/` inside), and a curated COPY of finished work into a PUBLIC GitHub fork that preserves upstream lineage (stays a fork, keeps attribution; GPL-clean). Triggers - «опубликовать форк/порт на гитхаб», «разработку держать приватно, релиз публичный», «приватный гитеа + публичный гитхаб», «publish a fork without exposing dev history», «curated publish to GitHub», «как правильно форкнуть open-source для публикации». NOT for purely-private projects, purely-public open development, or greenfield bootstrap (use project-bootstrap).

private-dev-public-publish

Two-repo topology for a publishable open-source port/fork: develop messily on a private Gitea repo (with .wiki/ + .tasks/ inside it), then publish only curated, finished work to a public GitHub fork that stays a real fork of upstream — so attribution and lineage hold and the dev history (experiments, dead-ends) never goes public.

Role Where Contents Visibility
Dev private Gitea repo upstream base + all development + .wiki/+.tasks/+CLAUDE.md; messy history private
Publish public GitHub fork code only, curated clean commits, upstream lineage (stays a fork) public

You work in the Gitea (dev) folder; matured work is copied as files into the GitHub (pub) folder → one clean commit → push.

When to use

  • You're porting/forking an open-source project and intend to publish it, but the development is exploratory (experiments, dead-ends, reverts) you don't want in public history.
  • You want attribution and licence lineage to hold (the public repo must stay a real fork of upstream).
  • You need a place for .wiki/ + .tasks/ + CLAUDE.md that never ships publicly.

Why curated publication is legitimate (GPL/OSI): the licence requires the source of what you distribute (the release), not your development history. A curated publish is clean as long as the public repo (1) stays a fork of upstream (lineage = attribution) and (2) contains the complete buildable source of the release.

Inputs

  • Upstream — the canonical project you're porting/forking (URL + the specific commit/tag that is your real base).
  • Public target — GitHub account/org for the fork.
  • Private dev host — Gitea repo (the primary working clone; projects-meta points here, not at GitHub).

Steps

  1. Establish provenance. Identify which upstream commit/fork is your real base. If history was lost, content-match the tree; find the author's PR/fork for the fix you're carrying so attribution is correct.
  2. Fork canonical upstream on GitHub (gh repo fork) → the public showcase. upstream remote = the original. Bring in needed third-party fixes via cherry-pick (preserves authorship) or merge.
  3. Create the private Gitea dev repo on the same base: clone the GitHub fork locally, add the Gitea repo as a remote, and push the base there — this carries the upstream lineage into the private repo. Put meta (.wiki/+.tasks/+CLAUDE.md) inside it. Trap: a global ~/.config/git/ignore (core.excludesfile) may silently ignore .wiki//.tasks/ → add local !-negation lines in the repo's .gitignore.
  4. Two local folders: dev (the Gitea private clone — your primary working copy) and pub (a clone of the GitHub fork; its origin = your fork, upstream = canonical).
  5. Publish: copy the code files dev→pub, excluding meta (.wiki/, .tasks/, CLAUDE.md, and any private notes — these must never reach the public fork; also list them in the pub repo's .gitignore as a backstop). Run git status in pub to confirm no meta is staged. Make one clean commit, push origin (github). Never reconstruct history — "copy" means lay files into the fork's tree.

Failure modes

  • Public folder is no longer a fork (rootless snapshot) → attribution/lineage lost. Do NOT start history from scratch; "copy" = place files into the fork's tree, keep the fork relationship.
  • Private meta copied into the public fork (.wiki//.tasks//CLAUDE.md leak) → dev internals exposed publicly. The dev→pub copy MUST exclude meta; keep those paths in the pub repo's .gitignore and check git status in pub before committing.
  • meta silently not committed in the private repo (global gitignore swallows .wiki//.tasks/) → verify with git check-ignore .wiki .tasks; add negation lines if matched.
  • Release without complete source in the public repo → GPL violation. The public release must be fully buildable from what's published.

Side effects

  • Creates a public GitHub fork (outward-facing — visible to anyone).
  • Creates a private Gitea repo and two local working clones.
  • Touches git remotes, gh/GitHub API, and potentially tokens — confirm before any push or repo-visibility change.

What NOT to do

  • Don't use this for a purely-private project (no intent to publish) — no second repo needed.
  • Don't use it for purely-public open development (nothing to hide) — a normal fork+dev on GitHub is enough.
  • Don't use it for greenfield bootstrap of a new project with no upstream — that's project-bootstrap.
  • Don't create a standalone meta repo — meta lives inside the private dev repo. A separate meta repo is only for when the dev repo itself is public.
  • Don't publish by pushing dev history or by initializing a fresh repo — both break lineage.