feat(skills): project-bootstrap@1.11.0 — .gitignore meta-isolation block

Step 1 now ships agent meta-paths inversions (`!.claude/`, `!.tasks/`,
`!.wiki/`, `!.brainstorm/`, `!.archive/`, `!.mcp/`, `!.mcp.json`,
`!MEMORY.md`) so own greenfield/upgrade projects re-enable visibility
against the global `core.excludesFile` cutter (`~/.config/git/ignore`)
that hides obvyaska from forks of upstream open-source. Without it any
fresh bootstrap landed an empty first commit on machines with the global
configured: setup-wiki/setup-tasks/Step 5 created .wiki/.tasks/CLAUDE.md
but git ignored them.

Two cases handled in Step 1:
- no .gitignore → write template (block included unconditionally)
- existing .gitignore → marker-based (`# AI обвеска — слой 2:`)
  append-if-missing; idempotent on re-run

Smoke-tested in %TEMP%\test-bootstrap-meta-iso: all 3 acceptance
criteria pass + negative control (strip block → global hides) +
idempotency (re-run with marker present skips). Source concept:
workshop wiki concepts/meta-out-of-repo.md. Closes board task
[meta-isolation-bootstrap-skill-update].

MINOR bump (1.10.1 → 1.11.0) — new feature, backward-compat.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-10 14:27:59 +03:00
parent c65fd26489
commit 6d503b16dc
6 changed files with 88 additions and 8 deletions

View File

@@ -724,7 +724,7 @@ Pattern для починки уже отработан в `setup-projects-meta`
---
## [meta-isolation-bootstrap-skill-update] — Обновить `project-bootstrap` skill чтобы для своих новых проектов он создавал локальный `.gitignore` с `!`-инверсиями мета-путей. Без обновления любой новый bootstrap'нутый проект ломается сразу: `.tasks/`, `.wiki/`, `.claude/` создаются, но git их не видит из-за глобального `core.excludesFile`, и в первый коммит они не попадают.
## 🟢 [meta-isolation-bootstrap-skill-update] — Обновить `project-bootstrap` skill чтобы для своих новых проектов он создавал локальный `.gitignore` с `!`-инверсиями мета-путей. Без обновления любой новый bootstrap'нутый проект ломается сразу: `.tasks/`, `.wiki/`, `.claude/` создаются, но git их не видит из-за глобального `core.excludesFile`, и в первый коммит они не попадают.
**Источник:** `.workshop/.wiki/concepts/meta-out-of-repo.md` — секции «Слой 2» и «Новые проекты».
@@ -761,10 +761,11 @@ Pattern для починки уже отработан в `setup-projects-meta`
**Не делать:** не клади инверсии безусловно, без проверки что цель — свой репо. В чужих форках это потенциально создаст расхождение с upstream'ом (новый файл в `.gitignore`). Если bootstrap отрабатывает только для своих новых проектов — этот edge-case не релевантен; уточнить в коде скила.
**Status:** ready
**Where I stopped:** (not started)
**Next action:** Прочитать текущий `project-bootstrap` SKILL.md (`~/projects/claude-skills/skills/project-bootstrap/SKILL.md`) чтобы понять структуру шагов и где встроить запись `.gitignore`. Добавить шаг после `git init`. MINOR-bump в frontmatter version. Тестовый run на greenfield: `mkdir /tmp/test-bootstrap && cd /tmp/test-bootstrap && /project-bootstrap` (или эквивалент через агента) → проверить acceptance. Коммит: `feat(skills): project-bootstrap adds local meta-paths inversions for own projects`.
**Branch:** n/a
**Status:** done
**Where I stopped:** v1.11.0 shipped + installed. Template carries meta-isolation block; SKILL.md Step 1 documents greenfield (template) + upgrade-case marker-append. Smoke test on `%TEMP%\test-bootstrap-meta-iso` passed all 3 acceptance + negative control + idempotency. Wiki: `concepts/project-bootstrap-meta-isolation.md` + index + log entries.
**Next action:** (closed)
**Branch:** master
<!-- created-by: OpeItcLoc03@DESKTOP-NSEF0UK / from: OpeItcLoc03/workshop / 2026-05-10T11:04:56.068Z -->
<!-- closed-by: OpeItcLoc03@DESKTOP-NSEF0UK / 2026-05-10 / note: project-bootstrap v1.11.0 — .gitignore meta-isolation block (template + upgrade-case marker append); 3/3 acceptance proven via greenfield smoke + negative control + idempotency check -->
---

View File

@@ -0,0 +1,36 @@
---
title: project-bootstrap meta-isolation block
type: concept
updated: 2026-05-10
---
# project-bootstrap meta-isolation block
`project-bootstrap` v1.11.0 ships a meta-isolation block in the local `.gitignore` it creates / appends. Block contains `!`-inversions for `.claude/`, `.tasks/`, `.wiki/`, `.brainstorm/`, `.archive/`, `.mcp/`, `.mcp.json`, `MEMORY.md`.
## Why
The global `core.excludesFile` (`~/.config/git/ignore`) hides agent meta-paths from forks of upstream open-source — see workshop wiki `concepts/meta-out-of-repo.md` (sections "Слой 2", "Новые проекты"). Without slой 2 in own repos, `setup-wiki` / `setup-tasks` / Step 5 produce `.wiki/`, `.tasks/`, `CLAUDE.md`, but git ignores them and the bootstrap commit lands empty of obvyaska. Empirically reproduced before the fix; smoke test in `assets/.gitignore.template` greenfield confirms.
## In-skill design choices
- **Marker comment** — `# AI обвеска — слой 2:` (case-sensitive substring) used to detect the block on upgrade-case append. Comment text matches workshop wiki concept; chosen over checking for `!.tasks/` line because users may add their own ad-hoc `!`-rules unrelated to this block.
- **Append-only on upgrade** — never rewrite or reorder existing `.gitignore`. Same discipline as Step 5's CLAUDE.md merge (idempotent, append missing).
- **Block applied unconditionally in current modes.** Bootstrap's three modes (greenfield-full, add-remote, upgrade) all assume the user owns the repo. Greenfield-full creates a fresh Gitea repo; add-remote and upgrade operate on user repos. There is no fork-of-upstream mode today — if added, the block must be omitted there (putting `!.claude/` into a fork's `.gitignore` would diverge from upstream's ignore semantics).
- **Template change is the load-bearing edit** — greenfield projects pick up the block by template copy. Upgrade-case append handles existing repos that bootstrapped before v1.11.0 (or were created without bootstrap).
## Acceptance proven
Smoke test on greenfield (`%TEMP%\test-bootstrap-meta-iso`):
1. `.gitignore` from template contains the block — ✓.
2. `.tasks/_smoke.md` shows as untracked in `git status` — ✓.
3. First-commit candidate set includes `.tasks/`, `.wiki/`, `.claude/`, `.brainstorm/`, `MEMORY.md` — ✓.
4. Negative control — strip block, status hides all meta-paths (only `.gitignore` itself remains visible). Confirms global excludesFile is the cutter and slой 2 is what restores visibility — ✓.
5. Upgrade-case append idempotent — second run with marker present skips — ✓.
## Pointers
- Source concept: `~/projects/.workshop/.wiki/concepts/meta-out-of-repo.md`
- Sister action-item: `[meta-isolation-existing-repos-migration]` in `OpeItcLoc03/workshop` — one-off migration of existing own repos.
- Long-term: `[meta-isolation-mcp-sync-extension]` in `OpeItcLoc03/common` — extend `projects-meta-mcp` to sync `.wiki/` + `.claude/skills/` so meta-paths can leave repo entirely.

View File

@@ -36,6 +36,7 @@ Catalog of all wiki pages. One line per page, organized by type. Updated on ever
- [interns-repo-read-design](concepts/interns-repo-read-design.md) — interns-repo-read-design
- [hermes-skills-rollout-design](concepts/hermes-skills-rollout-design.md) — hermes-skills-rollout-design
- [tdd-criteria-design](concepts/tdd-criteria-design.md) — tdd-criteria-design
- [project-bootstrap-meta-isolation.md](concepts/project-bootstrap-meta-isolation.md) — project-bootstrap@1.11.0 — Step 1 ships meta-isolation block in `.gitignore` (`!.claude/`, `!.tasks/`, `!.wiki/`, ...) so own greenfield/upgrade projects re-enable agent meta-paths against global `core.excludesFile` cutter. Marker-based append-only on existing files; smoke-tested with negative control
## Packages

View File

@@ -55,3 +55,5 @@ Parseable: `grep "^## \[" .wiki/log.md | tail -20`.
## [2026-05-07] ingest | concepts/tdd-criteria-design
## [2026-05-07] review | tdd-criteria v0.2.0 — 4 findings applied: trigger-loophole fix (removed session-authorship clause), composite-tasks + refactoring sections, expanded file-extension list, clarified wrapper line-count + spike-survivor fallback + foreign-schema fix; design doc synced
## [2026-05-10] decision | project-bootstrap-meta-isolation — v1.11.0 ships meta-isolation block in `.gitignore` template + Step 1 upgrade-case append; restores agent meta-paths visibility against global `core.excludesFile`; smoke-tested greenfield + negative control + idempotency

View File

@@ -1,6 +1,6 @@
---
name: project-bootstrap
version: 1.10.1
version: 1.11.0
description: >
Initializes or upgrades a project in the current folder: git, .gitignore, README.md,
.wiki/ using Karpathy's method, .tasks/ for task tracking, CLAUDE.md with skill triggers.
@@ -61,8 +61,37 @@ If git is not initialized:
git init
```
If `.gitignore` does not exist — create from template `assets/.gitignore.template`.
If it exists — leave it untouched.
### `.gitignore`
The template `assets/.gitignore.template` contains two parts:
1. Standard ignore rules (deps, build, env, IDE, OS, logs).
2. **Meta-isolation block**`!`-inversions for `.claude/`, `.tasks/`, `.wiki/`,
`.brainstorm/`, `.archive/`, `.mcp/`, `.mcp.json`, `MEMORY.md`. This block
re-enables tracking of agent meta-paths in **own** repos against the
global `core.excludesFile` rule (`~/.config/git/ignore`) that hides them
from forks of upstream open-source. Without it, the `.tasks/`, `.wiki/`,
and `.claude/` directories created by Steps 3-5 would be invisible to git
on machines where the global excludesFile is configured, and the first
commit would be empty of agent obvyaska. Full design: workshop wiki
`concepts/meta-out-of-repo.md` (sections "Слой 2" and "Новые проекты").
Two cases:
- **`.gitignore` does not exist** — create from `assets/.gitignore.template`
(block included unconditionally).
- **`.gitignore` exists** — check for the marker line
`# AI обвеска — слой 2:` (substring match, case-sensitive). If absent →
append the meta-isolation block (with the marker comment) to the end of
the file, prefixed by a blank line if the file does not already end with
one. If present → leave the file untouched.
The block is **scoped to own projects**. The bootstrap skill currently has no
fork-of-upstream mode (greenfield-full creates a brand-new Gitea repo;
add-remote and upgrade operate on the user's own repos), so the block is
applied unconditionally in all current modes. If a fork-bootstrap mode is
ever added, the block must be **omitted** there — putting `!.claude/` etc.
into a fork's `.gitignore` would diverge from upstream's ignore rules.
---

View File

@@ -27,3 +27,14 @@ Thumbs.db
# Logs
*.log
logs/
# AI обвеска — слой 2: переопределяем глобальный ~/.config/git/ignore
# для своих репо (см. global wiki concept meta-out-of-repo)
!.claude/
!.tasks/
!.wiki/
!.brainstorm/
!.archive/
!.mcp/
!.mcp.json
!MEMORY.md