@theglitchking/babel-fish 2.4.3 → 2.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,209 @@
1
+ ---
2
+ name: structure-bootstrap
3
+ description: |
4
+ Set up, adopt or change a repo's structure manifest (.claude/structure.toml) — the
5
+ approved folders, what each may hold, their lifecycle (planned / active / deprecated),
6
+ the dev → stg → prod environments and pointers to related repos — enforced by
7
+ babel-fish's structure-check.py at commit time and in CI.
8
+ Use when the user asks to set up / plan / detect / adopt the repo structure or folder
9
+ layout, asks where a new file, app, service or environment should go, wants to add,
10
+ move or retire a folder, starts a brand-new repo or project, or hits a
11
+ "[structure-check] Commit blocked" failure.
12
+ ---
13
+
14
+ # Repo structure: set up, adopt, change
15
+
16
+ `.claude/structure.toml` says where files go. `.claude/project-map/structure-check.py`
17
+ enforces it: pre-commit (only when the manifest exists) and CI. The script gathers
18
+ **facts** and checks **placement**. You make the **judgment calls**: what a folder is
19
+ for, which layout fits, what to ask.
20
+
21
+ ## Ground rules
22
+
23
+ - **The manifest is the repo's data.** Never overwrite one. Change an existing manifest
24
+ only by editing it, and only after the user agrees to the change.
25
+ - **Existing structure wins.** On an existing repo a layout template is a reference.
26
+ Its differences become questions for the user, or `exceptions`, never a block.
27
+ - **Ask only what you can't infer.** Read the tree first. Ask about purpose only when
28
+ the contents don't answer it.
29
+ - **One repo at a time.** For multi-repo, record `[[repo]]` pointers. Never write into
30
+ another repo. Each one runs its own babel-fish (map, drift, structure check).
31
+ - **Placement, not contents.** The check can say a Compose file is in the wrong
32
+ folder. It can't say a function is in the wrong file.
33
+
34
+ If `.claude/project-map/structure-check.py` is missing, the repo hasn't run the full
35
+ installer: `npx @theglitchking/babel-fish init`.
36
+
37
+ Commands below use `python3`. Many machines have no `python`. Reading a manifest
38
+ needs 3.11+; on older versions the check warns and passes, which proves nothing.
39
+
40
+ **`holds` globs** are relative to the folder's `path`. `*` and `?` stop at `/`; `**`
41
+ crosses it; `**/` may match zero directories, so `**/*.py` also matches direct
42
+ children. Name extensionless files literally (`"pre-commit"`, `"Makefile"`).
43
+
44
+ ## Step 0: facts
45
+
46
+ ```bash
47
+ python3 .claude/project-map/structure-check.py --detect --json
48
+ ```
49
+
50
+ Returns `mode` + `reasons`, `environments` (name → evidence paths), `top_level`
51
+ (folders, file counts, main extensions), `root_files`, `sibling_repos`, `packages`,
52
+ `near_empty`, `manifest` (exists?) and `layouts` (available templates in
53
+ `.claude/templates/structure/`). Needs Python 3.11+ only to *read* a manifest;
54
+ `--detect` works on any version.
55
+
56
+ Then pick the flow:
57
+
58
+ | Situation | Flow |
59
+ |---|---|
60
+ | `manifest` is true | **D: change the structure** |
61
+ | `near_empty` is true | **B: new repo** |
62
+ | The user doesn't know what their options are | **C: options** |
63
+ | Otherwise | **A: adopt an existing repo** |
64
+
65
+ ## Flow A: adopt an existing repo
66
+
67
+ 1. Confirm the mode with the user in one line, using the reasons ("Looks like a
68
+ monorepo: pnpm-workspace.yaml, apps/api + apps/web. Right?"). Siblings or
69
+ `.gitmodules` in a monorepo still means `[[repo]]` pointers.
70
+ 2. Get a baseline that blocks nothing:
71
+ ```bash
72
+ python3 .claude/project-map/structure-check.py --bootstrap --layout <mode>
73
+ ```
74
+ Top-level folders the layout doesn't cover become their own `[[folder]]` entries
75
+ ("TODO … (not in the <mode> layout)"). Leftover violations seed `exceptions` as
76
+ exact paths. If most of the `top_level` folders from Step 0 aren't in the layout,
77
+ use plain `--bootstrap` instead. It declares exactly what exists, with nothing to
78
+ prune.
79
+ 3. Refine `.claude/structure.toml` from what is actually there:
80
+ - **Prune what the layout brought:**
81
+ - `planned` folders this repo won't have, e.g. a top-level `migrations` when
82
+ migrations already live in `db/`
83
+ - the layout's dev/stg/prod `[[environment]]` blocks if Step 0 found no
84
+ environments. Ask first if the user may be planning them.
85
+ - **purpose:** one line per folder, from its README or a few of its files. Check
86
+ the purposes the layout supplied too, not just the `TODO`s; they're generic
87
+ and can be wrong for this repo.
88
+ - **holds:** tight enough to catch drift, loose enough not to nag. Survey the
89
+ real contents (`git ls-files <folder> | sed 's/.*\.//' | sort | uniq -c`).
90
+ `--detect` lists only the top few extensions per folder, and holds built from
91
+ that alone will FAIL on the rest. E.g. `["**/*.py"]` for a Python package,
92
+ `[".env.example", "README.md", "*/**"]` for `infra/env`. Leave `holds` out for folders that
93
+ legitimately hold anything.
94
+ - **environments:** from `environments` in the facts. Targets: `dev` / `local` →
95
+ `local`, everything else → `cloud`. Ask if a name is ambiguous (`test`, `qa`).
96
+ Order: `promotes_to` dev → stg → prod. `mirrors = "prod"` on stg when both exist.
97
+ `env_roots` if env folders live somewhere other than `infra/env` and `infra/deploy`
98
+ (e.g. `k8s/overlays`).
99
+ - **root_files:** keep what's there; globs for families (`*.lock`, `tsconfig*.json`).
100
+ - **env files (goal: as close to one `.env` as the structure allows):** Step 0's
101
+ `env_files` lists every template and real env file. There should be one
102
+ template, `env_file` (`.env.example`, holding every key for every environment
103
+ and app), and one real `.env` beside it, gitignored. Stg/prod values belong in
104
+ the secret manager or CI.
105
+ - Bootstrap keeps an existing single template where it is. Extra templates land
106
+ in `exceptions` as the merge backlog. Tell the user how many and where.
107
+ - Offer to merge them: union the keys into `env_file`, delete the extras, and
108
+ point apps that load their own `.env` at the shared one. Do it only with the
109
+ user's go-ahead; it changes how apps load config.
110
+ - Leave vendored third-party templates (sample apps, vendored frameworks) in
111
+ `exceptions`. Don't merge them.
112
+ 4. Run the check:
113
+ ```bash
114
+ python3 .claude/project-map/structure-check.py
115
+ ```
116
+ Straight after bootstrap it's usually green. Tightening `holds` is what surfaces
117
+ FAILs. Also review the `exceptions` bootstrap added: a file that legitimately
118
+ belongs at the root (`.gitleaks.toml`) goes in `root_files`, not
119
+ the backlog. For each FAIL on a file that already exists, either widen `holds` (the manifest
120
+ was wrong) or add the path to `exceptions` (the file is in the wrong place). Tell
121
+ the user which ones you put in `exceptions`: that list is the cleanup backlog.
122
+ Always use exact paths, never globs (a glob lets future files through). A tracked
123
+ secret (`.env`): tell the user, and have them `git rm --cached` it. Add its exact
124
+ path to `exceptions` only if the user confirms it's a committed test fixture with
125
+ no real secrets (e.g. a vendored `.env.testing`). Never decide that yourself.
126
+ 5. List what differs from the layout as suggestions, not changes. For example:
127
+ "Compose files live at the root; the layout puts them in `infra/compose/`", or
128
+ "3 `.env.example` files (`apps/api`, `apps/web`, root); one at `infra/env/` would
129
+ cover all of them".
130
+ 6. Wiring: `.githooks/pre-commit` should contain a `Structure Check` block (re-run
131
+ `npx @theglitchking/babel-fish init` if not). `git config core.hooksPath` should
132
+ print `.githooks`. If the repo has CI (`.github/workflows/`), offer the CI step
133
+ (below): the hook can be skipped, CI can't. Commit the manifest.
134
+
135
+ ## Flow B: new repo
136
+
137
+ Offer two paths:
138
+
139
+ - **Pick a mode.** Explain single / monorepo / multi-repo in one line each, then
140
+ `--bootstrap --layout <mode>`. Every folder starts `planned`.
141
+ - **Plan it.** Ask what the project is: apps or services, datastores, where it
142
+ deploys, which environments. Then build the manifest from the closest layout:
143
+ - one `[[folder]]` per thing the plan needs, `status = "planned"` (approved before
144
+ it exists; the check warns once it has files, and you flip it to `active`)
145
+ - environments from the plan (default dev → stg → prod)
146
+ - drop layout folders the plan doesn't need
147
+
148
+ Show the resulting tree as a short preview and confirm before writing.
149
+
150
+ Then offer the doc templates (below). A new repo is one of their triggers.
151
+
152
+ ## Flow C: options
153
+
154
+ Run the script with no flags. With no manifest it prints the modes, what detection
155
+ found and the ways to turn the check on. Summarize that in a few lines, then ask
156
+ which flow they want. Offer the doc templates too.
157
+
158
+ ## Flow D: change the structure
159
+
160
+ Every change is an edit to the manifest, committed together with the files it
161
+ covers:
162
+
163
+ | Change | Recipe |
164
+ |---|---|
165
+ | **Add a folder** | New `[[folder]]` with a purpose (+ holds). `planned` if it doesn't exist yet, `active` once it has files. |
166
+ | **Add an app** (monorepo) | Create `apps/<name>/`. `apps` holds `*/**` already. Its env config goes in `infra/env/<env>/`, never `apps/<name>/env/`. |
167
+ | **Add an environment** | New `[[environment]]` (`target`, `promotes_to`; `mirrors` if it must match another). Create `<env_root>/<name>/` with only its deltas. If it mirrors, give it the same file set. |
168
+ | **Move files** | `git mv` them, then fix `holds` / folders. A new path inside a deprecated folder is blocked. |
169
+ | **Retire a folder** | 1) `status = "deprecated"`, so new files are blocked. 2) Move the contents out. 3) Once empty (the check warns), remove the `[[folder]]` entry and the folder **in the same commit**. Git history keeps it. |
170
+ | **Shrink the baseline** | Fix a file listed in `exceptions`. The check warns when an entry no longer allows anything; delete it. |
171
+ | **Point at another repo** | `[[repo]]` with `name`, `path` (local checkout) and/or `url`, `purpose`. That repo sets up its own manifest. Offer to do it there, as a separate step. |
172
+
173
+ On a `[structure-check] Commit blocked` failure, read the FAIL lines. Each has a
174
+ `fix:` line. Apply it, or change the manifest if the structure really should change,
175
+ and ask the user first.
176
+
177
+ ## Doc templates: only on these triggers
178
+
179
+ Write these only when (1) the user asks for them, (2) you're in Flow C, or (3) it's a
180
+ new repo (Flow B). Never overwrite an existing file; propose a diff instead.
181
+
182
+ - **`.claude/rules/repo-structure.md`**: auto-loaded, so keep it short and in the rule
183
+ form context-check accepts:
184
+ ```markdown
185
+ # Repo structure
186
+
187
+ - ALWAYS check `.claude/structure.toml` before creating a folder or a new kind of file — it lists where things go. → `<procedure doc>`
188
+ - NEVER create a top-level folder or a per-environment copy of a file without asking — structure-check blocks the commit. → `<procedure doc>`
189
+ - NEVER add a second `.env` or `.env.example` — one template (`<env_file>`) and one gitignored `.env` beside it; stg/prod values live in the secret manager. → `<procedure doc>`
190
+ ```
191
+ - **Procedure doc `changing-repo-structure.md`:** the Flow D table, rendered for this
192
+ repo's actual mode, env_roots and environments. Where it goes:
193
+ - If `.documentation/` exists (hit-em-with-the-docs), write it into
194
+ `.documentation/procedures/` and run `npx hewtd integrate <file> -a`.
195
+ - Otherwise, skip the file, point the rules file at `.claude/structure.toml`, and
196
+ tell the user the recipes are available by asking Claude.
197
+
198
+ ## CI
199
+
200
+ The pre-commit hook can be skipped (`--no-verify`) or not installed. CI is the check
201
+ that can't be skipped. It needs Python 3.11+ and the base branch fetched:
202
+
203
+ ```yaml
204
+ - uses: actions/checkout@v4
205
+ with: { fetch-depth: 0 }
206
+ - uses: actions/setup-python@v5
207
+ with: { python-version: "3.12" }
208
+ - run: python3 .claude/project-map/structure-check.py --since origin/${{ github.base_ref || 'main' }}
209
+ ```