@rtorcato/repo-tooling 3.19.0 → 3.19.2
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/base/checks.js
CHANGED
|
@@ -2,7 +2,7 @@ import path from 'node:path';
|
|
|
2
2
|
import fs from 'fs-extra';
|
|
3
3
|
import { BLOCK_START, hasStaleAgentBlock } from '../cli/generators/agent-rules.js';
|
|
4
4
|
import { BADGE_START, hasPublicOnlyBadges } from '../cli/generators/badges.js';
|
|
5
|
-
import { claudeSkillStatus, SHIPPED_SKILL } from '../cli/generators/claude-skills.js';
|
|
5
|
+
import { claudeSkillStatus, SHIPPED_SKILL, skillDiffCommand, } from '../cli/generators/claude-skills.js';
|
|
6
6
|
import { DEPENDABOT_CONFIG_PATHS, dependabotIgnoreRules } from '../cli/generators/security.js';
|
|
7
7
|
import { detectNestedLanguages } from '../cli/utils/detect-language.js';
|
|
8
8
|
/**
|
|
@@ -500,7 +500,9 @@ export async function checkClaudeSkills(skillsDir) {
|
|
|
500
500
|
// A local fork is `ok` for the same reason a modified copied asset is (#448):
|
|
501
501
|
// it is somebody's deliberate work, so it is named once and never nagged as
|
|
502
502
|
// fixable — pointing at a `fix` that would refuse is worse than saying nothing.
|
|
503
|
-
|
|
503
|
+
// `realFile` is set whenever `contentState` is — both mean something is
|
|
504
|
+
// installed. The extra test is TypeScript's, not a real condition.
|
|
505
|
+
if (status.realFile && status.contentState && status.contentState !== 'pristine') {
|
|
504
506
|
const why = status.contentState === 'modified'
|
|
505
507
|
? `has local changes since ${status.installedVersion}`
|
|
506
508
|
: 'carries no content record, so a fork cannot be told from a stale copy';
|
|
@@ -508,7 +510,9 @@ export async function checkClaudeSkills(skillsDir) {
|
|
|
508
510
|
check,
|
|
509
511
|
status: 'ok',
|
|
510
512
|
detail: `${SHIPPED_SKILL} skill at ${status.file} ${why}; this package ships ${status.shippedVersion} and will not overwrite it`,
|
|
511
|
-
|
|
513
|
+
// Name both paths: "diff it against the shipped copy" left the reader
|
|
514
|
+
// with nothing to diff, in the one case they most want to look (#484).
|
|
515
|
+
hint: `Diff it against the shipped copy — \`${skillDiffCommand({ realFile: status.realFile, shippedFile: status.shippedFile })}\` — then run \`npx @rtorcato/repo-tooling fix claude-skills --force-skills\` to take the shipped version`,
|
|
512
516
|
};
|
|
513
517
|
}
|
|
514
518
|
return {
|
package/dist/base/fixers.js
CHANGED
|
@@ -16,7 +16,7 @@ import path from 'node:path';
|
|
|
16
16
|
import chalk from 'chalk';
|
|
17
17
|
import inquirer from 'inquirer';
|
|
18
18
|
import { installAgentRules, installAiSetup } from '../cli/generators/agent-rules.js';
|
|
19
|
-
import { installClaudeSkill, resolveSkillsDir, SHIPPED_SKILL, } from '../cli/generators/claude-skills.js';
|
|
19
|
+
import { installClaudeSkill, resolveSkillsDir, SHIPPED_SKILL, skillDiffCommand, } from '../cli/generators/claude-skills.js';
|
|
20
20
|
import { generateBrand } from '../cli/generators/brand.js';
|
|
21
21
|
import { generateCommunityHealth } from '../cli/generators/community-health.js';
|
|
22
22
|
import { generateCommitlintConfig } from '../cli/generators/git.js';
|
|
@@ -89,7 +89,7 @@ function describeSkillFork(result) {
|
|
|
89
89
|
return [
|
|
90
90
|
`skipped — ${SHIPPED_SKILL} was not overwritten with ${result.shippedVersion}: ${why}`,
|
|
91
91
|
` ${target}`,
|
|
92
|
-
` compare:
|
|
92
|
+
` compare: ${skillDiffCommand(result)}`,
|
|
93
93
|
' overwrite anyway: fix claude-skills --force-skills',
|
|
94
94
|
];
|
|
95
95
|
}
|
|
@@ -129,6 +129,32 @@ export async function readShippedSkill(name = SHIPPED_SKILL) {
|
|
|
129
129
|
const pkg = await fs.readJson(path.join(root, 'package.json'));
|
|
130
130
|
return { content, version: String(pkg.version), file };
|
|
131
131
|
}
|
|
132
|
+
/**
|
|
133
|
+
* POSIX single-quote escaping — the only form correct for arbitrary bytes.
|
|
134
|
+
* Inside single quotes every character is literal, so `'` is the sole one
|
|
135
|
+
* needing care: end the quote, escape it, start a new one. Double quotes are
|
|
136
|
+
* not a substitute; `$(...)`, backticks and `\` all still expand inside them.
|
|
137
|
+
*/
|
|
138
|
+
function shellQuote(value) {
|
|
139
|
+
return `'${value.replaceAll("'", "'\\''")}'`;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* The command a human runs to see what their fork changed, before deciding
|
|
143
|
+
* whether to take the shipped copy. One builder, because `doctor` and `fix`
|
|
144
|
+
* both print it and two independently-built strings drift (#484). Always
|
|
145
|
+
* `realFile`: through a stow symlink the nominal path is the link, and the
|
|
146
|
+
* bytes worth reading are in the dotfiles checkout it points at.
|
|
147
|
+
*
|
|
148
|
+
* Both paths are user-influenced — `--skills-dir` is an argument (#490) and
|
|
149
|
+
* `realFile` is wherever a symlink happens to point — and this line exists to
|
|
150
|
+
* be pasted into a shell, so it is quoted rather than merely interpolated
|
|
151
|
+
* (#493). Quoting beats refusing to emit a command: single quotes make an odd
|
|
152
|
+
* path *more* visible, not less, and keep the hint usable in the odd case
|
|
153
|
+
* instead of only the ordinary one.
|
|
154
|
+
*/
|
|
155
|
+
export function skillDiffCommand(paths) {
|
|
156
|
+
return `diff ${shellQuote(paths.realFile)} ${shellQuote(paths.shippedFile)}`;
|
|
157
|
+
}
|
|
132
158
|
/** Whether `file` is itself a symlink, as opposed to merely resolving through one. */
|
|
133
159
|
async function isSymlink(file) {
|
|
134
160
|
return await fs
|
|
@@ -185,6 +211,8 @@ export async function claudeSkillStatus(name = SHIPPED_SKILL, explicit) {
|
|
|
185
211
|
const shipped = await readShippedSkill(name);
|
|
186
212
|
const { dir } = await resolveSkillsDir(explicit);
|
|
187
213
|
const absent = {
|
|
214
|
+
realFile: null,
|
|
215
|
+
shippedFile: shipped.file,
|
|
188
216
|
installed: false,
|
|
189
217
|
installedVersion: null,
|
|
190
218
|
shippedVersion: shipped.version,
|
|
@@ -202,6 +230,8 @@ export async function claudeSkillStatus(name = SHIPPED_SKILL, explicit) {
|
|
|
202
230
|
const behind = installedVersion === null || isNewerVersion(shipped.version, installedVersion);
|
|
203
231
|
return {
|
|
204
232
|
file,
|
|
233
|
+
realFile: (await isSymlink(file)) ? await fs.realpath(file) : file,
|
|
234
|
+
shippedFile: shipped.file,
|
|
205
235
|
installed: true,
|
|
206
236
|
installedVersion,
|
|
207
237
|
shippedVersion: shipped.version,
|
|
@@ -4,7 +4,9 @@ import fs from 'fs-extra';
|
|
|
4
4
|
import { recordAssetHash } from './lockfile.js';
|
|
5
5
|
export const PRESETS = {
|
|
6
6
|
biome: {
|
|
7
|
-
|
|
7
|
+
// Not named `biome.json`: Biome auto-discovers any file by that name, so
|
|
8
|
+
// shipping one inside this package made it a second root config here (#486).
|
|
9
|
+
source: 'tooling/biome/preset.json',
|
|
8
10
|
target: 'biome.json',
|
|
9
11
|
desc: 'Biome formatter and linter configuration',
|
|
10
12
|
},
|
|
@@ -84,7 +84,7 @@ function matchesBiomeConfig(contents) {
|
|
|
84
84
|
if (BIOME_PRESET_REF.test(JSON.stringify(config.extends ?? '')))
|
|
85
85
|
return true;
|
|
86
86
|
// The inlined preset: biome's own `$schema` plus the `linter.rules.preset`
|
|
87
|
-
// key the shipped `tooling/biome/
|
|
87
|
+
// key the shipped `tooling/biome/preset.json` sets.
|
|
88
88
|
const schema = config.$schema;
|
|
89
89
|
return (typeof schema === 'string' &&
|
|
90
90
|
schema.includes('biomejs.dev/schemas/') &&
|
|
@@ -1373,7 +1373,7 @@ function readSchemaUrl(contents) {
|
|
|
1373
1373
|
* of which version the config targets, so comparing it against the declared
|
|
1374
1374
|
* dependency floor is exact — no heuristics, no false positives.
|
|
1375
1375
|
*
|
|
1376
|
-
* This is the #330 defect precisely: `tooling/biome/
|
|
1376
|
+
* This is the #330 defect precisely: `tooling/biome/preset.json` carries
|
|
1377
1377
|
* `$schema` 2.5.0 and uses `linter.rules.preset`, a 2.5 key, while
|
|
1378
1378
|
* `peerDependencies` advertised `@biomejs/biome: ^2.0.0`. Consumers on 2.0–2.4
|
|
1379
1379
|
* got `Found an unknown key \`preset\`` with nothing pointing at the range.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rtorcato/repo-tooling",
|
|
3
|
-
"version": "3.19.
|
|
3
|
+
"version": "3.19.2",
|
|
4
4
|
"description": "One CLI to scaffold, audit and fix your repo's whole toolchain — linting, tests, commits, releases & CI.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [
|
|
@@ -90,7 +90,7 @@
|
|
|
90
90
|
"tooling/docusaurus/docs-helpers.mjs",
|
|
91
91
|
"tooling/docusaurus/theme-tokens.css",
|
|
92
92
|
"tooling/docusaurus/theme.css",
|
|
93
|
-
"tooling/biome/
|
|
93
|
+
"tooling/biome/preset.json",
|
|
94
94
|
"tooling/bun/bunfig.toml",
|
|
95
95
|
"tooling/nx/nx.json",
|
|
96
96
|
"tooling/changesets/config.json",
|
|
@@ -201,7 +201,7 @@
|
|
|
201
201
|
"types": "./tooling/docusaurus/index.d.mts",
|
|
202
202
|
"import": "./tooling/docusaurus/index.mjs"
|
|
203
203
|
},
|
|
204
|
-
"./biome": "./tooling/biome/
|
|
204
|
+
"./biome": "./tooling/biome/preset.json",
|
|
205
205
|
"./nx": "./tooling/nx/nx.json",
|
|
206
206
|
"./changesets": "./tooling/changesets/config.json",
|
|
207
207
|
"./release-please": "./tooling/release-please/release-please-config.json",
|