generatesaas 3.7.0 → 3.8.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/dist/index.js +211 -159
- package/dist/skill/content/generatesaas-update/SKILL.md +121 -246
- package/dist/skill/content/generatesaas-update/scripts/classify-files.js +43 -14
- package/dist/skill/content/generatesaas-update/scripts/complete-update.js +40 -13
- package/dist/skill/content/generatesaas-update/scripts/prepare-update.js +21 -7
- package/package.json +4 -1
|
@@ -1,56 +1,44 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: update
|
|
3
|
-
description: Update a GenerateSaaS project to the latest boilerplate version. Use this whenever the user asks to "update my GenerateSaaS project",
|
|
3
|
+
description: Update a GenerateSaaS project to the latest boilerplate version. Use this whenever the user asks to "update my GenerateSaaS project", update their GenerateSaaS boilerplate/template, or pull the latest GenerateSaaS changes. Fetches and stages the new version, surfaces newly available options, classifies files, and merges every upstream change into the user's customizations - stopping only when a change is risky, uncertain, or alters what the app does or how it looks.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# GenerateSaaS Update
|
|
7
7
|
|
|
8
8
|
Update your project to the latest GenerateSaaS boilerplate version while preserving all your customizations.
|
|
9
9
|
|
|
10
|
+
## Intent
|
|
11
|
+
|
|
12
|
+
The owner wants **every change from the new version**. A customization the user made is **kept and merged with the upstream change in the same file**. The only reason to hold an upstream change back is a conflict with a customization you cannot resolve with confidence, or one of the [mandatory stops](#mandatory-stops).
|
|
13
|
+
|
|
14
|
+
Run the whole update **unattended** by default - fetch, stage, classify, merge, validate, and complete - without asking the user to pick a mode or confirm each step. Stop only at a mandatory stop, and only there.
|
|
15
|
+
|
|
10
16
|
## Core Principles
|
|
11
17
|
|
|
12
|
-
1. **
|
|
13
|
-
2. **Never break user code** -
|
|
14
|
-
3. **Full transparency** -
|
|
15
|
-
4. **Track everything** -
|
|
18
|
+
1. **Take every upstream change** - bring the new version in fully and merge it with the user's customizations in the same file. Never silently drop an upstream change.
|
|
19
|
+
2. **Never break user code** - when an upstream change conflicts with a customization you cannot merge with confidence, stop and ask. Keep the user's version if they choose, and record what was skipped.
|
|
20
|
+
3. **Full transparency** - the final report says what was auto-applied, what was merged, what was held and why, and what the user must still do (migrations, env).
|
|
21
|
+
4. **Track everything** - every change is tracked in the plan file: completed, merged, skipped, or failed, with a reason.
|
|
16
22
|
|
|
17
23
|
## Workflow Overview
|
|
18
24
|
|
|
19
25
|
```
|
|
20
26
|
Step 0: Pre-flight safety checks
|
|
21
27
|
Step 1: Fetch + stage + prepare update data (you run the CLI, then the script)
|
|
22
|
-
Step 2:
|
|
28
|
+
Step 2: Summarize the changelog
|
|
23
29
|
Step 2.5: Review newly available options - adopt or keep default (re-stage if adopted)
|
|
24
30
|
Step 3: Classify files (script)
|
|
25
31
|
Step 4: Analyze dependencies
|
|
26
|
-
Step 5:
|
|
32
|
+
Step 5: Write the plan, then apply
|
|
27
33
|
Step 6: Apply safe auto-updates (script)
|
|
28
|
-
Step 7:
|
|
34
|
+
Step 7: Merge modified files - stopping only at a mandatory stop
|
|
29
35
|
Step 8: Post-update validation
|
|
30
36
|
Step 9: Complete update (script)
|
|
31
37
|
```
|
|
32
38
|
|
|
33
|
-
**You own the whole flow.** When the user says "update my GenerateSaaS project," do
|
|
34
|
-
|
|
35
|
-
The
|
|
36
|
-
|
|
37
|
-
**Automatic mode.** If the user's request includes the word "auto" (e.g. "update auto",
|
|
38
|
-
"update my GenerateSaaS project, auto"), or `staging.json` has `"mode": "auto"` (set by
|
|
39
|
-
`generatesaas update auto`), run the entire update **unattended** in Automatic mode: skip
|
|
40
|
-
the Step 5 mode prompt and proceed start to finish, making the best decisions to bring in
|
|
41
|
-
upstream changes while preserving the user's customizations. Automatic mode still **stops to
|
|
42
|
-
ask** whenever a decision is genuinely risky or you are not confident - and it always runs
|
|
43
|
-
the Step 2.5 new-options review (surfacing a new feature is never a decision to assume). The
|
|
44
|
-
exact always-ask triggers are listed in Step 5 and "When to Always Ask".
|
|
45
|
-
|
|
46
|
-
**What the staged update contains (important):** `generatesaas update` re-shapes the
|
|
47
|
-
new version's template into THIS project's exact configuration before staging - same
|
|
48
|
-
frontend, payment provider, database, feature flags, etc. So everything in
|
|
49
|
-
`.generatesaas/staging/` and the `.generatesaas/template/` baseline is buyer-shaped:
|
|
50
|
-
you will never see another framework's files, a provider the project doesn't use, the
|
|
51
|
-
boilerplate's internal tooling, or dev-only secrets. Every diff you surface already
|
|
52
|
-
applies to this project. The 3-way merge baseline (`.generatesaas/template/`) is a
|
|
53
|
-
faithful pristine copy of what this project started from - trust it.
|
|
39
|
+
**You own the whole flow.** When the user says "update my GenerateSaaS project," do everything end-to-end - including fetching and staging the new version (Step 1). The user does not run any CLI command themselves.
|
|
40
|
+
|
|
41
|
+
**What the staged update contains (important):** `generatesaas update` re-shapes the new version's template into THIS project's exact configuration before staging - same frontend, payment provider, database, feature flags, etc. So everything in `.generatesaas/staging/` and the `.generatesaas/template/` baseline is buyer-shaped: you will never see another framework's files, a provider the project doesn't use, the boilerplate's internal tooling, or dev-only secrets. Every diff you surface already applies to this project. The 3-way merge baseline (`.generatesaas/template/`) is a faithful pristine copy of what this project started from - trust it.
|
|
54
42
|
|
|
55
43
|
---
|
|
56
44
|
|
|
@@ -84,29 +72,25 @@ If starting fresh, delete the old plan file. Note: files that were auto-applied
|
|
|
84
72
|
|
|
85
73
|
### Step 1: Fetch, Stage, and Prepare Update Data
|
|
86
74
|
|
|
87
|
-
**1a. Stage the new version yourself.** Unless a staged update already exists
|
|
88
|
-
(`.generatesaas/staging.json` present), run the CLI to fetch the latest version and
|
|
89
|
-
stage it - re-shaped for this project's exact configuration:
|
|
75
|
+
**1a. Stage the new version yourself.** Unless a staged update already exists (`.generatesaas/staging.json` present), run the CLI to fetch the latest version and stage it - re-shaped for this project's exact configuration:
|
|
90
76
|
|
|
91
77
|
```bash
|
|
92
78
|
npx generatesaas@latest update
|
|
93
79
|
```
|
|
94
80
|
|
|
95
|
-
This resolves the saved API key from `~/.generatesaas` (written at init), so it runs
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
81
|
+
This resolves the saved API key from `~/.generatesaas` (written at init), so it runs non-interactively - it never prompts you for a key. It refreshes the skill files, downloads the new version, shapes it into this project's configuration, and writes `.generatesaas/staging/` + `staging.json`. If it reports "Already on the latest version," there is nothing to update - tell the user and stop. If it fails because the API key is missing or rejected, ask the user to run `generatesaas auth` (which sets the key once and saves it), then re-run the update. For a network error, ask them to retry.
|
|
82
|
+
|
|
83
|
+
**If `update` exits asking a question.** A few decisions are the buyer's alone (a retired desktop-AI shape, a retired option whose new default spends money or profiles end users). Because you run the CLI without a terminal, it cannot prompt you: it prints the question with a **stable id** and its **allowed choices**, then exits non-zero. Do not guess. Relay the question and its choices to the user, collect their answer, and re-run with the choice appended:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
npx generatesaas@latest update --answer <id>=<choice>
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
`--answer` is repeatable - pass one per question if the CLI asks more than one. An unknown id or choice is rejected with the valid values, so read the error and correct the flag.
|
|
102
90
|
|
|
103
|
-
> Note: this command also rewrites the skill scripts to their latest version. That is
|
|
104
|
-
> expected - the scripts you run in the following steps are the freshly-installed ones.
|
|
91
|
+
> Note: this command also rewrites the skill scripts to their latest version. That is expected - the scripts you run in the following steps are the freshly-installed ones.
|
|
105
92
|
|
|
106
|
-
**Re-read this SKILL.md now**, from `__SKILL_ROOT__/generatesaas-update/SKILL.md`. The command
|
|
107
|
-
just overwrote it along with the scripts, so the copy in your context is the PREVIOUS release's
|
|
108
|
-
instructions while every script you are about to run is the new one. Follow the file on disk
|
|
109
|
-
wherever the two disagree.
|
|
93
|
+
**Re-read this SKILL.md now**, from `__SKILL_ROOT__/generatesaas-update/SKILL.md`. The command just overwrote it along with the scripts, so the copy in your context is the PREVIOUS release's instructions while every script you are about to run is the new one. Follow the file on disk wherever the two disagree.
|
|
110
94
|
|
|
111
95
|
**1b. Prepare the diff/classification data:**
|
|
112
96
|
|
|
@@ -116,16 +100,10 @@ node __SKILL_ROOT__/generatesaas-update/scripts/prepare-update.js
|
|
|
116
100
|
|
|
117
101
|
Creates:
|
|
118
102
|
- `references/changelog.md` - what changed and why
|
|
119
|
-
- `references/diffs/<path>.diff` - one unified diff per changed file, named by the
|
|
120
|
-
|
|
121
|
-
`references/diffs/packages/config/src/index.ts.diff`). Diffs cover `modified` +
|
|
122
|
-
`added` files; `unmodified`, `deleted`, and `removed` files have none.
|
|
123
|
-
- `references/update-manifest.json` - lists of added, modified, and removed files,
|
|
124
|
-
plus `renamed` (upstream renames detected by identical content: `[{from, to}]`)
|
|
125
|
-
and `sensitive` (database schema, `packages/database/drizzle/`, and
|
|
126
|
-
`.env.example` changes that carry follow-up work: migrations, new env vars)
|
|
103
|
+
- `references/diffs/<path>.diff` - one unified diff per changed file, named by the file's project-relative path with `.diff` appended (e.g. `references/diffs/packages/config/src/index.ts.diff`). Diffs cover `modified` + `added` files; `unmodified`, `deleted`, and `removed` files have none.
|
|
104
|
+
- `references/update-manifest.json` - lists of added, modified, and removed files, plus `renamed` (upstream renames detected by identical content: `[{from, to}]`) and `sensitive` (database schema, `packages/database/drizzle/`, and `.env.example` changes that carry follow-up work: migrations, new env vars)
|
|
127
105
|
|
|
128
|
-
### Step 2:
|
|
106
|
+
### Step 2: Summarize the Changelog
|
|
129
107
|
|
|
130
108
|
Read `references/changelog.md`. When the update spans multiple releases, it contains one `# vX.Y.Z` section per release, oldest first - read ALL of them, not just the last; a breaking change can sit in any intermediate release. A `[BREAKING]` marker on a section header is authoritative (it comes from the version index: a major bump or release notes flagged BREAKING) - always call those releases out explicitly.
|
|
131
109
|
|
|
@@ -136,7 +114,7 @@ Each release's notes may be one of two shapes:
|
|
|
136
114
|
|
|
137
115
|
Also read `sensitive` in `references/update-manifest.json`: database schema changes mean a migration is likely required, anything under `packages/database/drizzle/` means upstream migrations that must be regenerated into the project's own history before they will run (see [Database](#database-schema-migrations)), and `.env.example` changes mean new or changed environment variables. Mention all three in the summary and again in the final post-update steps.
|
|
138
116
|
|
|
139
|
-
Present a clear, organized summary:
|
|
117
|
+
Present a clear, organized summary (this is a summary, not a gate - continue straight to the next step):
|
|
140
118
|
|
|
141
119
|
> ## What's New in v{targetVersion}
|
|
142
120
|
>
|
|
@@ -147,19 +125,11 @@ Present a clear, organized summary:
|
|
|
147
125
|
|
|
148
126
|
**Be honest about uncertainty.** Never present an inferred "Breaking changes: None" or "Migration steps: None" as if it were authoritative when the changelog is raw PR titles - say it's not specified and that you'll watch for schema/config/env changes during the file review. A silently-missed migration (e.g. a new DB column) is the worst failure mode.
|
|
149
127
|
|
|
150
|
-
Then ask: *"Ready to proceed with the file analysis?"*
|
|
151
|
-
|
|
152
|
-
Wait for the user to confirm before continuing.
|
|
153
|
-
|
|
154
128
|
### Step 2.5: Review Newly Available Options
|
|
155
129
|
|
|
156
|
-
The boilerplate adds features over time. When this project predates one, `generatesaas update`
|
|
157
|
-
records it in `staging.json` under `newOptions` (and has already default-filled the manifest so
|
|
158
|
-
it stays complete). Read `newOptions` from `.generatesaas/staging.json`. **If it is absent or
|
|
159
|
-
empty, skip this step entirely.**
|
|
130
|
+
The boilerplate adds features over time. When this project predates one, `generatesaas update` records it in `staging.json` under `newOptions` (and has already default-filled the manifest so it stays complete). Read `newOptions` from `.generatesaas/staging.json`. **If it is absent or empty, skip this step entirely.**
|
|
160
131
|
|
|
161
|
-
Otherwise, present each option so the user can decide whether to adopt it. Each entry has
|
|
162
|
-
`{ key, label, hint, default, impact, choices?, requiresLabel? }`. For each one:
|
|
132
|
+
Otherwise, present each option so the user can decide whether to adopt it. Adopting a new feature is a [mandatory stop](#mandatory-stops) - surfacing it is never a decision to assume. Each entry has `{ key, label, hint, default, impact, choices?, requiresLabel? }`. For each one:
|
|
163
133
|
|
|
164
134
|
```
|
|
165
135
|
### New since your version: {label}
|
|
@@ -177,9 +147,7 @@ it is a large surface you didn't originally choose" or "Safe to adopt - it is pu
|
|
|
177
147
|
> 2. **Adopt it** - turn this feature on
|
|
178
148
|
```
|
|
179
149
|
|
|
180
|
-
**An entry with `choices` is not a yes/no.** It takes one of several values, so the two-way block
|
|
181
|
-
above cannot express it - offer the values as a numbered pick list instead, one line per choice,
|
|
182
|
-
with the entry's `default` marked as the current behavior:
|
|
150
|
+
**An entry with `choices` is not a yes/no.** It takes one of several values, so the two-way block above cannot express it - offer the values as a numbered pick list instead, one line per choice, with the entry's `default` marked as the current behavior:
|
|
183
151
|
|
|
184
152
|
```
|
|
185
153
|
**Default:** `{default}` (your project's current behavior is unchanged).
|
|
@@ -191,34 +159,19 @@ with the entry's `default` marked as the current behavior:
|
|
|
191
159
|
> 3. **`{choices[2]}`** ...one line per choice, however many there are
|
|
192
160
|
```
|
|
193
161
|
|
|
194
|
-
|
|
195
|
-
feature is exactly the kind of decision the update must never assume. Give your recommendation,
|
|
196
|
-
but the user decides.
|
|
162
|
+
Give your recommendation, but the user decides.
|
|
197
163
|
|
|
198
164
|
**Applying the decisions:**
|
|
199
165
|
|
|
200
|
-
1. For each option the user **adopts**, write the value they picked into
|
|
201
|
-
|
|
202
|
-
is `true` (e.g. set `"desktop": true`); for one with `choices` it is the choice they named,
|
|
203
|
-
verbatim (e.g. set `"errorTracking": "sentry"`). Never write `true` for an option that has
|
|
204
|
-
`choices` - the CLI refuses any value outside them and stages nothing at all. The manifest is the
|
|
205
|
-
single shaping input.
|
|
206
|
-
2. **If the user adopted at least one option, re-stage once** so re-shaping produces the
|
|
207
|
-
feature's files. Re-run the CLI (append `auto` if you are in Automatic mode, so the staged
|
|
208
|
-
metadata keeps the unattended signal):
|
|
166
|
+
1. For each option the user **adopts**, write the value they picked into `.generatesaas/manifest.json` under the entry's `key`. For an option with no `choices` that value is `true` (e.g. set `"desktop": true`); for one with `choices` it is the choice they named, verbatim (e.g. set `"errorTracking": "sentry"`). Never write `true` for an option that has `choices` - the CLI refuses any value outside them and stages nothing at all. The manifest is the single shaping input.
|
|
167
|
+
2. **If the user adopted at least one option, re-stage once** so re-shaping produces the feature's files:
|
|
209
168
|
|
|
210
169
|
```bash
|
|
211
170
|
npx generatesaas@latest update
|
|
212
171
|
```
|
|
213
172
|
|
|
214
|
-
Because the manifest now carries the adopted flags, the new `.generatesaas/staging/` includes
|
|
215
|
-
|
|
216
|
-
adoption is handled the same way for `config` and `structural` options: both are applied by
|
|
217
|
-
re-shaping, never by mimicking the generator. The adopted keys are now present in the
|
|
218
|
-
manifest, so they will not re-appear in `newOptions`.
|
|
219
|
-
3. Re-read `staging.json`, then continue to Step 3. Classification runs on the final staging, so
|
|
220
|
-
the adopted feature's files are classified as `new` and created in Step 6. Nothing is applied
|
|
221
|
-
before this point, so a re-stage never leaves a half-applied tree.
|
|
173
|
+
Because the manifest now carries the adopted flags, the new `.generatesaas/staging/` includes the feature - config flags and whole new trees alike - with no hand-editing. This is why adoption is handled the same way for `config` and `structural` options: both are applied by re-shaping, never by mimicking the generator. The adopted keys are now present in the manifest, so they will not re-appear in `newOptions`.
|
|
174
|
+
3. Re-read `staging.json`, then continue to Step 3. Classification runs on the final staging, so the adopted feature's files are classified as `new` and created in Step 6. Nothing is applied before this point, so a re-stage never leaves a half-applied tree.
|
|
222
175
|
4. If the user adopted nothing, continue to Step 3 directly.
|
|
223
176
|
|
|
224
177
|
### Step 3: Classify Files
|
|
@@ -230,11 +183,11 @@ node __SKILL_ROOT__/generatesaas-update/scripts/classify-files.js
|
|
|
230
183
|
Read `references/classification.json`. It contains:
|
|
231
184
|
|
|
232
185
|
- **unmodified** - file matches the original template, safe to replace
|
|
233
|
-
- **modified** - user has customized this file, needs
|
|
186
|
+
- **modified** - user has customized this file, needs a merge
|
|
234
187
|
- **deleted** - user deleted this file, skip update for it
|
|
235
188
|
- **new** - file doesn't exist locally and its directory tree is genuinely new upstream, safe to create
|
|
236
|
-
- **newInDeletedTree** - file is new upstream BUT lives inside a directory tree the user intentionally deleted (the tree existed in the baseline and is now gone on disk). **Never auto-create these
|
|
237
|
-
- **removed** - file was removed upstream,
|
|
189
|
+
- **newInDeletedTree** - file is new upstream BUT lives inside a directory tree the user intentionally deleted (the tree existed in the baseline and is now gone on disk). **Never auto-create these** (a [mandatory stop](#mandatory-stops)). Ask the user whether to bring the tree back (see "For New Files In Deleted Trees" in Step 7).
|
|
190
|
+
- **removed** - file was removed upstream, you decide whether to delete (see Step 7)
|
|
238
191
|
- **crossDependencies** - import relationships between categories (if detected)
|
|
239
192
|
|
|
240
193
|
### Step 4: Analyze Dependencies
|
|
@@ -247,7 +200,7 @@ This step prevents breaking the user's code through indirect effects.
|
|
|
247
200
|
- `newImportsModified` - new files that import from modified files
|
|
248
201
|
|
|
249
202
|
2. **For each cross-dependency**, read the relevant diff at `references/diffs/<path>.diff`. Handle all three directions the classifier emits:
|
|
250
|
-
- **`modifiedImportsUnmodified`** - a modified file imports from an auto-apply (unmodified) file. If the auto-apply file's diff changes **exports, function signatures, types, or interfaces** that the modified file uses → promote it from `unmodified` to `modified` (it needs
|
|
203
|
+
- **`modifiedImportsUnmodified`** - a modified file imports from an auto-apply (unmodified) file. If the auto-apply file's diff changes **exports, function signatures, types, or interfaces** that the modified file uses → promote it from `unmodified` to `modified` (it needs a merge alongside its dependent, so the merge accounts for the new API).
|
|
251
204
|
- **`unmodifiedImportsModified`** - an auto-apply file imports from a modified file. After the modified file is handled in Step 7, re-check this auto-apply file: if the user kept their version of the modified file but the auto-apply file's new version expects the upstream API, the auto-apply file may not be compatible. Flag it and revisit in the Step 7 cascade-awareness check.
|
|
252
205
|
- **`newImportsModified`** - a new file imports from a modified file. The new file will be auto-created in Step 6. After the modified file is handled, verify the new file's imports resolve against whatever version of the modified file the user ended up with (their merge, their kept version, or upstream). If the new file expects the upstream API but the user kept their version, surface it.
|
|
253
206
|
|
|
@@ -255,11 +208,9 @@ This step prevents breaking the user's code through indirect effects.
|
|
|
255
208
|
|
|
256
209
|
4. If there are no cross-dependencies or all cross-dependencies are safe (no API changes), no reclassification is needed.
|
|
257
210
|
|
|
258
|
-
### Step 5:
|
|
259
|
-
|
|
260
|
-
Generate the plan file at `.generatesaas/updates/update-{currentVersion}-to-{targetVersion}.md`.
|
|
211
|
+
### Step 5: Write the Plan, Then Apply
|
|
261
212
|
|
|
262
|
-
|
|
213
|
+
Generate the plan file at `.generatesaas/updates/update-{currentVersion}-to-{targetVersion}.md`:
|
|
263
214
|
|
|
264
215
|
```markdown
|
|
265
216
|
# Update: {currentVersion} → {targetVersion}
|
|
@@ -277,8 +228,8 @@ These files haven't been customized and will be updated automatically:
|
|
|
277
228
|
New in this version:
|
|
278
229
|
- [ ] `path/to/new-file.ts` - {what this file does}
|
|
279
230
|
|
|
280
|
-
## Files Needing
|
|
281
|
-
These files have your customizations. Each
|
|
231
|
+
## Files Needing a Merge ({count} files)
|
|
232
|
+
These files have your customizations. Each is merged with the upstream change:
|
|
282
233
|
- [ ] `path/to/modified.ts` - Risk: {Low/Medium/High} - {what changed}
|
|
283
234
|
|
|
284
235
|
## Removed Upstream ({count} files)
|
|
@@ -289,119 +240,68 @@ Removed in the new version - you decide whether to delete:
|
|
|
289
240
|
{Empty - items move here during execution with reasons}
|
|
290
241
|
```
|
|
291
242
|
|
|
292
|
-
|
|
293
|
-
**skip this prompt** - do not ask the user to choose a mode. Use Automatic mode (described below)
|
|
294
|
-
and proceed. Note in the plan that Automatic mode was selected.
|
|
243
|
+
Then show the user a **short plan** and continue - no mode question, no proceed gate:
|
|
295
244
|
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
>
|
|
245
|
+
> **Update plan: v{currentVersion} → v{targetVersion}**
|
|
246
|
+
>
|
|
247
|
+
> - {N} safe files auto-applied, {N} new files created
|
|
248
|
+
> - {N} customized files merged with the upstream change
|
|
249
|
+
> - {N} removed upstream, {N} needing your decision
|
|
299
250
|
>
|
|
300
|
-
>
|
|
301
|
-
> 2. **Careful** - I'll present every single change for your approval, including auto-updates. Nothing happens without your explicit OK.
|
|
302
|
-
> 3. **Quick** - Auto-apply safe files, auto-apply my recommended merges for low-risk files, and only ask you about medium/high-risk changes.
|
|
303
|
-
> 4. **Automatic** - Run the whole update unattended: auto-apply safe files and auto-merge low- and medium-risk files I'm confident about, only stopping to ask when a decision is genuinely risky or I'm unsure. (This is what `update auto` selects.)
|
|
304
|
-
|
|
305
|
-
**Wait for the user's choice.** Default to **Recommended** if they just say "proceed" or similar.
|
|
306
|
-
|
|
307
|
-
#### Automatic mode behavior
|
|
308
|
-
|
|
309
|
-
In Automatic mode, run the entire flow without prompting **except** at the mandatory stops below:
|
|
310
|
-
|
|
311
|
-
- **Auto-apply** safe (`unmodified`) and genuinely-`new` files, same as Recommended.
|
|
312
|
-
- **Auto-merge Low AND Medium risk** modified files when you are confident the merge preserves
|
|
313
|
-
the user's customizations (this is the difference from Quick, which stops at Low). Report each
|
|
314
|
-
merge you apply.
|
|
315
|
-
- **Always stop and ask** - even in Automatic mode - for:
|
|
316
|
-
- High-risk or structurally conflicting files, and files the user heavily rewrote (>30% diverged).
|
|
317
|
-
- Database schema changes (never auto-merge schema).
|
|
318
|
-
- `.env.example` changes that imply a decision (new required variables).
|
|
319
|
-
- Removed-upstream files that other project code imports (run the import search first).
|
|
320
|
-
- Renames where the user customized the old path (porting customizations is a judgment call).
|
|
321
|
-
- **Any merge you are not confident preserves the user's intent.** When unsure, ask. It is
|
|
322
|
-
always better to interrupt than to assume.
|
|
323
|
-
- **Removed files:** auto-delete only when the user never modified the file AND no importers are
|
|
324
|
-
found; otherwise ask.
|
|
325
|
-
- **New files in deleted trees (`newInDeletedTree`):** keep them deleted (never resurrect a tree
|
|
326
|
-
the user removed); note it in the summary, no prompt needed.
|
|
327
|
-
- **Validation (Step 8):** run the FULL ladder - lint, type check, tests, dependency
|
|
328
|
-
parity, the auth probe when auth changed, and the e2e gate; if the update introduced
|
|
329
|
-
breakage you can fix with confidence, fix it and re-verify; if not, stop and ask.
|
|
330
|
-
Unattended never means ungated: the e2e rung is still required.
|
|
331
|
-
|
|
332
|
-
The Step 2.5 new-options review still runs and still asks per option - Automatic mode never
|
|
333
|
-
auto-adopts a new feature.
|
|
251
|
+
> **I'll stop to ask you about:** {list the mandatory stops you expect for THIS update - e.g. a schema change, a new required env var, {N} new options, a removed file still imported, a merge that changes a route or a screen. Say "none expected" if you anticipate none.}
|
|
334
252
|
|
|
335
|
-
|
|
253
|
+
Then proceed to Step 6.
|
|
336
254
|
|
|
337
|
-
|
|
255
|
+
### Step 6: Apply Safe Auto-Updates
|
|
338
256
|
|
|
339
|
-
|
|
257
|
+
Preview first (optional), then apply:
|
|
340
258
|
|
|
341
|
-
Preview first (especially useful in Careful mode or when unsure), then apply:
|
|
342
259
|
```bash
|
|
343
260
|
node __SKILL_ROOT__/generatesaas-update/scripts/apply-auto.js --dry-run # lists every file it would update/create, changes nothing
|
|
344
261
|
node __SKILL_ROOT__/generatesaas-update/scripts/apply-auto.js
|
|
345
262
|
```
|
|
263
|
+
|
|
346
264
|
`apply-auto.js` copies only `unmodified` (safe replace) + `new` (any upstream-added file whose tree the buyer has not deleted). It will **never** touch `newInDeletedTree` files, and it aborts without writing anything if any source is missing from staging (no half-applied tree). Report what was applied. Mark all auto-update and new file items as `[x]` in the plan - **except any file the script reports as held back**, which was never applied and moves to **Skipped** with the regenerate reason. Marking a held-back migration `[x]` records a table that does not exist as delivered, in the one artifact that outlives the session.
|
|
347
265
|
|
|
348
266
|
It also holds back everything under `packages/database/drizzle/` and lists what it skipped. Those are NOT pending work you can copy in afterwards - migrations must be regenerated into the project's own history or they never run. See [Database](#database-schema-migrations).
|
|
349
267
|
|
|
350
|
-
|
|
351
|
-
Present the list of safe auto-updates and new files to the user:
|
|
352
|
-
> These {N} files haven't been customized and can be safely replaced with the new version. {N} new files will be created. Want me to apply all of these, or would you like to review any specific ones first?
|
|
353
|
-
|
|
354
|
-
If the user wants to review specific files, show them the diff for each requested file. Apply only after approval. Do not count held-back migrations in either number - they are not being created, and presenting them as applied is the same error as marking them `[x]`.
|
|
268
|
+
### Step 7: Merge Modified Files
|
|
355
269
|
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
This is the most important step. Work through each file in the `modified` category.
|
|
270
|
+
This is the most important step. Work through each file in the `modified` category. Merge the upstream change into the user's file, preserving their customizations - and stop to ask only when a [mandatory stop](#mandatory-stops) applies.
|
|
359
271
|
|
|
360
272
|
#### For Each Modified File
|
|
361
273
|
|
|
362
|
-
For each file, you have three versions available for proper three-way merge
|
|
274
|
+
For each file, you have three versions available for a proper three-way merge:
|
|
363
275
|
|
|
364
276
|
1. **Old template:** `.generatesaas/template/<path>` - the original boilerplate version
|
|
365
277
|
2. **New template:** `.generatesaas/staging/<path>` - the updated boilerplate version
|
|
366
278
|
3. **User's version:** the current file on disk - their customized version
|
|
367
279
|
|
|
368
|
-
The diff at `references/diffs/<path>.diff` shows **pure upstream changes** (old template → new template), making it easy to see exactly what
|
|
369
|
-
|
|
370
|
-
If `.generatesaas/template/<path>` does not exist (backward compat), fall back to comparing the user's file against staging directly. If no diff file exists, read both files to understand the differences.
|
|
280
|
+
The diff at `references/diffs/<path>.diff` shows **pure upstream changes** (old template → new template), making it easy to see exactly what changed and why. If `.generatesaas/template/<path>` does not exist (backward compat), fall back to comparing the user's file against staging directly. If no diff file exists, read both files to understand the differences.
|
|
371
281
|
|
|
372
|
-
**
|
|
282
|
+
**Assess the merge:**
|
|
373
283
|
|
|
374
|
-
|
|
375
|
-
|
|
284
|
+
- **What changed upstream** (old template → new template, from the diff and changelog)
|
|
285
|
+
- **What the user changed** (old template → user's file)
|
|
286
|
+
- **Overlap** (None / Partial / Significant) and **Risk** (Low = changes don't overlap; Medium = some overlap, cleanly resolvable; High = structural conflict or a heavily rewritten file)
|
|
376
287
|
|
|
377
|
-
**
|
|
378
|
-
**What you changed:** {describe changes from old template → user's file - compare the two to identify customizations}
|
|
379
|
-
**Overlap:** {None / Partial / Significant}
|
|
380
|
-
**Risk:** {Low / Medium / High}
|
|
288
|
+
**Then act by whether a mandatory stop applies:**
|
|
381
289
|
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
**My recommendation:** {one of the actions below}
|
|
385
|
-
|
|
386
|
-
{If recommending a merge, show the proposed result with comments marking the source:}
|
|
387
|
-
```
|
|
388
|
-
|
|
389
|
-
**Then present the user's options:**
|
|
290
|
+
- **No mandatory stop, and you are confident the merge preserves the user's customizations:** apply the merge and report it (one line: what upstream added, what user code it kept). This is the default path for most files.
|
|
291
|
+
- **A mandatory stop applies** (you are not confident; the merge changes observable behaviour or how a screen looks; or another stop below): present both versions side by side and let the user choose:
|
|
390
292
|
|
|
293
|
+
> ### `{file path}`
|
|
294
|
+
>
|
|
295
|
+
> **What changed upstream:** {…}
|
|
296
|
+
> **What you changed:** {…}
|
|
297
|
+
> **Why I'm asking:** {which mandatory stop - low confidence, a changed route/default/limit/flow, changed layout/copy/theme, …}
|
|
298
|
+
>
|
|
391
299
|
> **What would you like to do?**
|
|
392
300
|
> 1. **Accept merge** - {brief description of the merged result}
|
|
393
301
|
> 2. **Keep my version** - Skip this upstream change entirely
|
|
394
302
|
> 3. **Use upstream version** - Replace with the new template version (your changes will be lost)
|
|
395
|
-
> 4. **Show me the diff** - Display the raw upstream diff
|
|
396
|
-
> 5. **
|
|
397
|
-
|
|
398
|
-
**In Quick mode:** For **Low risk** files, apply the recommended merge automatically and report what was done. For **Medium/High risk**, always ask.
|
|
399
|
-
|
|
400
|
-
**In Automatic mode:** For **Low and Medium risk** files, apply the recommended merge automatically when you are confident it preserves the user's customizations, and report what was done. For **High risk** files - and any merge you are not confident about - always ask (see "Automatic mode behavior" in Step 5).
|
|
401
|
-
|
|
402
|
-
**In Recommended mode:** Present each file and wait for the user's decision.
|
|
403
|
-
|
|
404
|
-
**In Careful mode:** Present each file with the full proposed merged code shown, and wait for the user's decision.
|
|
303
|
+
> 4. **Show me the diff** - Display the raw upstream diff
|
|
304
|
+
> 5. **Combine them differently** - Tell me exactly what you want
|
|
405
305
|
|
|
406
306
|
#### For Removed Files
|
|
407
307
|
|
|
@@ -411,21 +311,10 @@ If `.generatesaas/template/<path>` does not exist (backward compat), fall back t
|
|
|
411
311
|
- If the user **modified** the old file: their customizations exist nowhere in the new version. Port them to the `to` path (show the proposed result) before deleting the old file. Never let a rename silently drop customizations.
|
|
412
312
|
- Imports of the old path elsewhere in the project must be updated to the new path - run the import search below for the old path either way.
|
|
413
313
|
|
|
414
|
-
Before
|
|
415
|
-
|
|
416
|
-
```
|
|
417
|
-
### `{file path}` - Removed Upstream
|
|
418
|
-
|
|
419
|
-
**Why it was removed:** {reason from changelog}
|
|
420
|
-
**Your modifications:** {describe if the user modified it, or "None - file is unmodified"}
|
|
421
|
-
**Files that import this:** {list ALL files found by searching, or "None found"}
|
|
314
|
+
Before deleting each removed file, **search the entire project** for imports of it. Use grep to find `import ... from` or `require(...)` statements referencing the file's path (check relative paths, aliases, and package paths). This is critical - the classification script only scans files in the update, not user-created files that may also depend on the removed file.
|
|
422
315
|
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
> 2. **Keep it** - I still use this file
|
|
426
|
-
```
|
|
427
|
-
|
|
428
|
-
If ANY files import the removed file, always warn before deletion and explain what would break.
|
|
316
|
+
- **No importers and the user never modified it:** delete it, and note it in the plan.
|
|
317
|
+
- **Any importer, or the user modified it:** this is a [mandatory stop](#mandatory-stops). Warn before deletion, list every importer, and let the user choose to delete or keep it.
|
|
429
318
|
|
|
430
319
|
#### For Deleted-by-User Files
|
|
431
320
|
|
|
@@ -433,7 +322,7 @@ Files the user intentionally deleted - skip silently. Just note in the plan: "Sk
|
|
|
433
322
|
|
|
434
323
|
#### For New Files In Deleted Trees (`newInDeletedTree`)
|
|
435
324
|
|
|
436
|
-
These are files the new version adds inside a directory the user previously deleted (e.g. a feature package they removed). Auto-creating them would silently resurrect the deleted tree. Group them by their deleted ancestor directory and ask once per tree:
|
|
325
|
+
These are files the new version adds inside a directory the user previously deleted (e.g. a feature package they removed). Auto-creating them would silently resurrect the deleted tree, so this is a [mandatory stop](#mandatory-stops). Group them by their deleted ancestor directory and ask once per tree:
|
|
437
326
|
|
|
438
327
|
```
|
|
439
328
|
### New upstream files under `{deleted dir}/` (which you removed)
|
|
@@ -450,7 +339,7 @@ Default to **keep deleted** unless the user says otherwise. If they keep it dele
|
|
|
450
339
|
|
|
451
340
|
#### After Each File
|
|
452
341
|
|
|
453
|
-
1. Apply the
|
|
342
|
+
1. Apply the chosen action immediately
|
|
454
343
|
2. Mark the item as `[x]` (completed) or move to **Skipped** with the reason
|
|
455
344
|
3. **Update the plan file** after every file so progress is saved
|
|
456
345
|
|
|
@@ -472,10 +361,7 @@ Similarly, if an auto-applied file changed its exports and a modified file that
|
|
|
472
361
|
|
|
473
362
|
### Step 8: Post-Update Validation
|
|
474
363
|
|
|
475
|
-
After all files are processed, run the validation ladder below - every rung. The static
|
|
476
|
-
rungs cannot see hook-level auth breakage, a missing static asset, or content wiring;
|
|
477
|
-
the e2e suite is the only gate that exercises sign-in, registration, payments and the
|
|
478
|
-
rendered pages. **Do not declare the update complete while any rung is red.**
|
|
364
|
+
After all files are processed, run the validation ladder below - every rung. The static rungs cannot see hook-level auth breakage, a missing static asset, or content wiring; the e2e suite is the only gate that exercises sign-in, registration, payments and the rendered pages. **Do not declare the update complete while any rung is red.** A verification failure you cannot fix with confidence is a [mandatory stop](#mandatory-stops).
|
|
479
365
|
|
|
480
366
|
1. **Static gates:**
|
|
481
367
|
- Scan merged files for syntax errors or broken imports
|
|
@@ -517,7 +403,7 @@ rendered pages. **Do not declare the update complete while any rung is red.**
|
|
|
517
403
|
>
|
|
518
404
|
> These appear to be caused by the update. Want me to fix them?
|
|
519
405
|
|
|
520
|
-
7. Fix any issues the user approves, then re-verify the affected rungs.
|
|
406
|
+
7. Fix any issues the user approves, then re-verify the affected rungs. If a failure resists a confident fix, stop and ask (a mandatory stop).
|
|
521
407
|
|
|
522
408
|
### Step 9: Complete Update
|
|
523
409
|
|
|
@@ -527,10 +413,7 @@ rendered pages. **Do not declare the update complete while any rung is red.**
|
|
|
527
413
|
- Modified files where the user chose "Keep my version"
|
|
528
414
|
- Modified files that were skipped for any reason (couldn't merge, user excluded, etc.)
|
|
529
415
|
- Auto-apply files that were reverted in the cascade awareness step
|
|
530
|
-
- Template test/spec files you adapted to the project's customizations during validation
|
|
531
|
-
(e.g. an e2e spec whose seeded-balance or gating assumption the project legitimately
|
|
532
|
-
breaks) - the adaptation is a kept-your-version outcome, and recording it keeps the
|
|
533
|
-
next update's diff honest
|
|
416
|
+
- Template test/spec files you adapted to the project's customizations during validation (e.g. an e2e spec whose seeded-balance or gating assumption the project legitimately breaks) - the adaptation is a kept-your-version outcome, and recording it keeps the next update's diff honest
|
|
534
417
|
|
|
535
418
|
**Do NOT include:**
|
|
536
419
|
- Files where the user accepted a merge or chose "Use upstream version" (template changes were applied)
|
|
@@ -544,12 +427,7 @@ rendered pages. **Do not declare the update complete while any rung is red.**
|
|
|
544
427
|
|
|
545
428
|
If no files were held back, skip creating this file.
|
|
546
429
|
|
|
547
|
-
> Note: the completion script runs a safety net that auto-holds-back upstream
|
|
548
|
-
> changes which were demonstrably never applied (the file was not touched during
|
|
549
|
-
> the entire update). Do NOT rely on it - it cannot detect a file you edited
|
|
550
|
-
> during a merge or that the user customized between updates - always write
|
|
551
|
-
> held-back.json yourself. Treat its warnings as a signal that your bookkeeping
|
|
552
|
-
> missed something.
|
|
430
|
+
> Note: the completion script runs a safety net that auto-holds-back upstream changes which were demonstrably never applied (the file was not touched during the entire update). Do NOT rely on it - it cannot detect a file you edited during a merge or that the user customized between updates - always write held-back.json yourself. Treat its warnings as a signal that your bookkeeping missed something.
|
|
553
431
|
|
|
554
432
|
2. **Run the completion script:**
|
|
555
433
|
|
|
@@ -559,48 +437,55 @@ node __SKILL_ROOT__/generatesaas-update/scripts/complete-update.js
|
|
|
559
437
|
|
|
560
438
|
This updates `.generatesaas/manifest.json` to the new version, regenerates file hashes, and cleans up staging.
|
|
561
439
|
|
|
562
|
-
3. **Present the final
|
|
440
|
+
3. **Present the final report:**
|
|
563
441
|
|
|
564
442
|
```markdown
|
|
565
443
|
## Result
|
|
566
444
|
|
|
567
445
|
- **Status:** Completed
|
|
568
446
|
- **Files auto-updated:** {count}
|
|
569
|
-
- **Files merged
|
|
447
|
+
- **Files merged:** {count}
|
|
570
448
|
- **New files created:** {count}
|
|
571
|
-
- **Changes
|
|
449
|
+
- **Changes held back:** {count}
|
|
572
450
|
- **Issues fixed:** {count or "None"}
|
|
573
451
|
|
|
574
452
|
### Post-update steps
|
|
575
453
|
- Run `pnpm install` if dependencies changed
|
|
576
454
|
- Run database migrations if schema was updated
|
|
455
|
+
- CI no longer runs on push: `ci.yml` now runs on pull requests and manual dispatch, so your pushes are quiet by design - run `pnpm preflight` locally and the full set from the Actions tab ("Run workflow")
|
|
577
456
|
- If your host auto-deploys on push, follow [Deploy Discipline](#deploy-discipline) below before pushing
|
|
578
457
|
- {any other steps from the changelog}
|
|
579
458
|
|
|
580
|
-
###
|
|
581
|
-
{For each
|
|
459
|
+
### Held back
|
|
460
|
+
{For each held-back item: what it was and why - so the user can revisit later}
|
|
582
461
|
```
|
|
583
462
|
|
|
584
463
|
---
|
|
585
464
|
|
|
465
|
+
## Mandatory stops
|
|
466
|
+
|
|
467
|
+
The update runs unattended, but it **always stops and asks** at any of these. This is the one rule; nothing below it is optional:
|
|
468
|
+
|
|
469
|
+
- **Database schema changes** - never auto-merge schema (see [Database](#database-schema-migrations)).
|
|
470
|
+
- **An env or config change that introduces a new required value** (a new required env var, a config key with no safe default).
|
|
471
|
+
- **Every new option** - never auto-adopt a feature (handled in [Step 2.5](#step-25-review-newly-available-options)).
|
|
472
|
+
- **A removed file that something still imports** - run the import search first (Step 7).
|
|
473
|
+
- **A `newInDeletedTree` file** - never resurrect a tree the user deleted (Step 7).
|
|
474
|
+
- **A merge you are not confident preserves the user's intent** - when unsure, ask. It is always better to interrupt than to assume.
|
|
475
|
+
- **A merge that changes application behaviour the user can observe** - a route, a default, a limit, a flow.
|
|
476
|
+
- **A merge that changes how a screen looks** - layout, copy the user customized, theme.
|
|
477
|
+
- **A verification failure you cannot fix with confidence** (Step 8).
|
|
478
|
+
|
|
479
|
+
For the two behaviour/appearance stops, show the two versions side by side and ask which to keep or how to combine them. Stopping is always safe - keep the user's version and record it in `held-back.json`.
|
|
480
|
+
|
|
586
481
|
## Deploy Discipline
|
|
587
482
|
|
|
588
|
-
An update usually ends with a push, and many hosts (Dokploy, Coolify, Vercel, Railway)
|
|
589
|
-
|
|
590
|
-
the
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
into a production incident.
|
|
595
|
-
2. **After pushing, watch the CI run to its conclusion.** A red run on a commit that
|
|
596
|
-
already deployed is an incident to act on now, not a follow-up for later.
|
|
597
|
-
3. **If a push webhook deploys the project, never trigger a manual deployment alongside
|
|
598
|
-
it.** Two racing deploys can fail with "service already exists" (HTTP 409) and leave
|
|
599
|
-
the service half-recreated. Trigger manually only when the deploy queue has been
|
|
600
|
-
empty for several minutes.
|
|
601
|
-
4. The structural fix is to deploy from a CI job that runs **after** the test jobs
|
|
602
|
-
succeed, instead of from the push webhook - then a red gate can never reach
|
|
603
|
-
production. See the deployment docs' going-to-production checklist.
|
|
483
|
+
An update usually ends with a push, and many hosts (Dokploy, Coolify, Vercel, Railway) auto-deploy that push. The update is not "done locally" on such a project - the push IS the deploy. Rules:
|
|
484
|
+
|
|
485
|
+
1. **Never push a branch that auto-deploys until the full Step 8 ladder - the e2e gate included - is green locally.** Pushing first and validating after turns a red gate into a production incident.
|
|
486
|
+
2. **Validate before the push, not after.** `ci.yml` no longer runs on push - it runs on pull requests and manual dispatch - so the push that deploys triggers no gate. Run `pnpm preflight` locally (or a green Actions dispatch) before pushing; a red gate found after a commit already deployed is an incident to act on now.
|
|
487
|
+
3. **If a push webhook deploys the project, never trigger a manual deployment alongside it.** Two racing deploys can fail with "service already exists" (HTTP 409) and leave the service half-recreated. Trigger manually only when the deploy queue has been empty for several minutes.
|
|
488
|
+
4. The structural fix is to deploy from a CI job that runs **after** the test jobs succeed, instead of from the push webhook - then a red gate can never reach production. See the deployment docs' going-to-production checklist.
|
|
604
489
|
|
|
605
490
|
## Merge Strategies
|
|
606
491
|
|
|
@@ -614,25 +499,25 @@ Config files are the most commonly customized.
|
|
|
614
499
|
- Add new config keys with their default values
|
|
615
500
|
- If a key was renamed upstream, migrate the user's value to the new key name
|
|
616
501
|
- Keep user's formatting preferences if they differ
|
|
617
|
-
-
|
|
502
|
+
- A config change that alters a default the app runs on is a [mandatory stop](#mandatory-stops)
|
|
618
503
|
|
|
619
504
|
### Components (`.vue`, `.tsx`)
|
|
620
505
|
|
|
621
506
|
- Preserve user-added props, slots, event handlers, and custom logic
|
|
622
507
|
- Apply upstream structural changes (new elements, accessibility improvements, bug fixes)
|
|
623
508
|
- Keep user's custom CSS classes and styles
|
|
624
|
-
-
|
|
509
|
+
- A change to layout, customized copy, or theme is a [mandatory stop](#mandatory-stops): present both versions side by side and let the user decide
|
|
625
510
|
|
|
626
511
|
### API Routes (`routes/*.ts`)
|
|
627
512
|
|
|
628
513
|
- Preserve user-added endpoints and middleware
|
|
629
514
|
- Apply upstream bug fixes and security patches to existing endpoints
|
|
630
515
|
- Keep user-added business logic intact
|
|
631
|
-
- Watch for new imports or dependency changes
|
|
516
|
+
- Watch for new imports or dependency changes; a changed route, default, or limit is a [mandatory stop](#mandatory-stops)
|
|
632
517
|
|
|
633
518
|
### Database (schema, migrations)
|
|
634
519
|
|
|
635
|
-
- NEVER auto-merge schema files - always
|
|
520
|
+
- NEVER auto-merge schema files - always a [mandatory stop](#mandatory-stops)
|
|
636
521
|
- Warn about schema changes that may require new migrations
|
|
637
522
|
|
|
638
523
|
**Never copy an upstream migration into `packages/database/drizzle/` as-is, and never overwrite the project's `drizzle/meta/_journal.json` or `drizzle/meta/*_snapshot.json` with the upstream versions.** A project's migration history is its own: upstream changes get re-derived into it, never pasted over it. Regenerate instead:
|
|
@@ -675,6 +560,7 @@ Whichever path applies, `db:deploy` re-reads the live schema afterwards and fail
|
|
|
675
560
|
|
|
676
561
|
- Add new environment variables with their example values and comments
|
|
677
562
|
- Preserve user-added variables
|
|
563
|
+
- A new **required** variable is a [mandatory stop](#mandatory-stops) - the app will not boot without it
|
|
678
564
|
- Never touch actual `.env` files
|
|
679
565
|
|
|
680
566
|
## When to Skip
|
|
@@ -691,14 +577,3 @@ When skipping, always explain:
|
|
|
691
577
|
1. What the upstream change was trying to do
|
|
692
578
|
2. Why it was skipped
|
|
693
579
|
3. Whether the user should revisit it later
|
|
694
|
-
|
|
695
|
-
## When to Always Ask
|
|
696
|
-
|
|
697
|
-
Even in Quick or Automatic mode, always ask the user about:
|
|
698
|
-
|
|
699
|
-
- Database schema changes
|
|
700
|
-
- Files where user modifications are extensive (>30% of the file differs from template)
|
|
701
|
-
- Changes where upstream and user modifications touch the same code sections
|
|
702
|
-
- Removed files that other code depends on
|
|
703
|
-
- Config changes where user's value format conflicts with new requirements
|
|
704
|
-
- Any change where you're unsure about the right action
|