tsykvas_rails_template 0.1.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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +200 -0
- data/CODE_OF_CONDUCT.md +10 -0
- data/LICENSE.txt +21 -0
- data/README.md +589 -0
- data/Rakefile +17 -0
- data/lib/generators/tsykvas_rails_template/companions/companions_generator.rb +273 -0
- data/lib/generators/tsykvas_rails_template/concept/concept_generator.rb +145 -0
- data/lib/generators/tsykvas_rails_template/concept/templates/component/edit.html.slim.tt +5 -0
- data/lib/generators/tsykvas_rails_template/concept/templates/component/edit.rb.tt +11 -0
- data/lib/generators/tsykvas_rails_template/concept/templates/component/index.html.slim.tt +5 -0
- data/lib/generators/tsykvas_rails_template/concept/templates/component/index.rb.tt +11 -0
- data/lib/generators/tsykvas_rails_template/concept/templates/component/new.html.slim.tt +5 -0
- data/lib/generators/tsykvas_rails_template/concept/templates/component/new.rb.tt +11 -0
- data/lib/generators/tsykvas_rails_template/concept/templates/component/show.html.slim.tt +4 -0
- data/lib/generators/tsykvas_rails_template/concept/templates/component/show.rb.tt +11 -0
- data/lib/generators/tsykvas_rails_template/concept/templates/controller.rb.tt +45 -0
- data/lib/generators/tsykvas_rails_template/concept/templates/operation/create.rb.tt +31 -0
- data/lib/generators/tsykvas_rails_template/concept/templates/operation/destroy.rb.tt +13 -0
- data/lib/generators/tsykvas_rails_template/concept/templates/operation/edit.rb.tt +10 -0
- data/lib/generators/tsykvas_rails_template/concept/templates/operation/index.rb.tt +9 -0
- data/lib/generators/tsykvas_rails_template/concept/templates/operation/new.rb.tt +10 -0
- data/lib/generators/tsykvas_rails_template/concept/templates/operation/show.rb.tt +10 -0
- data/lib/generators/tsykvas_rails_template/concept/templates/operation/update.rb.tt +31 -0
- data/lib/generators/tsykvas_rails_template/install/bootstrap_installer.rb +225 -0
- data/lib/generators/tsykvas_rails_template/install/install_generator.rb +298 -0
- data/lib/generators/tsykvas_rails_template/install/templates/.claude/agents/buddy.md +157 -0
- data/lib/generators/tsykvas_rails_template/install/templates/.claude/agents/code-reviewer.md +117 -0
- data/lib/generators/tsykvas_rails_template/install/templates/.claude/agents/security-reviewer.md +113 -0
- data/lib/generators/tsykvas_rails_template/install/templates/.claude/agents/tech-lead.md +150 -0
- data/lib/generators/tsykvas_rails_template/install/templates/.claude/commands/check.md +51 -0
- data/lib/generators/tsykvas_rails_template/install/templates/.claude/commands/code-review.md +60 -0
- data/lib/generators/tsykvas_rails_template/install/templates/.claude/commands/docs-create.md +102 -0
- data/lib/generators/tsykvas_rails_template/install/templates/.claude/commands/pr-review.md +81 -0
- data/lib/generators/tsykvas_rails_template/install/templates/.claude/commands/pushit.md +160 -0
- data/lib/generators/tsykvas_rails_template/install/templates/.claude/commands/refactor.md +132 -0
- data/lib/generators/tsykvas_rails_template/install/templates/.claude/commands/task-sum.md +47 -0
- data/lib/generators/tsykvas_rails_template/install/templates/.claude/commands/tests.md +67 -0
- data/lib/generators/tsykvas_rails_template/install/templates/.claude/commands/tsykvas-claude.md +262 -0
- data/lib/generators/tsykvas_rails_template/install/templates/.claude/commands/update-docs.md +78 -0
- data/lib/generators/tsykvas_rails_template/install/templates/.claude/commands/update-rules.md +102 -0
- data/lib/generators/tsykvas_rails_template/install/templates/.claude/commands/update-tests.md +135 -0
- data/lib/generators/tsykvas_rails_template/install/templates/.claude/docs/architecture.md +315 -0
- data/lib/generators/tsykvas_rails_template/install/templates/.claude/docs/authentication.md +96 -0
- data/lib/generators/tsykvas_rails_template/install/templates/.claude/docs/background-jobs.md +135 -0
- data/lib/generators/tsykvas_rails_template/install/templates/.claude/docs/code-style.md +101 -0
- data/lib/generators/tsykvas_rails_template/install/templates/.claude/docs/commands.md +34 -0
- data/lib/generators/tsykvas_rails_template/install/templates/.claude/docs/companions.md +128 -0
- data/lib/generators/tsykvas_rails_template/install/templates/.claude/docs/concepts-refactoring.md +194 -0
- data/lib/generators/tsykvas_rails_template/install/templates/.claude/docs/database.md +135 -0
- data/lib/generators/tsykvas_rails_template/install/templates/.claude/docs/deployment.md +138 -0
- data/lib/generators/tsykvas_rails_template/install/templates/.claude/docs/design-system.md +322 -0
- data/lib/generators/tsykvas_rails_template/install/templates/.claude/docs/documentation.md +89 -0
- data/lib/generators/tsykvas_rails_template/install/templates/.claude/docs/forms.md +174 -0
- data/lib/generators/tsykvas_rails_template/install/templates/.claude/docs/i18n.md +165 -0
- data/lib/generators/tsykvas_rails_template/install/templates/.claude/docs/routing-and-namespaces.md +114 -0
- data/lib/generators/tsykvas_rails_template/install/templates/.claude/docs/security.md +122 -0
- data/lib/generators/tsykvas_rails_template/install/templates/.claude/docs/stimulus-controllers.md +166 -0
- data/lib/generators/tsykvas_rails_template/install/templates/.claude/docs/testing-examples.md +180 -0
- data/lib/generators/tsykvas_rails_template/install/templates/.claude/docs/testing.md +117 -0
- data/lib/generators/tsykvas_rails_template/install/templates/.claude/docs/tsykvas_rails_template.md +280 -0
- data/lib/generators/tsykvas_rails_template/install/templates/.claude/docs/ui-components.md +196 -0
- data/lib/generators/tsykvas_rails_template/install/templates/CLAUDE.md.tt +81 -0
- data/lib/generators/tsykvas_rails_template/install/templates/app/concepts/base/component/base.rb +6 -0
- data/lib/generators/tsykvas_rails_template/install/templates/app/concepts/base/operation/base.rb +124 -0
- data/lib/generators/tsykvas_rails_template/install/templates/app/concepts/base/operation/result.rb +56 -0
- data/lib/generators/tsykvas_rails_template/install/templates/app/concepts/home/component/index.html.slim +49 -0
- data/lib/generators/tsykvas_rails_template/install/templates/app/concepts/home/component/index.rb +11 -0
- data/lib/generators/tsykvas_rails_template/install/templates/app/concepts/home/operation/index.rb +17 -0
- data/lib/generators/tsykvas_rails_template/install/templates/app/controllers/concerns/operations_methods.rb +148 -0
- data/lib/generators/tsykvas_rails_template/install/templates/app/controllers/home_controller.rb +10 -0
- data/lib/generators/tsykvas_rails_template/install/templates/app/policies/application_policy.rb +33 -0
- data/lib/generators/tsykvas_rails_template/install/templates/app/policies/home_policy.rb +8 -0
- data/lib/tasks/tsykvas.rake +11 -0
- data/lib/tsykvas_rails_template/probe.rb +236 -0
- data/lib/tsykvas_rails_template/railtie.rb +13 -0
- data/lib/tsykvas_rails_template/version.rb +5 -0
- data/lib/tsykvas_rails_template.rb +18 -0
- metadata +183 -0
data/lib/generators/tsykvas_rails_template/install/templates/.claude/commands/tsykvas-claude.md
ADDED
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
# /tsykvas-claude
|
|
2
|
+
|
|
3
|
+
Bootstrap and tailor `CLAUDE.md` + `.claude/docs/` to **this** project.
|
|
4
|
+
|
|
5
|
+
If `CLAUDE.md` doesn't exist yet, run `claude init` first to seed Claude's
|
|
6
|
+
own opinionated overview of the host. Then run `bundle exec rake tsykvas:probe`
|
|
7
|
+
for a deterministic inventory, integrate the gem's fenced sections into
|
|
8
|
+
`CLAUDE.md` (preserving anything Claude wrote outside the fences), and
|
|
9
|
+
**generate** host-specific docs (architecture, code-style, commands, testing,
|
|
10
|
+
ui-components, etc.) from the gem's reference templates.
|
|
11
|
+
|
|
12
|
+
Supports `--dry-run` to print a unified diff without writing.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Phase 0a — Bootstrap CLAUDE.md if missing
|
|
17
|
+
|
|
18
|
+
Check whether `CLAUDE.md` exists at the repo root:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
test -f CLAUDE.md && echo "exists" || echo "missing"
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
- **Exists** → continue to Phase 0b.
|
|
25
|
+
- **Missing** → run `claude init` (the built-in Claude Code command, NOT a
|
|
26
|
+
shell command — invoke it the same way the user would). It produces a
|
|
27
|
+
baseline `CLAUDE.md` with project overview / commands / architecture
|
|
28
|
+
inferred from the codebase. Wait for it to complete, then continue.
|
|
29
|
+
|
|
30
|
+
Why first: every subsequent phase assumes `CLAUDE.md` exists. The gem's
|
|
31
|
+
fence-based rewrite preserves user-authored content outside the fences;
|
|
32
|
+
running `claude init` first gives us a richer baseline (project name,
|
|
33
|
+
commands, conventions Claude inferred) for later phases to wrap fences
|
|
34
|
+
around — instead of starting from a blank shell.
|
|
35
|
+
|
|
36
|
+
If the user invoked `/tsykvas-claude` immediately after `bin/rails g
|
|
37
|
+
tsykvas_rails_template:install` (which creates a CLAUDE.md from the gem's
|
|
38
|
+
template), `claude init` is skipped — the file already exists.
|
|
39
|
+
|
|
40
|
+
## Phase 0b — Inventory the host project (deterministic)
|
|
41
|
+
|
|
42
|
+
Always run the Ruby probe first:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
bundle exec rake tsykvas:probe
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Output (schema v=2):
|
|
49
|
+
|
|
50
|
+
```json
|
|
51
|
+
{
|
|
52
|
+
"schema_version": 2,
|
|
53
|
+
"ruby_version": "3.4.7",
|
|
54
|
+
"rails_version": "8.0.2",
|
|
55
|
+
"default_branch": "main",
|
|
56
|
+
"api_only": false,
|
|
57
|
+
"engine_host": false,
|
|
58
|
+
"template_engine": "slim",
|
|
59
|
+
"auth": { "method": "devise", "devise": true, ... },
|
|
60
|
+
"authorization": "pundit",
|
|
61
|
+
"has_api_v1": false,
|
|
62
|
+
"has_bootstrap": false,
|
|
63
|
+
"test_framework": "rspec",
|
|
64
|
+
"background_jobs": ["solid_queue"],
|
|
65
|
+
"databases": ["primary"],
|
|
66
|
+
"concept_folders": ["home", "crm"],
|
|
67
|
+
"application_controller_includes": ["Pundit::Authorization", "OperationsMethods"]
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Bind this Hash to `probe`. If `probe.api_only` is true, skip every
|
|
72
|
+
HTML-rendering doc. If `probe.engine_host` is true, treat the host as
|
|
73
|
+
a Rails Engine (skip Application-only instructions).
|
|
74
|
+
|
|
75
|
+
If the probe rake task is missing, the host hasn't run
|
|
76
|
+
`rails g tsykvas_rails_template:install`. Stop and tell the user.
|
|
77
|
+
|
|
78
|
+
(After Phase 0a + 0b are done, treat what follows as starting from "Phase 1".)
|
|
79
|
+
|
|
80
|
+
If the host project has its own `README.md`, read it once for "what is this
|
|
81
|
+
app" copy that should seed the project-overview section.
|
|
82
|
+
|
|
83
|
+
## Phase 1 — Read existing state
|
|
84
|
+
|
|
85
|
+
For `CLAUDE.md`:
|
|
86
|
+
|
|
87
|
+
- If it doesn't exist → fresh-install case; you'll write it from
|
|
88
|
+
`.claude/docs/tsykvas_rails_template.md` cross-doc index plus the
|
|
89
|
+
fenced-section template.
|
|
90
|
+
- If it exists with `<!-- tsykvas-template:start v=X section=NAME -->` /
|
|
91
|
+
`<!-- tsykvas-template:end -->` markers → you'll **only rewrite content
|
|
92
|
+
inside those markers**. User-authored content above, between, or below
|
|
93
|
+
the fences is sacred.
|
|
94
|
+
- If it exists **without** any fences (the user ran `claude init` before
|
|
95
|
+
the gem's install, then ran `:install` which now leaves CLAUDE.md
|
|
96
|
+
alone) → you'll **add** the gem's fenced sections to a sensible position
|
|
97
|
+
(after user's existing content, separated by a horizontal rule).
|
|
98
|
+
Don't touch user prose.
|
|
99
|
+
|
|
100
|
+
For `.claude/docs/`:
|
|
101
|
+
|
|
102
|
+
- All 20 docs ship at install (under `.claude/docs/<name>.md`).
|
|
103
|
+
- The 3 gem-canonical (`tsykvas_rails_template.md`, `forms.md`,
|
|
104
|
+
`companions.md`) are kept **verbatim**.
|
|
105
|
+
- The other 17 may be **refreshed** in fenced sections to reflect the
|
|
106
|
+
host's actual stack (concept folder names, gem versions, default
|
|
107
|
+
branch, locale config). The reference content is project-agnostic
|
|
108
|
+
and ships scrubbed of any specific domain — refreshing is purely
|
|
109
|
+
about swapping in real values where the templates use placeholders.
|
|
110
|
+
|
|
111
|
+
## Phase 2a — Plan CLAUDE.md fence integration
|
|
112
|
+
|
|
113
|
+
Target sections (each its own fence in `CLAUDE.md`):
|
|
114
|
+
|
|
115
|
+
| Fence section | What goes inside |
|
|
116
|
+
|---|---|
|
|
117
|
+
| `project-overview` | 5–8 bullets pulled from `probe.ruby_version`, `probe.rails_version`, `probe.template_engine`, `probe.auth`, `probe.background_jobs`, `probe.test_framework`, `probe.default_branch`, `probe.databases`. |
|
|
118
|
+
| `architecture` | One paragraph; do not mention gems the host doesn't have (e.g. don't claim Bootstrap if `probe.has_bootstrap` is false). |
|
|
119
|
+
| `must-know-rules` | Pull from `code-style.md` (after Phase 2b generates it) and **always preserve** the `<Concept>::Form` rule with a link to `.claude/docs/forms.md`. |
|
|
120
|
+
| `routing` | Drop rows whose target doc was not generated (e.g. `api-endpoints.md` if `probe.has_api_v1` is false; `modal-refactoring.md` if `probe.has_bootstrap` is false). |
|
|
121
|
+
| `slash-commands`, `subagents` | Verbatim from the gem template unless host has added/removed files in `.claude/{commands,agents}/`. |
|
|
122
|
+
| `communication` | Verbatim default unless user has a stated preference. |
|
|
123
|
+
|
|
124
|
+
**Budget: `CLAUDE.md` must end up ≤ 100 lines.** Plan within that budget
|
|
125
|
+
before writing anything. Roughly: project-overview ≤ 8 lines, architecture
|
|
126
|
+
≤ 8 lines, must-know-rules ≤ 12 lines, routing table 4–10 rows, slash-
|
|
127
|
+
commands + subagents tables compact, communication ≤ 4 lines. If a section
|
|
128
|
+
needs more, push the overflow into a new `.claude/docs/<topic>.md` and
|
|
129
|
+
link it from the routing table. Phase 5 will reject the rewrite if
|
|
130
|
+
`wc -l CLAUDE.md` > 100.
|
|
131
|
+
|
|
132
|
+
## Phase 2b — Plan `.claude/docs/` refresh
|
|
133
|
+
|
|
134
|
+
All 20 docs already ship at install under `.claude/docs/`. Your job here
|
|
135
|
+
is **light refresh**: swap in probe-driven values where the shipped
|
|
136
|
+
template uses placeholders. **Do not trim, summarise, or rewrite the
|
|
137
|
+
shipped content.** The depth is intentional — that's why it ships.
|
|
138
|
+
|
|
139
|
+
| Doc | Refresh strategy |
|
|
140
|
+
|---|---|
|
|
141
|
+
| `architecture.md` | Replace example concept names (`Crm::Property`, `Admin::User`) with the host's actual top-level `concept_folders` if different. |
|
|
142
|
+
| `concepts-refactoring.md` | Keep verbatim — pure architecture walkthrough. |
|
|
143
|
+
| `routing-and-namespaces.md` | Replace example concept names with host's real ones. Keep the example route patterns. |
|
|
144
|
+
| `code-style.md` | Verify references to `.rubocop.yml`, `lefthook.yml`, `.github/workflows/*` resolve to files that actually exist; otherwise mark them with a TODO note. |
|
|
145
|
+
| `commands.md` | If `Procfile.dev` exists, point to `bin/dev`. Otherwise note that the watcher must be run separately. Verify test/lint commands match `bin/`. |
|
|
146
|
+
| `testing.md` + `testing-examples.md` | Confirm `probe.test_framework` (rspec / minitest). Replace any framework-specific snippets accordingly. |
|
|
147
|
+
| `ui-components.md` | Verbatim — Bootstrap is the gem default. |
|
|
148
|
+
| `stimulus-controllers.md` | Verbatim if `app/javascript/controllers/` exists; otherwise add a note that Stimulus is not currently wired. |
|
|
149
|
+
| `forms.md` | **Keep verbatim** (gem-canonical). |
|
|
150
|
+
| `companions.md` | **Keep verbatim** (gem-canonical). |
|
|
151
|
+
| `tsykvas_rails_template.md` | **Keep verbatim** (gem-canonical). |
|
|
152
|
+
| `authentication.md` | Confirm `probe.auth.method`. If `:devise`, leave as is. If custom/warden/jwt/basic_auth, replace the Devise-specific section with the host's actual auth source. |
|
|
153
|
+
| `design-system.md` | Verbatim — generic Bootstrap-default starting point. Host customises to taste. |
|
|
154
|
+
| `i18n.md` | Replace the example default-locale references with the host's actual default locale (read from `config/application.rb`). |
|
|
155
|
+
| `database.md` | Reflect actual `config/database.yml` adapters (postgres / sqlite / mysql / multi-DB). Replace the `<app_name>` placeholder with the actual host app name. |
|
|
156
|
+
| `background-jobs.md` | Confirm `probe.background_jobs`. If SolidQueue, leave as is. If Sidekiq / GoodJob / etc., replace the queue-class references. |
|
|
157
|
+
| `security.md` | Reflect host's actual Brakeman / bundler-audit / CSP setup. |
|
|
158
|
+
| `deployment.md` | If `config/deploy.yml` exists, replace `<your-app>` placeholders with host app name + image. If only `Dockerfile`, mark Kamal sections as optional. |
|
|
159
|
+
| `documentation.md` | Verbatim — generic standards doc. |
|
|
160
|
+
|
|
161
|
+
For each doc you refresh:
|
|
162
|
+
|
|
163
|
+
1. Read `.claude/docs/<name>.md` from the host.
|
|
164
|
+
2. Identify placeholder patterns (`<your-app>`, `<app_name>`, `Crm::Property`, `Admin::User`) and probe-driven hooks.
|
|
165
|
+
3. Substitute real values. Do **not** summarise or trim sample code; the
|
|
166
|
+
shipped depth is intentional and project-agnostic, so it stays.
|
|
167
|
+
4. Write back to `.claude/docs/<name>.md`.
|
|
168
|
+
|
|
169
|
+
For each doc that's already correct (no placeholders to substitute):
|
|
170
|
+
mark `keep-verbatim` in the change log.
|
|
171
|
+
|
|
172
|
+
## Phase 3 — Show the plan and wait for confirmation
|
|
173
|
+
|
|
174
|
+
If `--dry-run`:
|
|
175
|
+
|
|
176
|
+
1. Build the new content for every fence section + every doc to generate
|
|
177
|
+
in memory.
|
|
178
|
+
2. Print a unified diff (`diff -u` style) for every file that would change.
|
|
179
|
+
3. Exit. Do not write.
|
|
180
|
+
|
|
181
|
+
Otherwise present a compact plan table with **four action types**:
|
|
182
|
+
|
|
183
|
+
| File | Action | Reason |
|
|
184
|
+
|---|---|---|
|
|
185
|
+
| `CLAUDE.md` (`project-overview` fence) | rewrite-fence | seed from probe |
|
|
186
|
+
| `CLAUDE.md` (no fences yet) | create-fence | install left it untouched; integrate gem sections |
|
|
187
|
+
| `.claude/docs/architecture.md` | refresh | swap example concept names for host's actual `concept_folders` |
|
|
188
|
+
| `.claude/docs/deployment.md` | refresh | replace `<your-app>` with host service name |
|
|
189
|
+
| `.claude/docs/forms.md` | keep-verbatim | gem-canonical |
|
|
190
|
+
| … | … | … |
|
|
191
|
+
|
|
192
|
+
Ask:
|
|
193
|
+
|
|
194
|
+
> Proceed with N changes? (yes / no / dry-run / diff <file>)
|
|
195
|
+
|
|
196
|
+
- `yes` → apply.
|
|
197
|
+
- `no` → abort.
|
|
198
|
+
- `dry-run` → switch to dry-run mode and print the full diff.
|
|
199
|
+
- `diff <file>` → show the proposed diff for one file, then re-prompt.
|
|
200
|
+
|
|
201
|
+
## Phase 4 — Apply
|
|
202
|
+
|
|
203
|
+
For `CLAUDE.md`:
|
|
204
|
+
- If fences exist: replace **only** the content between matching
|
|
205
|
+
`<!-- tsykvas-template:start ... -->` and `<!-- tsykvas-template:end -->`
|
|
206
|
+
markers. Leave content above the first marker, between fences, and below
|
|
207
|
+
the last marker untouched.
|
|
208
|
+
- If no fences exist: append the gem's fenced sections after the user's
|
|
209
|
+
existing content, separated by `\n\n---\n\n`. Don't modify user prose.
|
|
210
|
+
|
|
211
|
+
For `.claude/docs/`:
|
|
212
|
+
- `keep-verbatim` files (the 3 gem-canonical + any doc with no placeholders to substitute): no-op.
|
|
213
|
+
- `refresh` files: write the placeholder-substituted content to `.claude/docs/<name>.md`. Do not trim or summarise.
|
|
214
|
+
|
|
215
|
+
## Phase 5 — Verify (mandatory; failure = roll back)
|
|
216
|
+
|
|
217
|
+
Before declaring success, run all of:
|
|
218
|
+
|
|
219
|
+
1. **CLAUDE.md ≤ 100 lines (HARD GATE).** Run `wc -l CLAUDE.md`. If
|
|
220
|
+
the result is > 100, the rewrite is rejected — `CLAUDE.md` sits in
|
|
221
|
+
every Claude session's context, so each extra line is a per-prompt
|
|
222
|
+
token tax. Re-plan, re-confirm, then re-apply.
|
|
223
|
+
2. **Link integrity.** Every `[…](.claude/docs/X.md)` in `CLAUDE.md`
|
|
224
|
+
resolves to a real file. Every slash command listed exists in
|
|
225
|
+
`.claude/commands/`. Every agent listed exists in `.claude/agents/`.
|
|
226
|
+
3. **Fence balance.** Every `tsykvas-template:start` has a matching
|
|
227
|
+
`tsykvas-template:end`. No unclosed or orphan markers.
|
|
228
|
+
4. **Code health.** Run `bin/rails zeitwerk:check`.
|
|
229
|
+
5. **Probe re-run match.** Re-run the probe. The deterministic fields it
|
|
230
|
+
reports should still match the values that drove this rewrite. (If the
|
|
231
|
+
user edited Gemfile during the run, abort.)
|
|
232
|
+
|
|
233
|
+
If any check fails, restore the pre-write state from your in-memory
|
|
234
|
+
snapshot and report which check failed. **Never leave the repo in a
|
|
235
|
+
half-rewritten state.**
|
|
236
|
+
|
|
237
|
+
## Phase 6 — Self-update
|
|
238
|
+
|
|
239
|
+
If you discover during this run that the gem's shipped templates have
|
|
240
|
+
diverged from what the host needs (e.g., a new must-know rule that should
|
|
241
|
+
live in every project), make a note in your memory file under
|
|
242
|
+
`memory/feedback_*.md` so future runs of this command in other repos start
|
|
243
|
+
from a better baseline.
|
|
244
|
+
|
|
245
|
+
---
|
|
246
|
+
|
|
247
|
+
## Constraints
|
|
248
|
+
|
|
249
|
+
- **Never edit content outside fence markers without explicit user
|
|
250
|
+
confirmation.** Treat unfenced content as user-authored.
|
|
251
|
+
- **Never edit `.claude/*.md` or `CLAUDE.md` without the Phase 3 confirmation
|
|
252
|
+
prompt.** No silent runs.
|
|
253
|
+
- **Never skip Phase 0.** The probe is the source of truth.
|
|
254
|
+
- **`CLAUDE.md` must stay ≤ 100 lines.** Hard rule, enforced at Phase 5.
|
|
255
|
+
- Use relative paths for all internal links: `.claude/docs/architecture.md`,
|
|
256
|
+
not absolute URLs.
|
|
257
|
+
- Do not commit. The user runs `/pushit` (or `git commit` themselves) when
|
|
258
|
+
they are happy with the diff.
|
|
259
|
+
- **Preserve gem-canonical docs verbatim.** `tsykvas_rails_template.md`,
|
|
260
|
+
`forms.md`, and `companions.md` ship with the gem and are the canonical
|
|
261
|
+
reference. If a section feels out of date, that's a gem update (bump the
|
|
262
|
+
gem version), not a project tailoring.
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
Check if documentation in `docs/` matches current code changes and update or create docs as needed.
|
|
2
|
+
|
|
3
|
+
## Step 1: Identify what changed
|
|
4
|
+
|
|
5
|
+
Compare current branch against `main`:
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
git diff main --name-only 2>&1
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
If working directly on `main` with uncommitted changes:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
git diff --name-only 2>&1
|
|
15
|
+
git diff --cached --name-only 2>&1
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Step 2: Understand the changes
|
|
19
|
+
|
|
20
|
+
Read the changed files and understand what flows or features were added or modified. Focus on:
|
|
21
|
+
|
|
22
|
+
- New controllers, operations, components
|
|
23
|
+
- Changed model logic (validations, callbacks, scopes)
|
|
24
|
+
- New or modified routes
|
|
25
|
+
- New mailers or jobs
|
|
26
|
+
- Configuration changes that affect behavior
|
|
27
|
+
- New integrations or external services
|
|
28
|
+
|
|
29
|
+
## Step 3: Audit existing documentation
|
|
30
|
+
|
|
31
|
+
Check what documentation already exists:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
find docs/ -name "*.md" -type f 2>&1
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
For each changed flow, determine:
|
|
38
|
+
|
|
39
|
+
1. **No doc exists** — a new doc file is needed
|
|
40
|
+
2. **Doc exists but is outdated** — the doc needs updating
|
|
41
|
+
3. **Doc exists and is current** — no action needed
|
|
42
|
+
|
|
43
|
+
## Step 4: Present findings and ask for confirmation
|
|
44
|
+
|
|
45
|
+
Show a table:
|
|
46
|
+
|
|
47
|
+
| Flow / Feature | Doc file | Status | Action needed |
|
|
48
|
+
|----------------|----------|--------|---------------|
|
|
49
|
+
| ... | `docs/...` or *none* | Current / Outdated / Missing | None / Update / Create |
|
|
50
|
+
|
|
51
|
+
Then ask:
|
|
52
|
+
|
|
53
|
+
> Found N doc(s) that need attention. Proceed?
|
|
54
|
+
> 1. Yes, update/create all
|
|
55
|
+
> 2. Let me pick which ones
|
|
56
|
+
> 3. Skip
|
|
57
|
+
|
|
58
|
+
**Wait for user response.** Do NOT make any changes without confirmation.
|
|
59
|
+
|
|
60
|
+
## Step 5: Update or create documentation
|
|
61
|
+
|
|
62
|
+
For **new docs**:
|
|
63
|
+
- Create in `docs/<domain>/` matching the feature domain (existing domains: `admin`, `crm`, `screener`, `shared`, `base` — or root for cross-cutting)
|
|
64
|
+
- Use clear markdown with sections: overview, how it works, configuration (if any), examples
|
|
65
|
+
- Keep it concise and practical — document behavior, not internal code structure
|
|
66
|
+
- Use the same style and level of detail as existing docs in `docs/` and the template in `.claude/docs/documentation.md`
|
|
67
|
+
|
|
68
|
+
For **existing docs**:
|
|
69
|
+
- Update only the sections affected by the changes
|
|
70
|
+
- Do not rewrite unrelated sections
|
|
71
|
+
- Add new sections if the change introduces new behavior
|
|
72
|
+
|
|
73
|
+
## Rules
|
|
74
|
+
|
|
75
|
+
- Documentation language: English
|
|
76
|
+
- Never delete documentation without asking
|
|
77
|
+
- Keep docs focused on **what the feature does and how to use it**, not internal code structure
|
|
78
|
+
- If unsure whether a change warrants documentation — include it in the table and let the user decide
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
Check if `.claude/docs/` or `CLAUDE.md` need updating after changes to base classes, application controller, or policies.
|
|
2
|
+
|
|
3
|
+
## Step 1: Detect changes to watched files
|
|
4
|
+
|
|
5
|
+
Check if any of these files were modified:
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
git diff main --name-only -- \
|
|
9
|
+
app/concepts/base/ \
|
|
10
|
+
app/controllers/concerns/operations_methods.rb \
|
|
11
|
+
app/controllers/application_controller.rb \
|
|
12
|
+
app/policies/application_policy.rb \
|
|
13
|
+
app/policies/admin/base_policy.rb \
|
|
14
|
+
app/policies/crm/base_policy.rb \
|
|
15
|
+
app/policies/screener/base_policy.rb \
|
|
16
|
+
2>&1
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
If on `main` with uncommitted changes:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
git diff --name-only -- \
|
|
23
|
+
app/concepts/base/ \
|
|
24
|
+
app/controllers/concerns/operations_methods.rb \
|
|
25
|
+
app/controllers/application_controller.rb \
|
|
26
|
+
app/policies/application_policy.rb \
|
|
27
|
+
app/policies/admin/base_policy.rb \
|
|
28
|
+
app/policies/crm/base_policy.rb \
|
|
29
|
+
app/policies/screener/base_policy.rb \
|
|
30
|
+
2>&1
|
|
31
|
+
git diff --cached --name-only -- \
|
|
32
|
+
app/concepts/base/ \
|
|
33
|
+
app/controllers/concerns/operations_methods.rb \
|
|
34
|
+
app/controllers/application_controller.rb \
|
|
35
|
+
app/policies/application_policy.rb \
|
|
36
|
+
app/policies/admin/base_policy.rb \
|
|
37
|
+
app/policies/crm/base_policy.rb \
|
|
38
|
+
app/policies/screener/base_policy.rb \
|
|
39
|
+
2>&1
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
**If none of these files changed — stop here. No action needed.**
|
|
43
|
+
|
|
44
|
+
## Step 2: Understand what changed
|
|
45
|
+
|
|
46
|
+
Read the diffs for each changed file:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
git diff main -- <file> 2>&1
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Understand what was added, removed, or modified in terms of:
|
|
53
|
+
|
|
54
|
+
- New methods or method signatures
|
|
55
|
+
- Changed behavior of existing methods
|
|
56
|
+
- New conventions or patterns
|
|
57
|
+
- Removed or deprecated features
|
|
58
|
+
|
|
59
|
+
## Step 3: Audit current rules
|
|
60
|
+
|
|
61
|
+
Read the relevant doc files and `CLAUDE.md`. Map each change to the doc file it affects:
|
|
62
|
+
|
|
63
|
+
| Changed file | Doc file |
|
|
64
|
+
|---|---|
|
|
65
|
+
| `app/concepts/base/operation/base.rb` | `.claude/docs/architecture.md`, `.claude/docs/concepts-refactoring.md` |
|
|
66
|
+
| `app/concepts/base/operation/result.rb` | `.claude/docs/architecture.md` |
|
|
67
|
+
| `app/concepts/base/operation/sortable.rb` | `.claude/docs/architecture.md` |
|
|
68
|
+
| `app/concepts/base/component/base.rb` | `.claude/docs/architecture.md`, `.claude/docs/ui-components.md` |
|
|
69
|
+
| `app/concepts/base/component/btn.rb` (or `btn_config.rb`) | `.claude/docs/ui-components.md` |
|
|
70
|
+
| `app/concepts/base/component/table/*.rb` | `.claude/docs/ui-components.md` |
|
|
71
|
+
| `app/concepts/base/component/title_row.rb` | `.claude/docs/ui-components.md` |
|
|
72
|
+
| `app/controllers/concerns/operations_methods.rb` | `.claude/docs/architecture.md`, `.claude/docs/concepts-refactoring.md` |
|
|
73
|
+
| `app/controllers/application_controller.rb` | `CLAUDE.md`, `.claude/docs/architecture.md` |
|
|
74
|
+
| `app/policies/application_policy.rb` | `.claude/docs/architecture.md` |
|
|
75
|
+
| `app/policies/<domain>/base_policy.rb` | `.claude/docs/architecture.md` |
|
|
76
|
+
|
|
77
|
+
## Step 4: Present proposed changes — MANDATORY
|
|
78
|
+
|
|
79
|
+
**You MUST present a table of all proposed changes and get explicit confirmation before editing ANY file in `.claude/` or `CLAUDE.md`.**
|
|
80
|
+
|
|
81
|
+
Show:
|
|
82
|
+
|
|
83
|
+
| Doc file | Section | Current text (summary) | Proposed change | Why |
|
|
84
|
+
|----------|---------|----------------------|-----------------|-----|
|
|
85
|
+
| ... | ... | ... | ... | ... |
|
|
86
|
+
|
|
87
|
+
Then ask:
|
|
88
|
+
|
|
89
|
+
> Proposed N change(s) to docs/instructions. Apply them?
|
|
90
|
+
> 1. Yes, apply all
|
|
91
|
+
> 2. Let me pick which ones
|
|
92
|
+
> 3. Skip all
|
|
93
|
+
|
|
94
|
+
**Wait for user response. Do NOT make any changes without explicit confirmation.**
|
|
95
|
+
|
|
96
|
+
## Rules
|
|
97
|
+
|
|
98
|
+
- **NEVER edit `.claude/` or `CLAUDE.md` without user confirmation.** This is non-negotiable.
|
|
99
|
+
- Keep docs concise — do not add unnecessary text that wastes tokens.
|
|
100
|
+
- Only document patterns that Claude needs to follow. If it's obvious from the code, don't add a rule for it.
|
|
101
|
+
- Remove outdated rules when the underlying code changes.
|
|
102
|
+
- Prefer updating existing sections over adding new ones.
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
Audit RSpec coverage for all `.rb` files changed on this branch vs `main`, then write or update specs where coverage is missing.
|
|
2
|
+
|
|
3
|
+
Follow project conventions from `.claude/docs/testing.md` and `.claude/docs/testing-examples.md`.
|
|
4
|
+
|
|
5
|
+
## Step 1: Find changed `.rb` files
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
git diff main --name-only 2>&1 | grep '\.rb$'
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
If `main` does not exist as a remote ref, fall back to:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
git diff origin/main --name-only 2>&1 | grep '\.rb$'
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
If working directly on `main` with uncommitted changes:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
git diff --name-only 2>&1 | grep '\.rb$'
|
|
21
|
+
git diff --cached --name-only 2>&1 | grep '\.rb$'
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
From the output, collect only files under `app/` (skip `spec/`, `db/migrate/`, `config/`, `lib/` unless they contain real business logic).
|
|
25
|
+
|
|
26
|
+
## Step 2: Filter — skip files with no testable logic
|
|
27
|
+
|
|
28
|
+
For each changed `app/**/*.rb` file, read the actual diff and the full file. **Skip** the file if it matches any of these:
|
|
29
|
+
|
|
30
|
+
- Component `.rb` that only defines `initialize` (parameter wrapper, no methods)
|
|
31
|
+
- Migration file
|
|
32
|
+
- Pure configuration (`config/`, `initializers/`)
|
|
33
|
+
- Empty class with no methods beyond `initialize` and `attr_reader`/`attr_accessor`
|
|
34
|
+
- Route file, `application.rb`, or similar framework glue
|
|
35
|
+
|
|
36
|
+
**Include** everything else: operations, services, models, controllers, jobs, policies, concerns with logic.
|
|
37
|
+
|
|
38
|
+
## Step 3: Audit each file
|
|
39
|
+
|
|
40
|
+
For every included file, do all three:
|
|
41
|
+
|
|
42
|
+
1. **Read the diff** — `git diff main -- <file>` — understand exactly what changed or was added
|
|
43
|
+
2. **Find the spec** — mirror the `app/` path under `spec/`:
|
|
44
|
+
- `app/concepts/admin/user/operation/index.rb` → `spec/concepts/admin/user/operation/index_spec.rb`
|
|
45
|
+
- `app/services/foo.rb` → `spec/services/foo_spec.rb`
|
|
46
|
+
- `app/controllers/admin/users_controller.rb` → `spec/controllers/admin/users_controller_spec.rb` or `spec/requests/admin/users_spec.rb`
|
|
47
|
+
- `app/models/user.rb` → `spec/models/user_spec.rb`
|
|
48
|
+
- `app/jobs/foo_job.rb` → `spec/jobs/foo_job_spec.rb`
|
|
49
|
+
- `app/policies/crm/company_policy.rb` → `spec/policies/crm/company_policy_spec.rb`
|
|
50
|
+
3. **Verify coverage** — read the spec (if it exists) and confirm every new/changed public method, branch, and business logic path introduced by the diff is tested. Do not assume coverage — read the spec line by line.
|
|
51
|
+
|
|
52
|
+
## Step 4: Present findings before writing
|
|
53
|
+
|
|
54
|
+
Show a table of files that need action:
|
|
55
|
+
|
|
56
|
+
| File | Spec | Status | Action |
|
|
57
|
+
|------|------|--------|--------|
|
|
58
|
+
| `app/...` | `spec/...` | Missing / Incomplete | Create / Update |
|
|
59
|
+
|
|
60
|
+
Then ask:
|
|
61
|
+
|
|
62
|
+
> Found N file(s) that need test coverage. Proceed?
|
|
63
|
+
> 1. Yes, write/update all
|
|
64
|
+
> 2. Let me pick which ones
|
|
65
|
+
> 3. Skip
|
|
66
|
+
|
|
67
|
+
**Wait for user response before writing any specs.**
|
|
68
|
+
|
|
69
|
+
## Step 5: Write or update specs
|
|
70
|
+
|
|
71
|
+
Work through each file **one at a time**:
|
|
72
|
+
|
|
73
|
+
### Writing a new spec
|
|
74
|
+
|
|
75
|
+
- `# frozen_string_literal: true` at the top
|
|
76
|
+
- `require 'rails_helper'`
|
|
77
|
+
- Use `described_class`, not the class name directly
|
|
78
|
+
- Use `let` / `let!`, FactoryBot with Faker
|
|
79
|
+
- Structure: `describe '.call'` → `context 'when ...'` → `it '...'`
|
|
80
|
+
- Cover: happy path, authorization failure (`raise_error(Pundit::NotAuthorizedError)`), error branches, edge cases
|
|
81
|
+
- Declare `type:` explicitly (this project does NOT enable `infer_spec_type_from_file_location!`)
|
|
82
|
+
|
|
83
|
+
### Updating an existing spec
|
|
84
|
+
|
|
85
|
+
- Add new `context` blocks for new branches; do not rewrite existing passing tests
|
|
86
|
+
- Keep the same describe/context depth and naming style as the rest of the file
|
|
87
|
+
|
|
88
|
+
### Skip spec creation if:
|
|
89
|
+
|
|
90
|
+
- The file contains only component initialization (no logic methods)
|
|
91
|
+
- The change is cosmetic (rename, whitespace, comment)
|
|
92
|
+
|
|
93
|
+
## Step 6: Run the specs
|
|
94
|
+
|
|
95
|
+
After writing/updating, run **only the affected spec files**:
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
bundle exec rspec <spec_file_1> <spec_file_2> ... --format documentation 2>&1
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Do **not** run the full suite — run only the files you touched.
|
|
102
|
+
|
|
103
|
+
## Step 7: Fix failures
|
|
104
|
+
|
|
105
|
+
For each failing example:
|
|
106
|
+
|
|
107
|
+
1. Read the failure message and backtrace
|
|
108
|
+
2. Read the source file and the spec
|
|
109
|
+
3. Determine root cause: bug in the spec (wrong stub, wrong expectation) or bug in the source code
|
|
110
|
+
4. Fix the appropriate file
|
|
111
|
+
5. Re-run only that spec to confirm: `bundle exec rspec <file>:<line> 2>&1`
|
|
112
|
+
|
|
113
|
+
If a failure reveals a real source code bug — fix the source and note it in the final report.
|
|
114
|
+
|
|
115
|
+
## Step 8: Report
|
|
116
|
+
|
|
117
|
+
After all specs pass, report:
|
|
118
|
+
|
|
119
|
+
```
|
|
120
|
+
## Test Coverage Update
|
|
121
|
+
|
|
122
|
+
| File | Spec | Action taken | Result |
|
|
123
|
+
|------|------|--------------|--------|
|
|
124
|
+
| app/... | spec/... | Created / Updated / Skipped | ✅ X examples, 0 failures |
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
If any spec still fails after fix attempts — show the failure and ask for guidance.
|
|
128
|
+
|
|
129
|
+
## Rules
|
|
130
|
+
|
|
131
|
+
- Never run the full suite (`bundle exec rspec`) — run only changed spec files
|
|
132
|
+
- Never delete existing passing tests
|
|
133
|
+
- Use `instance_double` over plain `double` wherever the interface is known
|
|
134
|
+
- Write tests in English
|
|
135
|
+
- Keep tests focused — one logical assertion per `it` block
|