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:
Keysat
2026-06-14 12:19:48 -05:00
parent 36e1f78014
commit 828fc99dd4
5 changed files with 69 additions and 34 deletions
+19 -9
View File
@@ -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 - `/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 AGENTS.md/ROADMAP.md plus the inbox and groups all to-dos by priority — reads and reports
only; deciding focus stays with the user. only; deciding focus stays with the user.
- The inbox-check line and canonical `.gitignore` are now threaded into the retrofit flow - The cross-repo git-hygiene audit (ROADMAP item 6) is **DONE**: all 9 git repos under
(playbook + `/retrofit` guide), so new repos inherit them — but they're **not yet in other `~/Projects` audited (one read-only `portability-checker` each). No safety issues anywhere —
*existing* repos**; a shallow scan shows the `.claude`/git setup is inconsistent across zero tracked `.env`/`.DS_Store`/`*.local.json`, all in-repo symlinks relative. 6 repos
repos. remediated (inbox-check line + canonical `.gitignore`) and pushed; `recap-relay` is
- Specced in `ROADMAP.md`, not built: the cross-repo git-hygiene audit (item 6, HIGH), the committed locally only (no git remote).
`new-project` bootstrap, the cross-repo quality-gate standard, and the SessionStart hook. - The audit drove a **standards change**: `portability.md`'s canonical `.claude/` block is now
- Next session: (1) run the cross-repo git-hygiene audit (ROADMAP item 6, HIGH); (2) build **deny-by-default** (`.claude/*` + an allow-list of the shared wiring). The old
the `new-project` bootstrap (item 5); (3) add `/capture`, `/triage`, `/roundup` to README's allow-by-default block would have un-ignored `premier-gunner`'s password-bearing
"The rhythm" section. `.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
View File
@@ -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 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`. 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* Fanned out one read-only `portability-checker` per git repo under `~/Projects`. **No safety
consistent across repos. Git repos with the full AGENTS.md + `.claude` + `.gitignore` setup: issues anywhere:** zero tracked `.env` / `.DS_Store` / `*.local.json`, and every in-repo
`CRM`, `premier-gunner`, `recap-relay`, `recap`, `spark-control`, `standards`, `Workout-log`. symlink is relative. The gaps were consistency: the inbox-check line was missing in all 7
Outliers: `ten31-transcripts` has a `CLAUDE.md` but **no `.claude/` dir** (possible real file non-standards repos, and only `standards` had a complete canonical `.gitignore`.
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.
**Do:** fan out one read-only `portability-checker` (or `Explore`) per git repo under **Fixed — 6 repos, one commit each, pushed** (`CRM`, `premier-gunner`, `recap`,
`~/Projects`, each reporting: is `CLAUDE.md` a relative symlink to `AGENTS.md` or a real `spark-control`, `Workout-log`; `recap-relay` committed locally — see residuals): added the
file; what's in `.claude/` and which of it is tracked vs gitignored (esp. `settings.local.json` repo-tagged inbox-check line and normalized `.gitignore`.
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).
**Open questions:** treat non-git folders (flag for retrofit) vs. external upstreams **Standard improved by the audit:** the documented canonical `.claude/` block was
(`start-os`?) differently; report-only first vs. auto-fix. 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
View File
@@ -23,8 +23,8 @@ guess on anything that changes what lands on disk.
## Phase 1 — Git audit (playbook Step 0) ## Phase 1 — Git audit (playbook Step 0)
- If this is not a git repo: propose `git init`, a `.gitignore` (the canonical block from - 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 `portability.md`'s "What git tracks" — `.env`/`.env.*`, a deny-by-default `.claude/*` with
`*.local.*`, OS cruft), and an initial commit. Get approval before running. 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, - 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 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). being saved — uncommitted changes are as unprotected as no repo at all).
+20 -5
View File
@@ -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`, deterministic behavior is part of the repo); `.claude/agents/*.md`, `.claude/commands/*.md`,
`.claude/skills/` (project-scoped wrappers). `.claude/skills/` (project-scoped wrappers).
Gitignored (per-user, per-machine, or secret): `.claude/settings.local.json` and any Gitignored (per-user, per-machine, secret, or session scratch): `.claude/settings.local.json`
`*.local.*` (personal permissions/overrides); `.env` and secrets (corollary 5); OS cruft. 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 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: 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.*
!.env.example !.env.example
# Claude Code — commit shared config, ignore personal/local # Claude Code — deny by default, allow-list shared wiring.
.claude/settings.local.json # .claude/ also accumulates worktrees, editor configs, and OS cruft; commit
.claude/*.local.json # 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 # OS cruft
.DS_Store .DS_Store
+1 -1
View File
@@ -62,7 +62,7 @@ claude
Paste: 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.) 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.)