feat(#517): keep onboarding config out of git (example-file + gitignore + guard)#522
Conversation
…re + guard) Layer 1 — structure: - Add tracked onboarding.example.yaml (placeholders only) as the template - Gitignore onboarding.yaml; untrack it (git rm --cached, local copy preserved) - /setup copies example -> onboarding.yaml (gitignored) and never stages the real file - onboarding-check.sh detects configured state from the local real file (or the v2 private committed copy), not a committed public file; prompts /setup on a fresh fork that has only the example Layer 2 — commit-time guard: - New block-onboarding-in-git.sh: blocks committing a filled-in onboarding.yaml via placeholder-diff vs onboarding.example.yaml; env-var + in-message escape hatches; wired into settings.json after check-secrets.sh - Tests: test_block_onboarding_in_git.sh (6 cases) — all green Docs: - Migration note (git rm --cached) in docs/multi-project.md + /setup SKILL - Hook listed in .claude/hooks/README.md - Decision recorded in AgDR-0064 Note: already-committed history still holds prior real values until the full-history scrub tracked in #518. This change untracks going forward. Closes #517 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ion drift - Bump hook count 39→40 across site/ marketing copy (the new block-onboarding-in-git.sh hook from this PR) — satisfies the site-counts drift gate - Incidental: bump site/index.html advertised version 2.2.0→2.3.0 to match CHANGELOG (pre-existing drift on dev from the 2.3.0 release; the version-drift guard only fires here because this PR touches site/) Refs #517 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
atlas-apex
left a comment
There was a problem hiding this comment.
Code Review (re-review): PR #522
Commit: e32983461407e1259395acd16d4e6ef6a279b0ca
Scope of this re-review
Prior APPROVAL stands at f5a9c6f. This re-review covers the single new commit e329834 — a site/ marketing-copy drift refresh triggered because this PR now touches site/.
Verification of the new commit
-
Scope — clean, no creep ✅
Commite329834touches exactly the 7site/files described and nothing else:site/architecture.html,site/architecture.md.gen,site/index.html,site/index.md.gen,site/llms-full.txt,site/llms.txt,site/skill.md. No code, hook, test, or feature file is touched by this commit. -
Hook count bump 39 → 40 — correct ✅
The canonical count (find .claude/hooks -maxdepth 1 -name '*.sh' ! -name '_lib*', pertest_site_counts.sh) returns 40 at HEADe329834. The newblock-onboarding-in-git.shthis PR adds is included in that set. Every39→40edit across the 7 files is a 1:1 refresh of the same claim — no over- or under-count. -
Version bump 2.2.0 → 2.3.0 — matches CHANGELOG ✅
CHANGELOG.mdtop release entry at HEAD is## [2.3.0] — 2026-06-04.site/index.htmlsoftwareVersionand thev2.3.0release-tag link are both bumped to2.3.0, satisfying the version-drift guard (#493). This was pre-existing drift ondevthat surfaced only because the PR now touchessite/— correctly resolved in-band rather than left for a later cut. -
Prior approval rationale holds ✅
The new commit carries zero functional or behavioural change to the onboarding feature (block-onboarding-in-git.sh,onboarding-check.sh,/setup,.gitignore, AgDR-0064). The feature code reviewed atf5a9c6fis byte-identical ate329834. Nothing in a marketing-copy refresh can invalidate the original verdict.
Checklist Results
- ✅ Architecture & Design: Pass (unchanged from f5a9c6f)
- ✅ Code Quality: Pass (no code change in new commit)
- ✅ Testing: Pass (6-case hook suite green; drift gate satisfied by the count + version refresh)
- ✅ Security: Pass (this is the leak-prevention feature itself)
- ✅ Performance: Pass (N/A — docs only)
- ✅ PR Description & Glossary: Pass (narrative summary + glossary present)
- ✅ Summary Bullet Narrative: Pass
- ✅ Technical Decisions (AgDR): Pass — AgDR-0064 linked
- ✅ Adopter Handbooks: N/A (no handbooks loaded)
Issues Found
None.
Verdict
APPROVED (recorded via comment — Rex cannot self-approve on GitHub; approval marker written for the merge gate.)
🤖 Reviewed by Rex (Code Reviewer Agent)
📌 Reviewed commit: e32983461407e1259395acd16d4e6ef6a279b0ca
) Follow-up to the #517 review (PR #522): the staged-path check used `grep -qx`, so the '.' in 'onboarding.yaml' was a regex wildcard. Switch to `grep -Fxq` (fixed string, still whole-line anchored) so it matches the literal filename only. No behaviour change in practice; removes a latent over-match. Refs #517 Co-authored-by: me2resh <ahmed.abdelaliem@gmail.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Summary
.env.example/.envconvention: a trackedonboarding.example.yaml(placeholders) plus a gitignoredonboarding.yaml(real values). Previously the real config was tracked and committed, so on a publicly-forked framework a CTO's company name, internal URLs, tracker instance, and team roster leaked into public history / upstream PR refs by default. Single-fork mode now matches what split-portfolio v2 already does.block-onboarding-in-git.sh(PreToolUse ongit commit) blocks a stagedonboarding.yamlwhose content differs from the example placeholders (a placeholder-diff signal), so agit add -for a pre-[Feature] Keep onboarding config out of git: example-file + gitignore + commit-time guard #517 tracked copy can't silently re-leak. Sibling tocheck-secrets.sh; env-var (APEXYARD_ALLOW_ONBOARDING_COMMIT=1) and in-message (<!-- onboarding: allow -->) escape hatches. 6-case test suite, all green.onboarding-check.shnow reports "configured" from the local real file (or the v2 private committed copy) and prompts/setupon a fresh fork that has only the example;/setupcopies the example → real and never stages the real file. Split-portfolio v2 is unaffected (private committed config still carries across clones); the only single-fork change is that each fresh clone runs/setuponce.docs/multi-project.md+ the/setupskill carry the one-timegit rm --cached onboarding.yamlstep for existing adopters. Decision recorded inAgDR-0064.Known follow-up (called out, not hidden)
The already-committed history of
onboarding.yamlstill contains prior real values — this PR untracks going forward but does not rewrite history. The full-history secret/config sweep is tracked in #518 (security hardening), which also reuses this PR's placeholder-diff signal for its release-artifact guard.Testing
.claude/hooks/tests/test_block_onboarding_in_git.sh→ 6 passed, 0 failed (filled-in blocked · placeholder-equals-example allowed · env-var escape · marker escape · non-onboarding file unaffected · non-commit ignored).shellcheck -S errorclean on the new + modified hooks.python3 yaml.safe_loadononboarding.example.yaml;json.loadon.claude/settings.json→ valid.git rm --cached onboarding.yamlverified: file untracked,git check-ignoreconfirms ignored, local copy preserved on disk.markdownlintclean on the new AgDR.Closes #517
Glossary
*.exampletemplate + gitignored real file (like.env.example/.env).*.exampleplaceholders.git commithook that blocks staged content which must never be published.