@kitschpatrol/shared-config 8.12.1 → 8.13.1

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.
@@ -1,300 +1,255 @@
1
1
  ---
2
2
  name: ksc-update
3
3
  description: >-
4
- Update dependencies in kitschpatrol shared config pnpm repositories and
5
- monorepos with compatible changes, explicitly approved breaking changes, or
6
- breaking changes for zero-versioned projects. Use when asked to update,
7
- upgrade, refresh, or audit repository dependencies or GitHub Actions. Applies
8
- a 24-hour release maturity policy with exceptions for kitschpatrol's packages,
9
- reviews fresh-install consumer compatibility, validates known consumers,
10
- minimizes configuration overrides, and recommends a release level.
11
- Does not commit or release.
12
- compatibility: Requires Node.js, pnpm/pnpx, curl, jq, git, Bash, and access to npm, GitHub, and upstream release documentation.
4
+ Run full dependency and repository maintenance in kitschpatrol shared config
5
+ pnpm repositories and monorepos. Use when asked to update, upgrade, refresh,
6
+ or audit dependencies or GitHub Actions. Includes compatibility review,
7
+ migrations, configuration and documentation cleanup, packed-install
8
+ validation, and a release recommendation. Does not commit or release.
9
+ license: MIT
13
10
  ---
14
11
 
15
12
  # Update dependencies
16
13
 
17
- Accept dependency and GitHub Actions updates under the version policy below.
18
- For projects at 1.0.0 or later, preserve existing contracts: public APIs, CLI
19
- behavior, outputs, defaults, supported consumer environments, and peer
20
- compatibility, unless the user explicitly approves a reviewed breaking change.
21
- Make the migrations accepted updates require. Do not commit, push, tag, publish,
22
- or release.
23
-
24
- ## Execution mode
25
-
26
- Determine the mode before Setup and record it with the reason. Use unattended
27
- mode when explicitly requested, when `GITHUB_ACTIONS=true` or `CI=true`, or when
28
- the host cannot receive user replies. Otherwise use interactive mode; a missing
29
- TTY alone does not establish that an agent session is unattended.
30
-
31
- In unattended mode, never ask questions, wait for answers, or invoke a command
32
- that requires an interactive response. Existing explicit approvals still apply;
33
- silence and CI execution do not grant new approval. This mode overrides every
34
- instruction below to ask, confirm, or await a decision:
35
-
36
- - **Projects at 1.0.0 or later:** apply compatible changes and any reviewed
37
- breaks already explicitly authorized. Defer other breaking candidates and
38
- report them for a later decision. Judge consumer impact, not dependency
39
- version labels; a compatible dependency major remains eligible.
40
- - **Zero-versioned projects:** retain the existing `0.x` allowance in unattended
41
- runs. Apply reviewed breaking changes, complete their migrations, validate
42
- the new contracts, and normally recommend a minor release. Do not defer them
43
- merely because no person is present to approve the break. Other requirements,
44
- including explicit approval for runtime-range restrictions and Node-types
45
- changes, still apply.
46
- - **Other decisions and missing prerequisites:** without prior authorization,
47
- leave approval-dependent changes unapplied, including range restrictions.
48
- Scoped peer-warning suppressions with verified compatibility (step 5) are not
49
- approval-dependent: apply them and report them. Report missing consumer
50
- information, credentials, permissions, or validation resources instead of
51
- requesting them. Continue independent work; if a required prerequisite
52
- prevents progress, report the affected work as blocked or incomplete without
53
- waiting or bypassing it.
54
-
55
- Review and validation remain required in both modes. Defer candidates whose
56
- impact cannot be established or whose migration cannot be validated. If safe
57
- updates cannot be isolated without an unapproved change, leave those updates
58
- unapplied and explain the blocker. Report incompatible releases already allowed
59
- by published runtime ranges as existing consumer exposure; an older lockfile
60
- does not resolve that exposure.
61
-
62
- Produce changes and a report suitable for later PR automation. This skill does
63
- not create workflows or pull requests, or split work into multiple PRs. If
64
- nothing can be applied, produce the report without manufacturing a change.
65
-
66
- ## Policy
67
-
68
- - **Compatible by default at 1.0.0 or later:** assess the effect on this repository
69
- and its consumers, not just the dependency's version label. Minor and patch
70
- updates can break compatibility; a dependency major can still be compatible.
71
- Present useful breaking candidates with their impact, migration, validation,
72
- and release implications before asking for approval; apply only within the
73
- approved scope. Existing explicit approval remains valid. Defer unapproved
74
- breaks and updates whose impact cannot be established. This includes authored
75
- packages, production transitives, and workflow actions.
76
- - **Zero-versioned projects:** if the project's current release version has
77
- major version zero (`0.x.y`), any breaking change within this update workflow
78
- is permitted in both interactive and unattended modes, including changes to
79
- public contracts and consumer Node.js requirements. This exception overrides
80
- compatibility-preservation requirements below. Use the project's version, not
81
- the dependency's version; in monorepos,
82
- assess each affected published package or shared release version, not just a
83
- private workspace root. Review and report breaking changes, make required
84
- migrations, and validate the resulting behavior. All other policies still
85
- apply.
86
- - **Release maturity:** third-party releases must be at least 24 hours old
87
- (`--maturity-period 1` for Taze, `--min-age 1` for Actions Up, pnpm
88
- `minimumReleaseAge` of 1440 minutes). The period governs which releases a run
89
- may introduce; it never requires downgrading a version that was locked before
90
- the run. Never disable installation safeguards to make an update succeed.
91
- - **Authored packages:** packages owned by `kitschpatrol` (discovered at runtime
92
- in Setup) are exempt from maturity and target their latest stable release,
93
- including majors. pnpm enforces `minimumReleaseAge` silently by selecting the
94
- newest mature version, so the exemption is only real while a
95
- `minimumReleaseAgeExclude` entry for the young release exists: add it when
96
- needed (step 5) and keep it through cleanup (step 6). The maturity period
97
- must never hold an authored package back or downgrade it. The exemption does
98
- not bypass security or compatibility review.
99
- - **Consumer ranges:** review the newest published version allowed by each
100
- runtime dependency's declared range, as well as the lockfile. A fresh consumer
101
- install can resolve that version even when CI locks an older one. Holding
102
- back an in-range release requires a genuinely restrictive published range
103
- (for example, `~1.8.0` instead of `^1.8.0` to exclude `1.9.0`), not just an
104
- older lockfile entry. Obtain explicit approval before narrowing a runtime
105
- range to hold a release back, even for a zero-versioned project; explain the
106
- consumer effect. Do not use local overrides as a substitute for that decision.
107
- - **TypeScript:** select a compiler within the peer range of the accepted
108
- `@kitschpatrol/typescript-config` version, intersected with other required
109
- peers. Do not hard-code a compiler version. Offer the migration when an
110
- authored major requires a newer compiler; see step 3. If that config is not
111
- used, follow the project's compiler policy and peer requirements.
112
- - **Node types:** preserve `@types/node` declarations, including catalogs and
113
- overrides, unless a reviewed migration has explicit authorization to change
114
- them. New compiler libraries do not establish runtime API availability.
115
- - **Package manager:** only Setup manages `packageManager`. Exclude `pnpm`
116
- from Taze discovery and writes.
117
- - **No weakening:** do not relax tests, lint rules, type checking, or security
118
- settings to get a pass; do not blindly accept changed snapshots or generated
119
- output. Compatibility-preserving lint disables described in step 5 are an
120
- exception.
121
- - **No new noise:** every check is compared against the Setup baseline. A new
122
- warning, deprecation, or peer issue is a finding to trace and report, not
123
- background noise. Report compatibility-preserving lint disables and scoped
124
- peer-warning entries from step 5; ask before silencing other findings.
14
+ Every invocation is a full maintenance run, including audits and requests that
15
+ mention only GitHub Actions; there is no report-only or Actions-only mode. The
16
+ caller's only decision is whether consumer-breaking changes are pre-approved for
17
+ packages at 1.0.0 or later. Make the migrations that accepted updates require.
18
+
19
+ Supporting files sit beside this file. [configuration.md](references/configuration.md)
20
+ owns every per-file rule; read it during Setup and apply it through the final
21
+ cleanup. [verification.md](references/verification.md) owns baselines,
22
+ validation procedures, and the bundled scripts.
23
+
24
+ ## Execution and authorization
25
+
26
+ Record the execution mode and its reason before Setup. Use unattended mode when
27
+ explicitly requested, when `GITHUB_ACTIONS=true` or `CI=true`, or when the host
28
+ cannot receive replies; a missing TTY alone does not establish it. Unattended
29
+ runs never ask, wait, or run a command that needs an interactive response, and
30
+ report needed decisions as follow-up items.
31
+
32
+ Judge compatibility by effect on public APIs, CLI behavior, outputs, defaults,
33
+ supported consumer environments, and peers, never by a dependency's version
34
+ label: minors and patches can break those contracts and majors can preserve
35
+ them. This applies to authored packages, production transitives, and actions
36
+ alike. A package is `0.x` by its own published version, or the shared release
37
+ version in a monorepo, never a private root's version.
38
+
39
+ | Change | Rule |
40
+ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------- |
41
+ | Compatible update | Apply after review and validation. |
42
+ | Consumer break in a package at 1.0.0 or later | Apply only within existing explicit approval. |
43
+ | Consumer break in a `0.x` package, including Node.js support changes | Apply after review, migration, and validation. |
44
+ | Pre-authorized by the configuration policy: Homebrew pnpm alignment, LTS-only Node.js ranges, Node-types alignment, compatibility-preserving lint disables, scoped suppression of a verified-compatible peer warning | Apply and report. |
45
+ | Other restrictions and suppressions: a published runtime-range restriction to hold a release back, including in `0.x`; a build approval outside the trust list; any other warning suppression | Apply only within existing explicit approval. |
46
+
47
+ Where approval is missing, present the reviewed proposal and ask in interactive
48
+ mode; defer in unattended mode. General permission to update dependencies never
49
+ approves an unspecified break. For each approval-dependent candidate record
50
+ concrete effects, migration work, validation results or gaps, and release
51
+ implications, trialing an isolated migration when useful. Continue independent
52
+ work while a decision is pending; track accepted, declined, pending, and
53
+ deferred decisions separately. Defer candidates with unknown impact or
54
+ unvalidated migrations, and leave acceptable updates unapplied when they cannot
55
+ be separated from an unauthorized change. Report missing credentials,
56
+ permissions, and validation resources instead of bypassing them.
57
+
58
+ Produce working-tree changes and a report suitable for later PR automation even
59
+ when nothing can be applied. Do not manufacture changes, create workflows or
60
+ pull requests, split work into PRs, bump repository versions, commit, push, tag,
61
+ publish, or release.
62
+
63
+ ### Pacing
64
+
65
+ Unattended runs have a turn limit, and a run that stops early publishes nothing.
66
+ Finish Setup and steps 1 to 5 before steps 6 to 9 and the fresh-install
67
+ exposure checks, and reserve budget for the report. Delegate per-package reviews
68
+ when subagents are available. If budget runs short, skip the remaining optional
69
+ work, list it in the report as not done, and write the report.
70
+
71
+ ## Version policy
72
+
73
+ - **Third-party maturity:** a run introduces only releases at least 24 hours
74
+ old: Taze `--maturity-period 1` and Actions Up `--min-age 1` enforce it for
75
+ candidates, and pnpm's default `minimumReleaseAge` of 1440 minutes covers
76
+ resolution. Do not add or change `minimumReleaseAge` in `pnpm-workspace.yaml`,
77
+ never disable an installation safeguard, and never downgrade a previously
78
+ locked version to satisfy age.
79
+ - **Authored packages:** npm packages and GitHub Actions owned by `kitschpatrol`
80
+ always target their latest stable release, including majors, however young.
81
+ They still get security and compatibility review and required migrations, but
82
+ age alone never causes an older target, a deferral, or a downgrade. The
83
+ commands below and the configuration policy's exact-version rules make the
84
+ exemption effective in Taze, pnpm, and Actions Up. If another policy blocks
85
+ latest, report the blocker and the retained version.
86
+ - **Consumer ranges:** review the newest stable version allowed by each runtime
87
+ dependency's declared range, not only the locked version; consumers resolve
88
+ it regardless of this repository's lockfile and maturity settings. Holding one
89
+ back needs an approved, genuinely restrictive published range such as `~1.8.0`
90
+ instead of `^1.8.0`; an older lockfile or a local override is no substitute.
91
+ - **No weakening:** never relax tests, lint rules, type checking, or security to
92
+ get a pass, and never accept changed snapshots or generated output unread.
93
+ Trace and report every new warning, deprecation, and peer issue against the
94
+ recorded baseline; the configuration policy defines the only permitted
95
+ suppressions.
125
96
 
126
97
  ## Environment
127
98
 
128
- Shell variables do not persist between commands. Save anything later steps need
129
- under `node_modules/.cache/ksc-update/` and pass values literally.
130
-
131
- Plan network access for `registry.npmjs.org`, `raw.githubusercontent.com`,
132
- `api.github.com`, and `nodejs.org`; identify any additional upstream hosts as
133
- needed. Prefer registry metadata and raw changelog files over GitHub API calls
134
- for package reviews. Cache responses and share them between reviewers.
135
-
136
- Under Claude Code's sandbox:
137
-
138
- - **pnpm store:** pnpm 12 cannot take its store lock inside the sandbox
139
- (`ERR_PNPM_STORE_DIR_OPEN_OPERATION_LOCK`), even with writable store, cache,
140
- and temp directories. `pnpm install`, `pnpm update`, `pnpm dedupe`,
141
- `pnpx taze`, and `pnpx actions-up` must be listed in the user's
142
- `sandbox.excludedCommands` and `permissions.allow`. If the Setup install fails
143
- this way, stop the affected work and ask the user to add them in interactive
144
- mode; in unattended mode, report the missing prerequisite. Do not route around
145
- it. Run these commands bare (no pipes, redirects, or command substitution) so the
146
- exclusions match. Run each as its own invocation, without `&&` or `||`.
147
- Save captured tool output to log files in a separate operation.
148
- - **Proxy:** Node-based tools ignore the proxy variables. If one fails with
149
- `ENOTFOUND`, rerun it with `NODE_USE_ENV_PROXY=1`.
150
- - **Sockets:** the `tsx` CLI cannot open its IPC socket. Run the same script
151
- with `node --import tsx <script>` and report the substitution.
152
- - **GitHub API:** without `GITHUB_TOKEN`, GitHub allows 60 requests per hour.
153
- One Actions Up run plus a few release-note lookups can exhaust it. The sandbox
154
- cannot read `gh` credentials, so budget lookups or ask for a token in
155
- interactive mode. In unattended mode, report any review blocked by missing
156
- credentials or exhausted API limits.
157
- - **JSON output:** pnpm can emit `[WARN]` lines on stdout. Sync `packageManager`
158
- before parsing pnpm JSON; if warnings remain, save them separately, remove
159
- only lines beginning with `[WARN]`, and parse the rest strictly. Do not hide
160
- malformed output or other diagnostics.
161
- - **Supply-chain settings:** an unreadable global config or `~/.npmrc` can make
162
- a sandboxed config query return `undefined`; this does not mean the policy is
163
- disabled. Read accessible workspace settings and record pnpm's successful
164
- `Lockfile passes supply-chain policies` message from the actual install.
165
- That message confirms the active checks passed, not the numeric release-age
166
- threshold. Verify the required 1440 minutes from accessible configuration or
167
- release timestamps when the effective setting cannot be read. Do not disable
168
- safeguards or access private config through a workaround.
169
-
170
- ## Setup
171
-
172
- 1. Read repository instructions. Note uncommitted changes in the working tree
173
- and preserve them. If files change during the run that you did not touch,
174
- leave them alone and report them.
175
- Read the `Known consumers` section in the project's `CLAUDE.md` or `AGENTS.md`.
176
- Maintain a short section in the existing instruction file using confirmed
177
- consumer names, local paths, consumed packages, test commands, and CLI
178
- fixtures. If none are documented, ask for known consumers in interactive
179
- mode; in unattended mode, report the missing information and use available
180
- repository evidence. Continue independent review; do not invent consumers or
181
- treat example paths as real. Report unavailable consumer validation as a gap.
182
- 2. Map the workspace: root, every maintained package root, catalogs, overrides,
183
- `pnpm-workspace.yaml`, Taze config. Exclude fixtures, generated files, and
184
- dependency directories. Run each step once per shared-lockfile workspace and
185
- separately in any independent package root. Check Taze config for anything
186
- that overrides mode, adds maturity exemptions, or auto-writes/installs.
187
- Record current project and published package versions to determine where the
188
- zero-versioned exception applies. Record every existing
189
- `minimumReleaseAgeExclude` entry with the publish time of that exact version
190
- (`time` in the registry metadata), so step 6 can tell which entries still
191
- matter.
192
- Create the baseline folder and preserve the starting manifests and lockfile
193
- before the package-manager sync or any other edit.
194
- 3. Sync `packageManager` before installs and parsed pnpm output. Choose the
195
- newest of three versions, so the pin only ever moves up:
196
-
197
- - the current `packageManager` pin;
198
- - the pnpm installed on this host, read from a new empty directory under
199
- `${TMPDIR:-/tmp}` so the project's stale pin cannot select or download
200
- another version:
201
-
202
- ```bash
203
- pnpm --version
204
- ```
205
-
206
- - the newest stable pnpm release at least 24 hours old, from `versions` and
207
- `time` in `https://registry.npmjs.org/pnpm` (`dist-tags.latest` when it
208
- qualifies).
209
-
210
- A CI runner usually installs the pinned version itself, so the installed
211
- pnpm alone never moves the pin; the registry lookup is what keeps it
212
- current. Then edit only the workspace root's `packageManager` directly to
213
- `pnpm@<chosen-version>`, preserving all other manifest fields. Use the
214
- editor or a structured JSON edit, not `pnpm pkg set`; use direct edits for
215
- later specifiers and engines too. pnpm downloads and runs the pinned
216
- version on demand after the pin changes. If this crosses a pnpm major,
217
- report it, review the pnpm release notes for lockfile and settings changes,
218
- and verify the CI installer supports the selected version.
219
-
220
- 4. Install the starting dependency declarations and record a baseline before
221
- dependency updates. Keep the original files saved in Setup 2 even if
222
- installation fails.
99
+ Expect Claude Code in GitHub Actions with Node.js, pnpm and pnpx, curl, jq, git,
100
+ Bash, and network access to `registry.npmjs.org`, `raw.githubusercontent.com`,
101
+ `api.github.com`, `nodejs.org`, and upstream documentation hosts. Prefer
102
+ registry metadata and raw changelogs over GitHub API calls, and cache responses
103
+ for reuse between reviewers. Diagnose actual failures rather than assuming
104
+ sandbox restrictions, and never add sandbox workarounds.
223
105
 
224
- ```bash
225
- pnpm install --frozen-lockfile
226
- ```
106
+ Before saving any starting files, create a fresh run directory once per run:
227
107
 
228
- On `ERR_PNPM_OUTDATED_LOCKFILE` only, run this as a separate bare command:
108
+ ```bash
109
+ set -euo pipefail
110
+ repo_name="$(basename "$(git rev-parse --show-toplevel)")"
111
+ run_dir="$(mktemp -d "${RUNNER_TEMP:-${TMPDIR:-/tmp}}/ksc-update-${repo_name}.XXXXXX")"
112
+ export KSC_UPDATE_RUN_DIR="$run_dir"
113
+ ```
114
+
115
+ The repository name identifies the run; the random suffix prevents collisions
116
+ between concurrent runs, including separate checkouts of the same repository.
117
+ Record the absolute path and reuse it for every command and reviewer in this
118
+ run. In later shells, restore `KSC_UPDATE_RUN_DIR` and `run_dir` to that recorded
119
+ path rather than rerunning initialization. Bundled scripts require
120
+ `KSC_UPDATE_RUN_DIR`; never use a shared fixed directory or overwrite another
121
+ run's saved files.
122
+
123
+ Keep every baseline, log, fetched metadata file, and decision record there; it survives
124
+ pnpm rebuilding `node_modules` and never enters the pull request. Preserve exit
125
+ codes when capturing logs, for example with `set -o pipefail` before
126
+ `cmd 2>&1 | tee log`.
127
+
128
+ ### Bundled scripts
129
+
130
+ `scripts/` holds helpers for the mechanical parts of a run. Each documents its
131
+ usage in a header comment; the references say where each fits.
132
+
133
+ | Script | Purpose |
134
+ | ------------------------ | ------------------------------------------------------------- |
135
+ | `consumer-ranges.mjs` | Newest version each published runtime range allows (step 3) |
136
+ | `release-age.mjs` | Exemption inventory and young-version detection (steps 0–6) |
137
+ | `production-engines.mjs` | Declared engines across a production tree |
138
+ | `packed-fixture.mjs` | Packed or published consumer fixture install |
139
+ | `run-at-node.mjs` | Command at an exact Node.js release, with child-process proof |
140
+ | `compare-outputs.mjs` | Normalized comparison of captured outputs and build trees |
141
+
142
+ The scripts are conveniences, not requirements; the procedures they serve are.
143
+ When one fails for a reason that is not the repository's fault, produces output
144
+ that disagrees with what direct inspection shows, or does not fit this
145
+ repository's layout, make at most one quick attempt to understand why, then
146
+ abandon it: write a replacement for that step in the run directory, or do the
147
+ step by hand, and continue. Never let a broken helper stall the run, never edit
148
+ the bundled copy during a run (it is synced from the published package and
149
+ overwritten), and never weaken a check to make a script pass. Name each
150
+ abandoned or replaced script and the reason in the report's gaps so it can be
151
+ fixed upstream. Verify any script's result against one or two direct
152
+ observations before relying on it.
153
+
154
+ ## Step 0: Setup
155
+
156
+ 1. Read repository instructions, including run-specific instructions, and
157
+ preserve uncommitted changes. Run-specific instructions also live in the
158
+ `instructions:` input of the skill-running step in
159
+ `.github/workflows/update-dependencies.yml`; read it even when running
160
+ locally, where the workflow does not pass it, and follow it as if it had
161
+ been. Leave files changed by others during the run alone and report them.
162
+ Keep compatibility validation inside this repository and isolated
163
+ package-install fixtures. Record the latest release tag and the commits
164
+ since it (`git describe --tags --abbrev=0`, then `git log <tag>..HEAD`);
165
+ they explain differences between the published release and the current
166
+ build and feed the release recommendation.
167
+ 2. Map maintained package roots, shared lockfiles, catalogs, overrides,
168
+ `pnpm-workspace.yaml`, and Taze config, excluding fixtures, generated files,
169
+ and dependency directories. Run the workflow once per shared-lockfile
170
+ workspace and separately for each independent root. Check Taze config for
171
+ mode overrides, maturity exemptions, and automatic writes or installs; Taze
172
+ and `pnpm update` also read `minimumReleaseAge`, `minimumReleaseAgeExclude`,
173
+ and `update.ignoreDeps` from `pnpm-workspace.yaml`. Record project and
174
+ published package versions. Before any edit, copy the starting manifests,
175
+ lockfile, build approvals, and exact `publicHoistPattern` into the run
176
+ directory, and inventory release-age exclusions as the configuration policy
177
+ describes; `scripts/release-age.mjs inventory` classifies each entry once
178
+ the authored list from item 5 exists.
179
+ 3. Sync the workspace root's `packageManager` before any install or parsed pnpm
180
+ output: fetch the [Homebrew pnpm formula](https://raw.githubusercontent.com/Homebrew/homebrew-core/refs/heads/main/Formula/p/pnpm.rb),
181
+ read the stable version from its source URL or explicit `version`, and set
182
+ `pnpm@<homebrew-version>` by direct manifest edit, even across a major.
183
+ Homebrew is the only source and need not be installed; never substitute the
184
+ installed pnpm, npm's `latest` tag, or an age-filtered version, and report an
185
+ unavailable or unreadable formula as an incomplete sync. Review pnpm release
186
+ notes for lockfile and settings changes, confirm CI installs the selected
187
+ version, and record the formula URL and version. Make all later specifier
188
+ and engine changes by direct edit too, preserving other fields.
189
+ 4. Apply the configuration policy's build-trust decisions and exclusion
190
+ normalization, then install the starting declarations:
229
191
 
230
192
  ```bash
231
- pnpm install --no-frozen-lockfile
193
+ pnpm install --frozen-lockfile
232
194
  ```
233
195
 
234
- Save the lockfile diff against the starting copy in the baseline folder and
235
- report the drift. Treat checks after repair as the repaired baseline, not as
236
- proof that the original locked tree passed. Other installation failures need
237
- their own diagnosis; do not generalize this fallback or relax safeguards.
238
-
239
- Save the output of each install attempt and of `pnpm build`, `pnpm test`, and
240
- `pnpm lint` to `node_modules/.cache/ksc-update/baseline/`. If the repository
241
- produces build output (`dist/` or similar), copy it there as well. Use the
242
- repository's switches to disable nondeterministic build steps (encryption,
243
- timestamps) and note the exact command and environment; later comparison
244
- builds must match them. Baseline failures are pre-existing; record them.
245
-
246
- Record each published package's declared `engines.node`, effective consumer
247
- Node.js minimum and supported range, and separate development requirement.
248
- Include published dependency trees and built artifacts, not just the root
249
- manifest or current CI runtime. If no Node.js support policy is declared,
250
- establish the existing requirement from the published code and dependencies;
251
- do not assume the developer's Node.js version is the consumer minimum.
252
- Save production-tree engine inventories and baseline consumer results using
253
- [the verification recipes](references/verification.md). Distinguish the
254
- starting locked tree, the newest versions a fresh consumer install can
255
- resolve, and the published release with its old dependencies when available.
256
-
257
- 5. Discover authored packages:
196
+ Use `--no-frozen-lockfile` only for `ERR_PNPM_OUTDATED_LOCKFILE` and diagnose
197
+ every other failure individually; a pnpm major change can require a lockfile
198
+ format migration, which is expected drift to record. Keep the saved originals
199
+ even if installation fails, and label checks after a repair as repaired.
200
+ Record the [baseline](references/verification.md#baselines): install
201
+ attempts, build, test, lint, build artifacts, Node.js requirements, the
202
+ production-engine inventory, the advisory report, and packed-install fixture
203
+ results.
204
+
205
+ 5. Discover authored packages, those whose registry metadata lists
206
+ `kitschpatrol` in `maintainers`. The ownership endpoint is a shortcut for the
207
+ full list:
258
208
 
259
209
  ```bash
260
210
  set -euo pipefail
261
- mkdir -p node_modules/.cache/ksc-update
211
+ run_dir="${KSC_UPDATE_RUN_DIR:?Restore the recorded run directory first}"
262
212
  curl -fsS https://registry.npmjs.org/-/user/kitschpatrol/package \
263
213
  | jq -er 'keys | join(",") | select(length > 0)' \
264
- > node_modules/.cache/ksc-update/authored-packages.txt
214
+ > "$run_dir/authored-packages.txt"
265
215
  ```
266
216
 
267
- If registry discovery fails or returns empty, stop and report. Intersect the
268
- result with direct dependency names across the maintained manifests in this
269
- workspace, including dev, optional, and peer dependencies and dependencies
270
- using catalogs or npm aliases. Save the intersection separately; an empty
271
- intersection is valid. `<authored-packages>` below means only those exact
272
- matching names, comma-separated and passed literally, with no wildcards.
273
- Omit `--maturity-period-exclude` if the intersection is empty. Keep the full
274
- ownership list only for evaluating other packages encountered later.
217
+ If it fails or returns nothing, check each direct dependency's registry
218
+ metadata instead and report the fallback; do not stop the run. Intersect
219
+ ownership with the direct dependency names across maintained manifests,
220
+ including dev, optional, peer, catalog, and npm-alias dependencies, and save
221
+ that intersection separately; it may be empty. `<authored-packages>` below
222
+ means those exact names, comma-separated, with no wildcards; omit
223
+ `--maturity-period-exclude` when the list is empty. Keep the full ownership
224
+ list for packages met later.
275
225
 
276
- ## 1. Workflow actions
226
+ ## Step 1: Workflow actions
277
227
 
278
228
  ```bash
279
- pnpx actions-up --yes --min-age 1 --style sha
229
+ pnpx actions-up --yes --min-age 1 --min-age-exclude '^kitschpatrol/' --style sha \
230
+ --dir .github
280
231
  ```
281
232
 
282
- Read the whole output. Actions Up can print "All actions are up to date!" after
283
- checks failed; any `Skipped`, `Failed`, or `Rate Limit` line means the run is
284
- incomplete. Fix the cause and rerun.
233
+ Add a `--dir` for every other directory of workflows the repository maintains or
234
+ ships, such as templates that an init command copies into consumer projects
235
+ (for example `packages/*/init/.github`); by default only `.github` is scanned.
236
+ Find them with a search for `workflows` directories outside dependency and
237
+ fixture folders.
238
+
239
+ Treat `Skipped N actions` as a failure even when Actions Up also says "All
240
+ actions are up to date" or exits successfully. Any `Skipped`, `Failed`, or
241
+ `Rate Limit` output means the workflow-action check failed; fix the cause and
242
+ rerun, and report unresolved failures instead of claiming success.
285
243
 
286
- Review the diff: major action bumps, runner, input, output, and permission
287
- changes. Every external GitHub Action and reusable workflow must be pinned to
288
- its full commit SHA, including `kitschpatrol/*`; retain version comments for
289
- readability. Do not exclude first-party actions from pinning or allow their
290
- floating refs in zizmor's `unpinned-uses` policy. Resolve skipped branch/tag
291
- refs and unchanged versions to verified commits too; if an update is deferred,
292
- pin the retained version. Check existing zizmor configuration for exceptions
293
- that contradict this policy. Pin container actions by digest; local `./` actions
294
- use the checked-out tree. Keep only reviewed changes without disturbing user
295
- edits. Local tests say nothing about remote workflows.
244
+ Review major bumps and runner, input, output, and permission changes. Pin every
245
+ external action and reusable workflow, including `kitschpatrol/*`, to a verified
246
+ full commit SHA with its version comment, covering branch and tag refs,
247
+ unchanged versions, and the retained version of a deferred update. Pin container
248
+ actions by digest; local `./` actions use the checkout. Remove zizmor
249
+ `unpinned-uses` exceptions the pins make contradictory. Keep only reviewed
250
+ changes and preserve user edits; local tests do not validate remote workflows.
296
251
 
297
- ## 2. Discover all candidates (read-only)
252
+ ## Step 2: Discover candidates
298
253
 
299
254
  ```bash
300
255
  pnpx taze major -r --force --include-locked \
@@ -304,134 +259,88 @@ pnpx taze major -r --force --include-locked \
304
259
  --maturity-period-exclude '<authored-packages>'
305
260
  ```
306
261
 
307
- Major mode lists every available update, minor and major. Confirm authored
308
- packages are offered their latest stable release, not the latest within their
309
- current major. Do not opt into new prerelease channels. Taze's newest candidate
310
- does not replace the separate newest-in-range runtime review in step 3.
311
-
312
- ## 3. Evaluate candidates
313
-
314
- ### Runtime ranges and review scope
315
-
316
- For each runtime dependency of a published package, inspect registry metadata
317
- for the newest stable version satisfying its current declared range, accounting
318
- for catalogs and aliases. Record declared range, locked version, newest allowed
319
- version, and proposed range/version. Review that newest allowed release even
320
- if it is already in range or too young for this run to install; consumer
321
- package managers may not enforce this repository's maturity policy. Keep the
322
- installation safeguards and report any untested consumer exposure.
323
-
324
- Review direct candidates and production-tree changes fully. For development-only
325
- transitives, check advisories, deprecations, and engines; investigate release
326
- notes only when those checks, validation failures, or output differences give
327
- cause. A package bundled or shipped with a CLI/config package belongs to the
328
- consumer review even if this repository also uses it as development tooling.
329
-
330
- An in-range behavior change may already reach the published release's consumers.
331
- Do not describe an older lockfile as protecting them or infer a new breaking
332
- release solely from the lockfile movement. Test the published release and
333
- updated build against actual consumer resolution, and separately preserve the
334
- old locked baseline. To hold back an incompatible allowed release, present a
335
- specific narrower range and obtain the policy's required approval.
336
-
337
- ### Breaking candidates
338
-
339
- Track breaking-candidate decisions throughout the run; report applied breaks
340
- and deferred opportunities separately.
341
- For each candidate, identify affected APIs, behavior, Node.js support, known
342
- consumers, migration work, validation results or gaps, and release implications.
343
- Prepare a concrete proposal and, where useful, validate a trial migration in an
344
- isolated copy before seeking a decision. For stable projects in interactive
345
- mode, ask explicitly whether to accept each reviewed break unless that exact
346
- scope was already authorized; continue independent updates while awaiting the
347
- answer. In unattended mode, defer unapproved stable-project breaks and include
348
- them under `Breaking changes available` in the report without asking. General
349
- permission to update dependencies is not approval for an unspecified break.
350
- For `0.x` projects, both modes authorize reviewed breaking migrations without
351
- another question, but runtime-range narrowing still needs explicit approval.
352
- Record accepted, declined, pending, and deferred decisions separately.
262
+ Major mode lists every update size; confirm authored candidates are the latest
263
+ stable across majors. Do not opt into new prerelease channels.
264
+ `--include-locked` surfaces exact pins without authorizing their removal;
265
+ `@types/node` and `pnpm` are managed by the configuration policy and Setup. This
266
+ discovery does not replace the consumer-range review in step 3.
267
+
268
+ ## Step 3: Evaluate candidates
269
+
270
+ ### Scope and consumer ranges
271
+
272
+ For every runtime dependency of a published package, read registry metadata for
273
+ the newest stable version its declared range allows, accounting for catalogs and
274
+ aliases, and record the range, locked version, newest allowed version, and
275
+ proposed range or version. Review the allowed release even when it is already in
276
+ range or too young to install here, and report untested consumer exposure. Keep
277
+ the published release's fresh-install behavior, the updated build, and the old
278
+ locked baseline distinct; existing in-range exposure is not a break introduced
279
+ by this release. `scripts/consumer-ranges.mjs` builds this table from the
280
+ workspace root and flags rows where consumers resolve something newer than the
281
+ lockfile or something too young to install here; resolve catalog specifiers it
282
+ marks for manual review by hand.
283
+
284
+ Review direct candidates and production-tree changes fully; shipped or bundled
285
+ tooling belongs to consumer review even when used only for development here.
286
+ For development-only transitives, check advisories, deprecations, and engines,
287
+ and read release notes when those findings, validation failures, or output
288
+ differences warrant it. A full review reads release notes, migration guides, and
289
+ advisories and assesses:
290
+
291
+ - Security fixes or regressions, publishing or ownership anomalies, and new
292
+ install scripts or permissions.
293
+ - APIs, types, defaults, configuration, module format, peers, and engines
294
+ against actual repository usage and the versions this update produces,
295
+ reviewing coupled packages together since one update may need a newer
296
+ sibling.
297
+ - Adoptable fixes, performance, capabilities exposed to consumers, and optional
298
+ feature opportunities for the report. Do not implement extra features.
299
+
300
+ When delegating, split independent reviews among authored packages, remaining
301
+ runtime packages, and remaining development packages. Give each reviewer a
302
+ disjoint list, actual usage and source paths, consumer requirements, and the
303
+ version policy; reviewers return decisions and sources without editing, the
304
+ primary agent resolves coupling, and all share fetched metadata and the GitHub
305
+ API budget.
306
+
307
+ Record current and proposed versions, decision, evidence, and approval scope per
308
+ the authorization table. Do not defer a migration merely because it implies a
309
+ major release recommendation. Review exact pins under
310
+ [Version declarations](references/configuration.md#version-declarations).
353
311
 
354
312
  ### Node.js compatibility
355
313
 
356
- For every candidate, minor and patch included, distinguish consumer requirements
357
- from development requirements:
358
-
359
- - **Consumers:** for projects at 1.0.0 or later, keep the user-facing Node.js
360
- minimum and supported range unchanged unless explicitly approved under
361
- `Breaking candidates`. A higher effective consumer minimum or loss of any
362
- supported Node.js version is a break even if `engines.node` is left unchanged.
363
- Check direct, transitive, optional, peer, and workspace dependencies used by
364
- published packages, plus bundled code, emitted syntax, and runtime APIs.
365
- A tool used only for development here is still a consumer dependency if it
366
- ships in a published CLI or configuration package. Compare
367
- full engine ranges, not just the lowest version in each range.
368
- For authorized breaks or zero-versioned projects, update published
369
- `engines.node` to reflect the actual supported range and validate against it.
370
- - **Development:** a higher Node.js requirement for development-only tools,
371
- builds, or CI is allowed when published artifacts remain compatible. If it
372
- exceeds the consumer requirement, add or update the Node.js entry in the
373
- relevant `package.json`'s `devEngines.runtime` with `name: "node"` and a
374
- `version` range covering the actual development requirement. Use the workspace
375
- root for shared tooling and package manifests for package-specific tooling;
376
- preserve other runtime entries and settings. This is the development Node.js
377
- dependency notice; do not raise published `engines.node` to satisfy dev tools.
378
- Align development version pins and build CI as needed while retaining consumer
379
- compatibility checks at the applicable supported minimums (the original ones
380
- unless an approved break or the zero-versioned exception changes them).
314
+ For every candidate, including minors and patches, check consumer and
315
+ development requirements separately:
316
+
317
+ - **Consumers:** compare full supported Node.js ranges across direct,
318
+ transitive, optional, peer, and workspace dependencies, bundled code, emitted
319
+ syntax, and runtime APIs. A higher effective minimum or a lost supported line
320
+ is a break even when `engines.node` is unchanged. Preserve the contract under
321
+ the authorization table; for accepted changes publish truthful engines in the
322
+ [LTS-only shape](references/configuration.md#nodejs-support) and validate the
323
+ resulting range.
324
+ - **Development:** higher requirements for development-only tools, builds, or
325
+ CI are fine while artifacts stay consumer-compatible. When they exceed
326
+ consumer requirements, add or update `devEngines.runtime` with `name: "node"`
327
+ and the actual range, at the root for shared tooling and in package manifests
328
+ for package-specific tools, preserving other entries. Align development pins
329
+ and CI while keeping tests at the applicable consumer minimums. Never raise
330
+ published `engines.node` for development tooling.
381
331
 
382
332
  ### TypeScript migrations
383
333
 
384
- Read the accepted `@kitschpatrol/typescript-config` release's TypeScript peer
385
- range and base configuration. If it requires a new compiler major, offer that
386
- migration with its concrete effects rather than automatically deferring the
387
- authored update. Apply it within existing authorization; ask only for additional
388
- breaking or Node-types changes that the policy actually requires approval for.
389
-
390
- - Add `"node"` to `compilerOptions.types` where Node globals are needed,
391
- preserving other required type entries and the separation from browser code.
392
- - Fix errors exposed by newly enabled strict options; do not disable those
393
- options just to pass.
394
- - Check the new base `lib`, emitted syntax, declarations, and APIs used by
395
- shipped code against the consumer Node.js floor and browser targets. A newer
396
- `lib` can make unavailable APIs type-check; it does not polyfill them.
397
-
398
- Run type checks, build, and consumer validation after the migration, retaining
399
- the distinction between development and consumer Node.js requirements.
400
-
401
- ### Compatibility review
402
-
403
- For direct candidates and production-tree changes, read relevant upstream
404
- release notes, migration guides, and advisories, and assess:
405
-
406
- - **Security:** vulnerabilities fixed or introduced, ownership or publishing
407
- anomalies, new install scripts or permissions.
408
- - **Breaking:** APIs, types, defaults, configuration, module format, peer
409
- ranges, runtime requirements, measured against this repository's actual use.
410
- - **Coupling:** peer and engine requirements against the versions this update
411
- will produce, not the current ones. A major can require a newer minor of a
412
- sibling package (`@astrojs/mdx` 8 requires `astro` 7.2.10 or later).
413
- - **Worth it:** fixes and performance adoptable under the version policy.
414
- Note features exposed by the update and optional feature opportunities for the
415
- report; do not implement new features as extra work.
416
-
417
- When delegation is available, run independent release-note reviews in parallel,
418
- split into authored packages, remaining runtime packages, and remaining direct
419
- development packages. Give each reviewer its disjoint package list, a short
420
- survey of actual usage and relevant source paths, consumer requirements, and
421
- the version policy. Reviewers return decisions and sources without editing
422
- dependencies; the primary agent resolves coupling and combines the results.
423
- Share cached metadata and the GitHub API budget. Review sequentially when
424
- delegation is unavailable.
425
-
426
- Record current → proposed version, decision, and sources. Accept only when
427
- compatibility is preserved, an explicit approval covers the break, or the
428
- zero-versioned exception permits it; defer the rest with a reason. Do not
429
- defer a migration merely because it needs a major release recommendation.
430
-
431
- ## 4. Apply
432
-
433
- Apply only accepted candidates, including minors and patches, by exact package
434
- name. Major mode can apply all accepted update sizes:
334
+ Follow the [tsconfig.json policy](references/configuration.md#tsconfigjson)
335
+ with the accepted config release. When an authored update needs a newer compiler
336
+ major, offer that migration with its concrete effects instead of deferring the
337
+ update, apply it within the authorization table, then run type checks, the
338
+ build, and packed-install validation.
339
+
340
+ ## Step 4: Apply
341
+
342
+ Apply accepted candidates by exact package name, replacing the example list;
343
+ skip this when nothing was accepted:
435
344
 
436
345
  ```bash
437
346
  pnpx taze major -rw --force --include-locked \
@@ -442,321 +351,138 @@ pnpx taze major -rw --force --include-locked \
442
351
  --maturity-period-exclude '<authored-packages>'
443
352
  ```
444
353
 
445
- Replace the example names with the accepted set; skip the command if it is
446
- empty. If only an older compatible target was accepted, set that reviewed
447
- version manually instead of letting Taze choose the latest. Then check the
448
- diff: every manifest and catalog covered, only reviewed versions applied, no
449
- excluded or deferred update slipped in, range style and `workspace:` references
450
- intact. A package accepted in one workspace package is not automatically
451
- accepted in every other one. Hand-edit anything Taze missed (catalogs,
452
- overrides), and add any required development Node.js notice. Use direct edits
453
- for reviewed compiler versions inside the required peer range and for
454
- authorized Node-types changes; do not let Taze choose an incompatible compiler.
455
- Verify `packageManager` remains at Setup's selected version.
354
+ Set a reviewed older target by direct edit when latest was not accepted.
355
+ Acceptance in one workspace package does not apply to the others. Afterwards
356
+ check every manifest and catalog: only reviewed versions, range styles and
357
+ `workspace:` references intact, no deferred or excluded updates. Directly edit
358
+ missed catalogs and overrides, the reviewed compiler and Node-types versions,
359
+ and development Node.js notices. Apply the configuration policy's manifest rules
360
+ and keep Setup's `packageManager`.
456
361
 
457
- ## 5. Resolve and validate
362
+ ## Step 5: Resolve and validate
458
363
 
459
- Run each command as a separate invocation:
460
-
461
- ```bash
462
- pnpm update -r
463
- ```
364
+ Before anything can run install scripts, apply build-trust decisions, review
365
+ overrides and peer rules, and add the exact release-age exemptions that accepted
366
+ young authored targets need, all under the
367
+ [pnpm-workspace.yaml policy](references/configuration.md#pnpm-workspaceyaml).
368
+ Then resolve:
464
369
 
465
370
  ```bash
371
+ pnpm update -r --no-save
466
372
  pnpm dedupe --check
467
373
  ```
468
374
 
469
- Inspect the result. If it reports available deduplication, run the following
470
- separately; other failures need diagnosis, not an unconditional retry:
471
-
472
- ```bash
473
- pnpm dedupe
474
- ```
475
-
476
- Then run the checks, each separately:
477
-
478
- ```bash
479
- pnpm build
480
- pnpm fix
481
- pnpm build # only if fix changed source files
482
- pnpm test
483
- pnpm lint
484
- ```
485
-
486
- Always use bare `pnpm update -r` for the full refresh, without package selectors.
487
- Named-package updates do not provide the same transitive refresh; do not use
488
- `!pkg` selectors as a workaround for deferred candidates. It resolves within
489
- the written ranges and rechecks release age without discarding `node_modules`.
490
- In pnpm 12 it can also raise range floors in `package.json` and catalogs
491
- (for example, `^1.8.0` to `^1.9.0`), so review the manifest and catalog diffs
492
- after every update, not just the lockfile. Preserve excluded declarations and
493
- undo unreviewed range changes by direct edits, then synchronize the lockfile.
494
-
495
- Deduplication consolidates compatible references onto newer versions already
496
- in the tree; it is not a way to hold back or downgrade a dependency. Review
497
- production changes fully and development-only transitives under step 3's
498
- narrower checks. If a deferred version is still allowed by a published runtime
499
- range, use the explicit range/consumer decision path rather than fighting the
500
- resolver with an older lockfile or an unapproved override.
501
- After every `pnpm update -r`, confirm each accepted authored package resolved
502
- to its accepted version. pnpm does not report a maturity holdback, so a lower
503
- resolved version means the release is blocked by `minimumReleaseAge`: add only
504
- that package/version to `minimumReleaseAgeExclude`, never its dependencies,
505
- and update again. If the release still cannot resolve because its own
506
- third-party dependencies are too young, defer that authored update, keep the
507
- previously locked version, and report the date it becomes installable.
508
-
509
- Compare every result with the baseline:
510
-
511
- - **Consumer compatibility:** recheck the resolved published dependency trees
512
- and build artifacts against the Node.js baseline, including transitive
513
- changes from resolution or deduplication. Validate consumer installation and
514
- representative runtime behavior at the applicable supported minimums separately
515
- from checks needing the newer development runtime. Review `pnpm fix` changes
516
- to `engines.node` and `devEngines.runtime`; a passing fixer or build on newer
517
- Node.js does not establish consumer compatibility. Diff the production-engine
518
- inventories, test the packed build in known consumers, and run fixtures at the
519
- exact supported Node.js floor using [the verification recipes](references/verification.md).
520
- For stable projects, do not retain a newly introduced break outside explicit
521
- approval; present the candidate or defer it. Do not mask it with an unapproved
522
- `engines.node` increase. For authorized breaks and zero-versioned projects,
523
- validate the new contracts and Node.js range and report the baseline changes.
524
- - **Logs:** for each new warning, deprecation, or peer issue, find the package
525
- that introduced it (`pnpm why`) and search upstream for a known issue. Report
526
- it with the link. For a peer declaration lagging a verified compatible
527
- version, add a scoped `peerDependencyRules.allowedVersions` entry such as
528
- `"parent@range>peer": "tested-range"` to `pnpm-workspace.yaml` in both modes,
529
- and report the entry, the evidence, and that it suppresses a warning rather
530
- than fixing incompatibility. Compatibility is verified when the checks pass
531
- with the installed combination and no upstream report contradicts it. Apply
532
- the entry even when the lagging declaration arrives through an authored
533
- package: the consumer's `pnpm-workspace.yaml` is where the warning is
534
- silenced, and the report flags the upstream fix separately. Do not use broad
535
- `allowAny` or disable strict peer checks. Revisit such workarounds during
536
- step 9.
537
- - **Build output:** if the baseline includes build output, rebuild with the
538
- same command and environment and diff the trees with content-hashed filenames
539
- normalized (`name.[hash].js`). Explain every remaining difference with an
540
- upstream changelog entry, issue, or reviewed migration/configuration change;
541
- anything unexplained needs investigation. Unless explicitly configured,
542
- tsdown derives its build target from `engines.node`, so an engine change can
543
- legitimately alter emitted syntax. Record the effective targets before and
544
- after, distinguish expected output changes from regressions, and check runtime
545
- APIs separately because syntax lowering does not provide polyfills.
546
- - **After `pnpm fix`:** review the diff, then rebuild and diff against the
547
- pre-fix build. Formatting changes must produce identical output. A lint
548
- rule's suggested fix can change behavior (default parameters do not replace
549
- `null`); in that case keep the code and add an inline disable that says why.
550
- If the project can or is likely to run in browsers, including alongside
551
- Node.js, disable the offending rule for the affected shipped code when its
552
- fix would introduce regex flags or DOM APIs unsupported by the project's
553
- browser targets. Explain the compatibility reason and keep the compatible
554
- code instead of applying the fix; revert the fix if already applied. This
555
- also applies to zero-versioned projects, but does not apply to Node.js-only
556
- projects.
557
- Resolve remaining lint errors by hand.
558
-
559
- On failure, make the smallest change consistent with the version policy and
560
- rerun from the failing step:
561
-
562
- - To tell a new failure from a pre-existing one, check the baseline logs.
563
- `git stash` does not revert `node_modules`, so rerunning a check after
564
- stashing still uses the new dependencies.
565
- - To isolate a breaking update: set half the accepted updates back to their
566
- previous specifiers, `pnpm update -r`, rerun the failing check, repeat.
567
- For an out-of-range update, defer the culprit unless an approval or the
568
- zero-versioned exception permits it and the migration resolves the failure.
569
- For an already allowed runtime release, follow the range decision path in
570
- step 3; resetting a specifier or lockfile may not exclude it.
571
-
572
- Add focused tests only where a compatibility change touches behavior not
573
- already covered. Review `readme.md` accuracy and automation opportunities in step 8.
574
-
575
- ## 6. Exclusion cleanup
576
-
577
- Only if `minimumReleaseAgeExclude` is non-empty in any `pnpm-workspace.yaml`
578
- (at the start, or after step 5). Cleanup removes entries that no longer do
579
- anything; it never changes which version is installed and never downgrades a
580
- package.
581
-
582
- Decide each entry from the publish time recorded in Setup, or look it up now:
583
-
584
- - **Mature** (published at least 24 hours before the run): remove it; the
585
- version resolves without it.
586
- - **Young, authored package:** keep it while that version is the release this
587
- run installs. Removing it would hold the package back to an older release.
588
- - **Young, third-party package:** keep it while it holds a version that is
589
- already locked; removing it would downgrade an installed package rather than
590
- block a new one. Report it as pending with the date it can be removed. Do not
591
- add new third-party entries.
592
- - **Unused** (the version is neither locked nor targeted): remove it.
593
-
594
- Edit the list directly, preserving neighboring keys and comments; use `[]` or
595
- remove the key when nothing remains. Then repeat step 5's separate bare
596
- `pnpm update -r` and `pnpm dedupe --check` invocations, followed by a separate
597
- `pnpm dedupe` only when the check reports available changes, and run each check
598
- separately:
599
-
600
- ```bash
601
- pnpm build
602
- pnpm test
603
- pnpm lint
604
- ```
605
-
606
- Compare the resolved versions with the lockfile saved before cleanup. pnpm
607
- does not report a maturity holdback; it silently selects the newest mature
608
- version. An authored package that resolved below its latest stable release, or
609
- any package that resolved below its previous locked version, means a removed
610
- entry was still needed: re-add that narrowest package/version entry and resolve
611
- again. Never restore the whole previous list.
612
-
613
- If `pnpm-lock.yaml` comes out byte-identical and no ranges or build settings
614
- changed, the installed tree did not change; rerun only `pnpm lint`.
615
-
616
- If the list was empty throughout, skip this section and continue to step 7.
617
- If cleanup changes resolution, repeat step 5's consumer compatibility review
618
- before reviewing documentation.
619
-
620
- ## 7. Side effects declaration
621
-
622
- For each published package, check that `sideEffects` in `package.json` tells
623
- the truth about the shipped code. Bundlers drop any import they consider
624
- side-effect-free when the declaration says `false`, and keep every module
625
- otherwise, so a wrong `false` silently removes code consumers rely on and a
626
- missing `false` on a pure package forfeits tree shaking.
627
-
628
- 1. Read the declaration: `false`, an array of file patterns, `true`, or absent,
629
- which means `true`.
630
- 2. Inspect the published entry points and every module they reach, in the
631
- build output that actually ships (`dist/` and the `files` list), including
632
- bundled dependencies. Look for work that runs on import rather than on
633
- call: assignments to globals or prototypes, polyfills, registrations such
634
- as `customElements.define`, event listeners, process or environment setup,
635
- CSS and asset imports, and bare imports kept only for their effects.
636
- 3. Set the declaration to match: `false` when nothing runs on import, an array
637
- naming the exact shipped files that do when only some do, and `true` when
638
- most modules have effects. A package with no importable entry point, such
639
- as a `bin`-only CLI, is unaffected either way; leave its declaration as is.
640
- 4. Report every evaluation: the package, which modules were inspected, what
641
- runs on import if anything, the declaration before and after, and why it
642
- changed or stayed. A wrong `false` is a bug; a newly added `false` is a
643
- performance improvement. Count either under the release recommendation.
644
-
645
- ## 8. Documentation review
646
-
647
- Review `readme.md` against the updated project. Correct stale installation
648
- instructions, requirements, commands, examples, configuration guidance, and
649
- feature descriptions. If `readme.md` is generated or copied from another file,
650
- update its maintained source and regenerate it through the existing workflow.
651
-
652
- Review each section for content that would be more reliably maintained through
653
- mdat, especially content duplicated from package metadata, CLI help, source
654
- files, or other documentation. Prefer a rule bundled with mdat when it fits,
655
- then a suitable mdat plugin, or a custom rule in `mdat.config.ts` for
656
- project-specific needs. Check the installed rules and relevant documentation
657
- before choosing an implementation. Replace manually maintained sections where
658
- generation reduces duplication or prevents drift while preserving their useful
659
- content and readability; keep explanatory prose manual when automation adds
660
- no benefit. Any new plugin dependency must satisfy the dependency review,
661
- release maturity, and compatibility policies above.
662
-
663
- Run the project's mdat generation and documentation checks, inspect the
664
- rendered content for accuracy, and confirm that a second generation produces
665
- no further changes. Validate any new dependency under steps 5 and 6 before
666
- continuing. Include documentation corrections and mdat conversions in the
667
- final report.
668
-
669
- ## 9. @kitschpatrol/shared-config override minimization
670
-
671
- Run this as the final cleanup after all accepted updates, migrations,
672
- validation, release-age exclusion cleanup, and documentation review, before
673
- the release recommendation and report.
674
-
675
- Review every shared-config-related configuration file in the project root,
676
- including dotfiles, companion ignore files, and configuration stored in
677
- `package.json`. Include the individual `@kitschpatrol/*-config` packages used by
678
- the project. Inventory every local override beyond the upstream default export
679
- or equivalent base configuration: rule settings, options, ignores, file globs,
680
- and other customizations.
681
- Include scoped peer-warning workarounds added during the update; remove them
682
- when upstream peer declarations now cover the tested versions.
683
-
684
- For each override, compare it with the defaults and effective configuration of
685
- the exact versions installed after the updates. Check the current code it
686
- targets and, for upstream workarounds, the relevant upstream changes or fixes.
687
- Remove overrides that duplicate current defaults, target code or files that no
688
- longer exist, or compensate for issues now fixed upstream. Do not infer that an
689
- override is redundant merely because checks pass while it is still enabled.
690
-
691
- Validate removals in small groups using the affected tools' checks without
692
- caches, covering the affected files and any files newly included by removing
693
- ignores. Recheck effective configuration where merge order or file matching
694
- matters. Keep overrides that still serve a concrete project requirement,
695
- including the behavior and browser-compatibility protections from step 5, and
696
- record why each is needed. If necessity cannot be established, retain the
697
- override and report the unresolved evidence instead of guessing.
698
-
699
- After changing configuration, rerun the affected build, test, type, and lint
700
- checks and compare results and build output as in step 5. The final report must
701
- account for every override: removed with evidence, retained with a current
702
- justification, or unresolved with the missing evidence identified.
375
+ `pnpm update -r --no-save` refreshes every direct and transitive dependency
376
+ within the declared ranges without rewriting manifests or catalogs; named
377
+ updates and `!pkg` selectors do not give that transitive refresh. Run
378
+ `pnpm dedupe` only when the check reports available deduplication, and diagnose
379
+ other failures; deduplication moves compatible references onto newer versions
380
+ already in the tree and cannot hold back a deferred release. Review newly
381
+ resolved packages under step 3, apply the consumer-range decision to deferred
382
+ in-range runtime releases, and confirm after each resolution that authored
383
+ packages reached their accepted targets, investigating mismatches with the
384
+ configuration policy's maturity procedure rather than assuming an age holdback.
385
+ After each resolution, run `scripts/release-age.mjs new-versions` against the
386
+ saved pre-resolution lockfile to list young versions it introduced, and diff
387
+ `minimumReleaseAgeExclude` against the entries you added: pnpm appends entries
388
+ itself when it falls back to young versions, and each one needs the policy's
389
+ review.
390
+
391
+ Run the [validation procedure](references/verification.md#updated-validation):
392
+ build, fix, rebuild when needed, test, lint, baseline and output comparison,
393
+ warning review, advisory comparison, packed consumer installs, and exact-floor
394
+ checks. Apply the configuration policy's compatibility fixes and warning rules.
395
+ Keep only changes the authorization table permits, revise decisions when
396
+ validation reveals a break, and add focused tests only for affected behavior
397
+ that is not already covered.
398
+
399
+ ## Step 6: Exclusion cleanup
400
+
401
+ If `minimumReleaseAgeExclude` was ever non-empty during the run, follow the
402
+ [release-age cleanup](references/configuration.md#release-age-exemptions), which
403
+ is version-preserving and names its own validation.
404
+
405
+ ## Step 7: Side effects
406
+
407
+ Evaluate each published package's shipped code against its `sideEffects`
408
+ declaration under the [side-effects policy](references/configuration.md#side-effects),
409
+ recording evidence and outcome even when nothing changes.
410
+
411
+ ## Step 8: Documentation
412
+
413
+ Review `readme.md` for stale installation instructions, requirements, commands,
414
+ examples, configuration guidance, and feature descriptions; for generated or
415
+ copied readmes, edit the maintained source and regenerate through the existing
416
+ workflow, never by running mdat from a different package's directory. Convert
417
+ sections that duplicate metadata, CLI help, source files, or other documentation
418
+ to mdat generation where that reduces duplication or drift without hurting
419
+ readability, preferring a bundled rule, then a suitable plugin, then a custom
420
+ rule in `mdat.config.ts`; keep explanatory prose that automation adds nothing
421
+ to. New plugin dependencies get the same review as any other candidate and go
422
+ through steps 5 and 6. Run generation and documentation checks, inspect the
423
+ rendered result, confirm a second generation changes nothing, and record
424
+ corrections and conversions.
425
+
426
+ ## Step 9: Final configuration cleanup
427
+
428
+ Recheck the complete configuration policy against the final tree and perform
429
+ [override minimization](references/configuration.md#final-override-minimization).
430
+ Run affected fixers and checks after the last edit, and account for every
431
+ override before recommending a release.
703
432
 
704
433
  ## Release recommendation
705
434
 
706
- Recommend `patch`, `minor`, or `major` from the final consumer-visible changes,
707
- following the repository's release conventions. Do not infer the recommendation
708
- from the largest dependency version bump:
709
-
710
- - **Patch:** compatible bug or security fixes, performance improvements, or
711
- dependency/tooling maintenance with no new consumer-facing capability. A
712
- development-only Node.js increase with the required notice can remain a
713
- patch, and so does a corrected or newly added `sideEffects` declaration.
714
- - **Minor:** backward-compatible functionality or capabilities actually exposed
715
- to consumers by the accepted updates. Explain what consumers gain; an upstream
716
- minor or major alone is not a reason for a minor release. For zero-versioned
717
- projects, also recommend a minor release for accepted consumer-facing breaking
718
- changes unless the repository's pre-1.0 release conventions specify otherwise.
719
- - **Major:** explicitly approved consumer-facing breaks in projects at 1.0.0
720
- or later, including a raised consumer Node.js floor. A dependency major or
721
- development-only requirement by itself does not justify a project major.
722
-
723
- Give a short rationale per affected published package, or one recommendation
724
- for a shared release version using the highest applicable level. If nothing
725
- releasable changed, say no release is needed. An approved major release is
726
- within scope; an unapproved breaking candidate stays pending or deferred.
727
- For `0.x`, accepted consumer breaks normally require a minor, not a patch;
728
- follow an explicit repository convention if it differs. Assess changes already
729
- reachable through the old published ranges separately from newly introduced
730
- consumer breaks. Recommend only; do not bump repository versions.
435
+ Recommend from the final consumer-visible changes, following repository
436
+ conventions, with a rationale per published package or the highest level for a
437
+ shared release:
438
+
439
+ - **Patch:** compatible bug and security fixes, performance, and dependency or
440
+ tooling maintenance without new consumer capability, including
441
+ development-only Node.js increases with their notice and corrected or newly
442
+ added `sideEffects` declarations.
443
+ - **Minor:** backward-compatible functionality actually exposed to consumers;
444
+ explain the gain. For `0.x`, also accepted consumer breaks unless explicit
445
+ pre-1.0 repository conventions differ.
446
+ - **Major:** authorized consumer breaks in packages at 1.0.0 or later, including
447
+ a raised Node.js floor or a declared line removed by the LTS-only range.
448
+
449
+ Dependency version labels and development-only requirements never decide the
450
+ level. Separate pre-existing exposure through published ranges from new breaks.
451
+ Say that no release is needed when nothing releasable changed, and leave
452
+ repository versions unchanged.
453
+
454
+ The next release also ships every unreleased commit recorded in Setup. Give the
455
+ level this run's changes need and, when the unreleased commits raise it, the
456
+ level for the next release overall, citing those commits.
731
457
 
732
458
  ## Report
733
459
 
734
- State the execution mode and why it was selected. Include a `Breaking changes
735
- available` section for deferred breaking candidates: current and proposed
736
- versions, affected consumers/contracts, required migration, validation results
737
- or gaps, recommended release level, and the decision still needed. Distinguish
738
- these from applied breaks authorized explicitly or by the `0.x` policy. In
739
- unattended mode, record decisions needed as follow-up items, not questions or
740
- pending waits. Report unavailable checks and blocked work even when independent
741
- updates succeeded.
742
-
743
460
  Review the full diff for unrelated changes, excluded-package edits, and stray
744
- exemptions first. Then summarize: applied updates; major decisions with
745
- sources; consumer impact, approvals, declined/deferred decisions, and breaks
746
- accepted under the zero-versioned policy;
747
- output differences and their upstream or migration explanations;
748
- consumer Node.js requirements before and after, development Node.js changes and
749
- their `devEngines.runtime` notices; the release recommendation and its rationale;
750
- baseline lockfile drift; the `packageManager` version chosen and its source;
751
- `sideEffects` evaluations with their evidence and outcome; runtime ranges,
752
- fresh-install exposure, and approved
753
- range restrictions; TypeScript migrations; new warnings and scoped peer
754
- workarounds; what was validated, at which exact Node.js versions, and in which
755
- known consumers, including CLI/fixture comparisons and unavailable baselines;
756
- remaining `minimumReleaseAgeExclude` entries with reasons and the dates they can
757
- be removed; deferred upgrades,
758
- documentation corrections and mdat conversions;
759
- shared-config overrides removed or retained with their justifications and any
760
- unresolved override reviews; unresolved failures, checks that could not run,
761
- and steps run differently because of the environment. Passing checks do not
762
- prove the absence of breaking changes. Leave everything uncommitted.
461
+ exemptions. Start the report with a summary of at most ten lines: what was
462
+ applied, the release recommendation per package, and the decisions needed. Raw
463
+ logs stay in the run directory. Then cover, from the decisions and evidence
464
+ recorded above and in both references:
465
+
466
+ - **Updates and decisions:** execution mode and reason, applied versions with
467
+ sources, approvals and applied breaks including `0.x`, declined and deferred
468
+ candidates, migrations, and optional feature opportunities. Under a
469
+ `Breaking changes available` heading list each deferred break's versions,
470
+ consumer impact, migration, validation or gaps, release level, and the
471
+ decision needed.
472
+ - **Consumer impact and release:** runtime ranges and fresh-install exposure,
473
+ approved restrictions, consumer Node.js before and after, development
474
+ requirements and notices, TypeScript migrations, and the release
475
+ recommendation with rationale.
476
+ - **Maintenance:** the Homebrew pnpm selection; every configuration decision
477
+ with its justification, including build trust, overrides and peers, preserved
478
+ hoisting, keywords, Node.js ranges and types, exact pins, CSpell, and side
479
+ effects; remaining age exemptions with reasons and removal dates;
480
+ documentation changes and mdat conversions.
481
+ - **Evidence and gaps:** the original versus Setup baseline distinction and any
482
+ lockfile drift, checks with their exact runtimes, installation and fixture
483
+ results, explained output differences, advisories, warnings and suppressions,
484
+ missing historical baselines, unresolved failures, blocked work, skipped
485
+ optional steps, and environment-driven deviations.
486
+
487
+ Passing checks do not prove the absence of breaks. Leave all changes
488
+ uncommitted.