Skip to content

docs(#143): document split-portfolio mode + add /setup privacy gate#144

Merged
atlas-apex merged 1 commit into
devfrom
feature/GH-143-split-portfolio-mode
May 3, 2026
Merged

docs(#143): document split-portfolio mode + add /setup privacy gate#144
atlas-apex merged 1 commit into
devfrom
feature/GH-143-split-portfolio-mode

Conversation

@atlas-apex

Copy link
Copy Markdown
Collaborator

Summary

Closes the silent privacy bug for adopters on GitHub Free with any private project. Today's docs/multi-project.md instructs them to fork apexyard and commit apexyard.projects.yaml + projects/<name>/ to that fork — but a fork of a public repo cannot be made private on GitHub Free, so private project names land on a public GitHub repo the moment they push.

This PR is the docs + setup-question minimum-viable starter:

  • Documents the two supported modes (single-fork default; split-portfolio for adopters with privacy needs)
  • Adds an upfront privacy gate to /setup that branches on the adopter's plan + project mix
  • Walks through the split-portfolio setup step-by-step

The framework code refactor (portfolio: config block in onboarding.yaml + audit of every skill that hardcodes the registry path) is out of scope for this PR — tracked separately on #143. Until that lands, the split-portfolio mode works via manual symlinks (ln -s ../portfolio/apexyard.projects.yaml ...) which are documented here.

Targets dev per the apexyard release-cut model.

What changes

docs/multi-project.md (+170 lines, -3):

  • New "Two setup modes — pick the one that matches your privacy needs" section before TL;DR, with a side-by-side comparison table and the explicit trip-wire callout
  • TL;DR retitled TL;DR — single-fork mode (default) with a one-line pointer down
  • New "Split-portfolio mode — public framework + private portfolio" section with:
    • Layout diagram (~/ops/apexyard/ + ~/ops/portfolio/)
    • 7-step copy-pasteable setup walkthrough
    • Daily workflow + upstream-sync notes
    • Trade-offs (two repos, two clones per machine, one upstream-sync conflict path)
    • Migration recovery flow for adopters already in single-fork mode with private names pushed

.claude/skills/setup/SKILL.md (+42 lines):

  • Step 2a — privacy gate: asks once whether any projects are private + branches on the answer (all-public → single-fork; paid plan → single-fork; private + GitHub Free → split mode)
  • Step 2b — split-portfolio walk-through: interactive private-repo create + sibling clone + gitignore + symlink. Auto-detected if already in split mode (test -L apexyard.projects.yaml).
  • Explicit do-NOT-auto-migrate rule for adopters already with private names committed — the recovery flow is destructive and warrants a deliberate run.

Why "docs + question" is enough for now

The split-portfolio mode is fully functional today with the two manual steps the docs describe (ln -s ... + .gitignore). Every existing skill resolves through the symlinks transparently — no skill change is required for the pattern to work.

Reference implementation: atlas-apex/apexyard (public fork, slim) + atlas-apex/ops (private portfolio) — set up by the adopter who hit the trip-wire on 2026-05-02. Daily workflow has been working through symlinks for one full session without issue.

Testing

  1. Markdownlintmarkdownlint-cli2 docs/multi-project.md .claude/skills/setup/SKILL.md (CI runs it).
  2. Lychee link-check — internal anchor #split-portfolio-mode--public-framework--private-portfolio resolves; external links (github.com/me2resh/apexyard) are not new.
  3. Manual setup walkthrough — follow the new 7-step split-portfolio section from a fresh fork and verify /projects resolves through the symlink at the end. (Verified by the reference adopter; capture as a test in a follow-up if useful.)
  4. Backward compatibility — single-fork mode (the default) is unchanged. Existing adopters who don't touch /setup again or follow the new section continue working exactly as before.

Out of scope (tracked on #143)

  • portfolio: config block in onboarding.yaml schema with registry, projects_dir, ideas_backlog fields
  • Skill audit + refactor — every skill that reads the registry currently hardcodes the path. Migrating to honour the config block is mechanical (~10 skills) but warrants its own PR for clean review
  • /split-portfolio migration helper skill — automates the recovery flow for existing single-fork adopters who hit the trip-wire (force-push history rewrite + redact issue/PR bodies + create private repo + symlink)
  • /setup --reset or similar to opt-out of the privacy gate when re-running on a configured fork

Refs

Glossary

Term Definition
Single-fork mode Today's setup: registry + per-project docs live inside the fork itself. Works fine for all-public portfolios or paid GitHub plans (Pro / Team / Enterprise) that support private forks of public repos.
Split-portfolio mode New supported pattern documented in this PR: public fork holds framework files, separate private repo holds the portfolio (registry + per-project docs). Two repos, both in the adopter's account, side-by-side on disk.
Trip-wire The silent privacy bug GitHub Free adopters hit with single-fork mode + any private project: GitHub disallows git fetch-ing a public fork into a private one, and there's no way to make a fork private after the fact, so the registry's private project names end up published on a public GitHub repo.
Privacy gate (Step 2a) New /setup question that branches the configuration flow on whether any of the adopter's projects are private + which GitHub plan they're on. Single message, three answers, prevents the trip-wire by default.
Symlink-based portability The split-portfolio mode works with the current framework (no skill changes needed) because apexyard.projects.yaml and projects/ are symlinks pointing at the private portfolio repo. Skills resolve through the symlinks transparently. The portfolio: config block (#143 follow-up) replaces this with a first-class config option.
Recovery flow Documented manual steps for adopters who already hit the trip-wire — force-push history rewrite to remove the registry from public main, redact GitHub Issue / PR bodies, push a backup branch first, then migrate to split mode. The flow has one irreducible caveat: GitHub Issue / PR edit history survives force-pushes (timeline API), so redaction is partial.

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants