@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.
- package/.claude/install.sh +79 -10
- package/.claude/project-map/context-check.py +156 -0
- package/.claude/project-map/generate.py +25 -0
- package/.claude/project-map/structure-check.py +773 -0
- package/.claude/project-map/test_context_check.py +221 -0
- package/.claude/project-map/test_generate.py +13 -0
- package/.claude/project-map/test_structure_check.py +864 -0
- package/.claude/templates/structure/monorepo.toml +76 -0
- package/.claude/templates/structure/multi-repo.toml +85 -0
- package/.claude/templates/structure/single.toml +73 -0
- package/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/.githooks/install.sh +0 -0
- package/.githooks/pre-commit +35 -0
- package/CHANGELOG.md +96 -0
- package/README.md +49 -3
- package/checksums.json +1 -1
- package/package.json +6 -2
- package/scripts/link-skills.js +3 -3
- package/skills/structure-bootstrap/SKILL.md +209 -0
|
@@ -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
|
+
```
|