Adopt deny-by-default .claude gitignore; record git-hygiene audit
The cross-repo git-hygiene audit (ROADMAP item 6) found the documented canonical .claude/ block was allow-by-default and would have un-ignored a password-bearing .claude/launch.json. Switch portability.md to a deny-by-default .claude/* + allow-list block and align the two retrofit summaries. Mark item 6 done with residuals; refresh Current state.
This commit is contained in:
@@ -93,12 +93,22 @@ should carry this so any vendor's agent surfaces pending items at session start:
|
||||
- `/roundup` is built: a cross-project status report that reads every repo's
|
||||
AGENTS.md/ROADMAP.md plus the inbox and groups all to-dos by priority — reads and reports
|
||||
only; deciding focus stays with the user.
|
||||
- The inbox-check line and canonical `.gitignore` are now threaded into the retrofit flow
|
||||
(playbook + `/retrofit` guide), so new repos inherit them — but they're **not yet in other
|
||||
*existing* repos**; a shallow scan shows the `.claude`/git setup is inconsistent across
|
||||
repos.
|
||||
- Specced in `ROADMAP.md`, not built: the cross-repo git-hygiene audit (item 6, HIGH), the
|
||||
`new-project` bootstrap, the cross-repo quality-gate standard, and the SessionStart hook.
|
||||
- Next session: (1) run the cross-repo git-hygiene audit (ROADMAP item 6, HIGH); (2) build
|
||||
the `new-project` bootstrap (item 5); (3) add `/capture`, `/triage`, `/roundup` to README's
|
||||
"The rhythm" section.
|
||||
- The cross-repo git-hygiene audit (ROADMAP item 6) is **DONE**: all 9 git repos under
|
||||
`~/Projects` audited (one read-only `portability-checker` each). No safety issues anywhere —
|
||||
zero tracked `.env`/`.DS_Store`/`*.local.json`, all in-repo symlinks relative. 6 repos
|
||||
remediated (inbox-check line + canonical `.gitignore`) and pushed; `recap-relay` is
|
||||
committed locally only (no git remote).
|
||||
- The audit drove a **standards change**: `portability.md`'s canonical `.claude/` block is now
|
||||
**deny-by-default** (`.claude/*` + an allow-list of the shared wiring). The old
|
||||
allow-by-default block would have un-ignored `premier-gunner`'s password-bearing
|
||||
`.claude/launch.json` — deny-by-default keeps stray scratch/secrets out by default. The two
|
||||
retrofit summaries were updated to match.
|
||||
- The inbox-check line + canonical `.gitignore` are threaded into the retrofit flow *and* now
|
||||
live in the 6 remediated repos. Still missing from `ten31-transcripts` (needs a mini-retrofit)
|
||||
and from the many **non-git folders** under `~/Projects` (unprotected work).
|
||||
- Specced in `ROADMAP.md`, not built: the `new-project` bootstrap (item 5), the cross-repo
|
||||
quality-gate standard (item 1), and the SessionStart hook (item 3). Item 6 residuals:
|
||||
`ten31-transcripts` mini-retrofit, a Gitea remote for `recap-relay`, the non-git-folder sweep.
|
||||
- Next session: (1) work the item-6 residuals — `ten31-transcripts` mini-retrofit and a remote
|
||||
for `recap-relay`; (2) build the `new-project` bootstrap (item 5); (3) add `/capture`,
|
||||
`/triage`, `/roundup` to README's "The rhythm" section.
|
||||
|
||||
+27
-17
@@ -104,23 +104,33 @@ the CLAUDE.md symlink, ROADMAP.md, the canonical `.gitignore`, and the inbox-che
|
||||
is generic vs. stack-specific (does it call a `/harden` step from item 1 to install the
|
||||
stack's linter+hook?); whether the workshop output also seeds the first `## Current state`.
|
||||
|
||||
## 6. Cross-repo git-hygiene audit + remediation — HIGH PRIORITY
|
||||
## 6. Cross-repo git-hygiene audit + remediation ✅ DONE (2026-06-14)
|
||||
|
||||
**Why:** a shallow scan of `~/Projects` (2026-06-14) shows the `.claude`/git setup is *not*
|
||||
consistent across repos. Git repos with the full AGENTS.md + `.claude` + `.gitignore` setup:
|
||||
`CRM`, `premier-gunner`, `recap-relay`, `recap`, `spark-control`, `standards`, `Workout-log`.
|
||||
Outliers: `ten31-transcripts` has a `CLAUDE.md` but **no `.claude/` dir** (possible real file
|
||||
instead of an AGENTS.md symlink — the stale-retrofit failure); `start-os` has neither (likely
|
||||
an external/upstream repo). Plus many non-git folders (unprotected work). We don't yet know,
|
||||
per repo, what inside `.claude/` is committed vs gitignored, or whether in-repo symlinks are
|
||||
relative.
|
||||
Fanned out one read-only `portability-checker` per git repo under `~/Projects`. **No safety
|
||||
issues anywhere:** zero tracked `.env` / `.DS_Store` / `*.local.json`, and every in-repo
|
||||
symlink is relative. The gaps were consistency: the inbox-check line was missing in all 7
|
||||
non-standards repos, and only `standards` had a complete canonical `.gitignore`.
|
||||
|
||||
**Do:** fan out one read-only `portability-checker` (or `Explore`) per git repo under
|
||||
`~/Projects`, each reporting: is `CLAUDE.md` a relative symlink to `AGENTS.md` or a real
|
||||
file; what's in `.claude/` and which of it is tracked vs gitignored (esp. `settings.local.json`
|
||||
committed by mistake, or shared `settings.json`/rules symlinks missing); whether `.gitignore`
|
||||
carries the canonical block; any absolute in-repo symlinks. Synthesize one compliance matrix +
|
||||
a prioritized remediation list, then a follow-up pass fixes each repo (its own commit).
|
||||
**Fixed — 6 repos, one commit each, pushed** (`CRM`, `premier-gunner`, `recap`,
|
||||
`spark-control`, `Workout-log`; `recap-relay` committed locally — see residuals): added the
|
||||
repo-tagged inbox-check line and normalized `.gitignore`.
|
||||
|
||||
**Open questions:** treat non-git folders (flag for retrofit) vs. external upstreams
|
||||
(`start-os`?) differently; report-only first vs. auto-fix.
|
||||
**Standard improved by the audit:** the documented canonical `.claude/` block was
|
||||
allow-by-default and would have *un-ignored* `premier-gunner`'s password-bearing
|
||||
`.claude/launch.json`. Switched `portability.md` (and the two retrofit summaries) to a
|
||||
**deny-by-default `.claude/*` + allow-list** of the shared wiring.
|
||||
|
||||
**Residual follow-ups:**
|
||||
- **`ten31-transcripts` (MAJOR) — needs its own mini-retrofit.** Despite the name it's an
|
||||
active Xcode/Swift app with no `.claude/` at all. Scaffold `.claude/settings.json`; decide
|
||||
whether to reorganize its flat `docs/NN_*.md` into `docs/guides/` + `.claude/rules/` symlinks.
|
||||
Too big for the mechanical pass.
|
||||
- **`recap-relay` has no git remote** — committed locally only; create a Gitea repo + push.
|
||||
- **`premier-gunner/s9pk/.gitignore`** lacks the secrets/Claude lines (low priority; the root
|
||||
`.gitignore` covers `.env` tree-wide already).
|
||||
- **Many non-git folders under `~/Projects` are unprotected work** (discount-watcher,
|
||||
expense-organizer, giga, heart-rate, licensing, one-river, satoshi-sleep, START9 PACKAGING,
|
||||
ten31-agents/-command-center/-signal-engine, timestamp-converter, timestamp-newspaper,
|
||||
website-landing, Grand-Cayman-paddleboard). Each needs `git init` + retrofit, or an explicit
|
||||
"scratch, don't track" decision.
|
||||
- **`start-os`** is an external upstream (Start9Labs/start-os) — out of scope, no action.
|
||||
|
||||
+2
-2
@@ -23,8 +23,8 @@ guess on anything that changes what lands on disk.
|
||||
## Phase 1 — Git audit (playbook Step 0)
|
||||
|
||||
- If this is not a git repo: propose `git init`, a `.gitignore` (the canonical block from
|
||||
`portability.md`'s "What git tracks" — `.env`, `.claude/settings.local.json` and
|
||||
`*.local.*`, OS cruft), and an initial commit. Get approval before running.
|
||||
`portability.md`'s "What git tracks" — `.env`/`.env.*`, a deny-by-default `.claude/*` with
|
||||
the shared wiring allow-listed, OS cruft), and an initial commit. Get approval before running.
|
||||
- If it is: report whether there are uncommitted changes and when the last commit was,
|
||||
then propose committing anything outstanding (a repo existing isn't the same as work
|
||||
being saved — uncommitted changes are as unprotected as no repo at all).
|
||||
|
||||
+20
-5
@@ -72,8 +72,17 @@ symlinks; `ROADMAP.md`; `.claude/settings.json` (shared project settings and hoo
|
||||
deterministic behavior is part of the repo); `.claude/agents/*.md`, `.claude/commands/*.md`,
|
||||
`.claude/skills/` (project-scoped wrappers).
|
||||
|
||||
Gitignored (per-user, per-machine, or secret): `.claude/settings.local.json` and any
|
||||
`*.local.*` (personal permissions/overrides); `.env` and secrets (corollary 5); OS cruft.
|
||||
Gitignored (per-user, per-machine, secret, or session scratch): `.claude/settings.local.json`
|
||||
and any `*.local.*` (personal permissions/overrides); `.claude/worktrees/` and other Claude
|
||||
session/editor scratch that lands in `.claude/`; `.env` and secrets (corollary 5); OS cruft.
|
||||
|
||||
Because `.claude/` accumulates unpredictable scratch — worktrees, editor debug configs
|
||||
(sometimes carrying credentials), `.DS_Store` — **ignore it deny-by-default and allow-list
|
||||
only the shared wiring.** A blanket `.claude/*` plus `!` exceptions is safer than naming
|
||||
individual local files: a new kind of local scratch is ignored automatically, and a stray
|
||||
secret never slips in by default. (Already-tracked files stay tracked even under `.claude/*`,
|
||||
so a deliberate, secret-free editor config a repo wants to commit can simply be allow-listed
|
||||
with its own `!` line.)
|
||||
|
||||
Put these in the repo's **own committed `.gitignore`** — don't rely on a global
|
||||
excludesfile, which a fresh clone or another machine won't have. Canonical block:
|
||||
@@ -84,9 +93,15 @@ excludesfile, which a fresh clone or another machine won't have. Canonical block
|
||||
.env.*
|
||||
!.env.example
|
||||
|
||||
# Claude Code — commit shared config, ignore personal/local
|
||||
.claude/settings.local.json
|
||||
.claude/*.local.json
|
||||
# Claude Code — deny by default, allow-list shared wiring.
|
||||
# .claude/ also accumulates worktrees, editor configs, and OS cruft; commit
|
||||
# only the shared parts so new local scratch (or a stray secret) stays out.
|
||||
.claude/*
|
||||
!.claude/rules/
|
||||
!.claude/agents/
|
||||
!.claude/commands/
|
||||
!.claude/skills/
|
||||
!.claude/settings.json
|
||||
|
||||
# OS cruft
|
||||
.DS_Store
|
||||
|
||||
@@ -62,7 +62,7 @@ claude
|
||||
|
||||
Paste:
|
||||
|
||||
> Is this a git repo? If not: git init, write a .gitignore covering .env, .claude/settings.local.json (and any *.local.*), and OS cruft — the canonical block in portability.md's "What git tracks" — and make an initial commit. If it is: tell me whether there are uncommitted changes and when the last commit was, then commit anything outstanding.
|
||||
> Is this a git repo? If not: git init, write a .gitignore covering .env/.env.*, a deny-by-default .claude/* with the shared wiring allow-listed (rules/agents/commands/skills/settings.json), and OS cruft — the canonical block in portability.md's "What git tracks" — and make an initial commit. If it is: tell me whether there are uncommitted changes and when the last commit was, then commit anything outstanding.
|
||||
|
||||
Approve the git commands it proposes. Then `/exit`. (A repo existing isn't the same as work being saved in it — uncommitted changes are exactly as unprotected as no repo at all.)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user