safeword 0.8.9 → 0.8.10
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/{check-QMAGWUOA.js → check-4HX4SNVV.js} +6 -8
- package/dist/{check-QMAGWUOA.js.map → check-4HX4SNVV.js.map} +1 -1
- package/dist/{chunk-CLSGXTOL.js → chunk-POPS3ZRQ.js} +479 -78
- package/dist/chunk-POPS3ZRQ.js.map +1 -0
- package/dist/cli.js +5 -9
- package/dist/cli.js.map +1 -1
- package/dist/{diff-2T7UDES7.js → diff-7QIV6Z5B.js} +5 -7
- package/dist/{diff-2T7UDES7.js.map → diff-7QIV6Z5B.js.map} +1 -1
- package/dist/index.d.ts +0 -5
- package/dist/reset-RP7AGR2Y.js +73 -0
- package/dist/reset-RP7AGR2Y.js.map +1 -0
- package/dist/setup-ZYRPDTQI.js +91 -0
- package/dist/setup-ZYRPDTQI.js.map +1 -0
- package/dist/{upgrade-FALAUUKE.js → upgrade-K2FFESUH.js} +31 -43
- package/dist/upgrade-K2FFESUH.js.map +1 -0
- package/package.json +1 -1
- package/templates/SAFEWORD.md +1 -0
- package/templates/guides/cli-reference.md +9 -11
- package/dist/chunk-4URRFBUS.js +0 -88
- package/dist/chunk-4URRFBUS.js.map +0 -1
- package/dist/chunk-CLSGXTOL.js.map +0 -1
- package/dist/chunk-KQ6BLN6W.js +0 -493
- package/dist/chunk-KQ6BLN6W.js.map +0 -1
- package/dist/reset-QRXG7KZZ.js +0 -74
- package/dist/reset-QRXG7KZZ.js.map +0 -1
- package/dist/setup-QUUJ7SH3.js +0 -100
- package/dist/setup-QUUJ7SH3.js.map +0 -1
- package/dist/sync-ISBJ7X2T.js +0 -9
- package/dist/sync-ISBJ7X2T.js.map +0 -1
- package/dist/upgrade-FALAUUKE.js.map +0 -1
|
@@ -2,38 +2,49 @@ import {
|
|
|
2
2
|
compareVersions
|
|
3
3
|
} from "./chunk-FJYRWU2V.js";
|
|
4
4
|
import {
|
|
5
|
-
|
|
6
|
-
} from "./chunk-4URRFBUS.js";
|
|
7
|
-
import {
|
|
5
|
+
SAFEWORD_SCHEMA,
|
|
8
6
|
createProjectContext,
|
|
9
7
|
error,
|
|
8
|
+
exists,
|
|
10
9
|
header,
|
|
11
10
|
info,
|
|
12
11
|
listItem,
|
|
12
|
+
readFileSafe,
|
|
13
13
|
reconcile,
|
|
14
14
|
success,
|
|
15
15
|
warn
|
|
16
|
-
} from "./chunk-
|
|
17
|
-
import {
|
|
18
|
-
SAFEWORD_SCHEMA,
|
|
19
|
-
exists,
|
|
20
|
-
readFileSafe
|
|
21
|
-
} from "./chunk-CLSGXTOL.js";
|
|
16
|
+
} from "./chunk-POPS3ZRQ.js";
|
|
22
17
|
import {
|
|
23
18
|
VERSION
|
|
24
19
|
} from "./chunk-ORQHKDT2.js";
|
|
25
20
|
|
|
26
21
|
// src/commands/upgrade.ts
|
|
27
22
|
import nodePath from "path";
|
|
28
|
-
function
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
23
|
+
function getProjectVersion(safewordDirectory) {
|
|
24
|
+
const versionPath = nodePath.join(safewordDirectory, "version");
|
|
25
|
+
return readFileSafe(versionPath)?.trim() ?? "0.0.0";
|
|
26
|
+
}
|
|
27
|
+
function printUpgradeSummary(result, projectVersion) {
|
|
28
|
+
header("Upgrade Complete");
|
|
29
|
+
info(`
|
|
30
|
+
Version: v${projectVersion} \u2192 v${VERSION}`);
|
|
31
|
+
if (result.created.length > 0) {
|
|
32
|
+
info("\nCreated:");
|
|
33
|
+
for (const file of result.created) listItem(file);
|
|
34
|
+
}
|
|
35
|
+
if (result.updated.length > 0) {
|
|
36
|
+
info("\nUpdated:");
|
|
37
|
+
for (const file of result.updated) listItem(file);
|
|
34
38
|
}
|
|
35
|
-
|
|
36
|
-
|
|
39
|
+
if (result.packagesToRemove.length > 0) {
|
|
40
|
+
warn(`
|
|
41
|
+
${result.packagesToRemove.length} package(s) are now bundled in eslint-plugin-safeword:`);
|
|
42
|
+
for (const pkg of result.packagesToRemove) listItem(pkg);
|
|
43
|
+
info("\nIf you don't use these elsewhere, you can remove them:");
|
|
44
|
+
listItem(`npm uninstall ${result.packagesToRemove.join(" ")}`);
|
|
45
|
+
}
|
|
46
|
+
success(`
|
|
47
|
+
Safeword upgraded to v${VERSION}`);
|
|
37
48
|
}
|
|
38
49
|
async function upgrade() {
|
|
39
50
|
const cwd = process.cwd();
|
|
@@ -42,8 +53,7 @@ async function upgrade() {
|
|
|
42
53
|
error("Not configured. Run `safeword setup` first.");
|
|
43
54
|
process.exit(1);
|
|
44
55
|
}
|
|
45
|
-
const
|
|
46
|
-
const projectVersion = readFileSafe(versionPath)?.trim() ?? "0.0.0";
|
|
56
|
+
const projectVersion = getProjectVersion(safewordDirectory);
|
|
47
57
|
if (compareVersions(VERSION, projectVersion) < 0) {
|
|
48
58
|
error(`CLI v${VERSION} is older than project v${projectVersion}.`);
|
|
49
59
|
error("Update the CLI first: npm install -g safeword");
|
|
@@ -54,29 +64,7 @@ async function upgrade() {
|
|
|
54
64
|
try {
|
|
55
65
|
const ctx = createProjectContext(cwd);
|
|
56
66
|
const result = await reconcile(SAFEWORD_SCHEMA, "upgrade", ctx);
|
|
57
|
-
|
|
58
|
-
info(`
|
|
59
|
-
Version: v${projectVersion} \u2192 v${VERSION}`);
|
|
60
|
-
if (result.created.length > 0) {
|
|
61
|
-
info("\nCreated:");
|
|
62
|
-
for (const file of result.created) {
|
|
63
|
-
listItem(file);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
if (result.updated.length > 0) {
|
|
67
|
-
info("\nUpdated:");
|
|
68
|
-
for (const file of result.updated) {
|
|
69
|
-
listItem(file);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
if (result.packagesToInstall.length > 0) {
|
|
73
|
-
info(`
|
|
74
|
-
Syncing ${result.packagesToInstall.length} package(s)...`);
|
|
75
|
-
await sync();
|
|
76
|
-
}
|
|
77
|
-
printDeprecatedPackagesInfo(result.packagesToRemove);
|
|
78
|
-
success(`
|
|
79
|
-
Safeword upgraded to v${VERSION}`);
|
|
67
|
+
printUpgradeSummary(result, projectVersion);
|
|
80
68
|
} catch (error_) {
|
|
81
69
|
error(`Upgrade failed: ${error_ instanceof Error ? error_.message : "Unknown error"}`);
|
|
82
70
|
process.exit(1);
|
|
@@ -85,4 +73,4 @@ Safeword upgraded to v${VERSION}`);
|
|
|
85
73
|
export {
|
|
86
74
|
upgrade
|
|
87
75
|
};
|
|
88
|
-
//# sourceMappingURL=upgrade-
|
|
76
|
+
//# sourceMappingURL=upgrade-K2FFESUH.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/upgrade.ts"],"sourcesContent":["/**\n * Upgrade command - Update safeword configuration to latest version\n *\n * Uses reconcile() with mode='upgrade' to update all managed files.\n */\n\nimport nodePath from 'node:path';\n\nimport { reconcile, type ReconcileResult } from '../reconcile.js';\nimport { SAFEWORD_SCHEMA } from '../schema.js';\nimport { createProjectContext } from '../utils/context.js';\nimport { exists, readFileSafe } from '../utils/fs.js';\nimport { error, header, info, listItem, success, warn } from '../utils/output.js';\nimport { compareVersions } from '../utils/version.js';\nimport { VERSION } from '../version.js';\n\nfunction getProjectVersion(safewordDirectory: string): string {\n const versionPath = nodePath.join(safewordDirectory, 'version');\n return readFileSafe(versionPath)?.trim() ?? '0.0.0';\n}\n\nfunction printUpgradeSummary(result: ReconcileResult, projectVersion: string): void {\n header('Upgrade Complete');\n info(`\\nVersion: v${projectVersion} → v${VERSION}`);\n\n if (result.created.length > 0) {\n info('\\nCreated:');\n for (const file of result.created) listItem(file);\n }\n\n if (result.updated.length > 0) {\n info('\\nUpdated:');\n for (const file of result.updated) listItem(file);\n }\n\n if (result.packagesToRemove.length > 0) {\n warn(`\\n${result.packagesToRemove.length} package(s) are now bundled in eslint-plugin-safeword:`);\n for (const pkg of result.packagesToRemove) listItem(pkg);\n info(\"\\nIf you don't use these elsewhere, you can remove them:\");\n listItem(`npm uninstall ${result.packagesToRemove.join(' ')}`);\n }\n\n success(`\\nSafeword upgraded to v${VERSION}`);\n}\n\nexport async function upgrade(): Promise<void> {\n const cwd = process.cwd();\n const safewordDirectory = nodePath.join(cwd, '.safeword');\n\n if (!exists(safewordDirectory)) {\n error('Not configured. Run `safeword setup` first.');\n process.exit(1);\n }\n\n const projectVersion = getProjectVersion(safewordDirectory);\n\n if (compareVersions(VERSION, projectVersion) < 0) {\n error(`CLI v${VERSION} is older than project v${projectVersion}.`);\n error('Update the CLI first: npm install -g safeword');\n process.exit(1);\n }\n\n header('Safeword Upgrade');\n info(`Upgrading from v${projectVersion} to v${VERSION}`);\n\n try {\n const ctx = createProjectContext(cwd);\n const result = await reconcile(SAFEWORD_SCHEMA, 'upgrade', ctx);\n printUpgradeSummary(result, projectVersion);\n } catch (error_) {\n error(`Upgrade failed: ${error_ instanceof Error ? error_.message : 'Unknown error'}`);\n process.exit(1);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAMA,OAAO,cAAc;AAUrB,SAAS,kBAAkB,mBAAmC;AAC5D,QAAM,cAAc,SAAS,KAAK,mBAAmB,SAAS;AAC9D,SAAO,aAAa,WAAW,GAAG,KAAK,KAAK;AAC9C;AAEA,SAAS,oBAAoB,QAAyB,gBAA8B;AAClF,SAAO,kBAAkB;AACzB,OAAK;AAAA,YAAe,cAAc,YAAO,OAAO,EAAE;AAElD,MAAI,OAAO,QAAQ,SAAS,GAAG;AAC7B,SAAK,YAAY;AACjB,eAAW,QAAQ,OAAO,QAAS,UAAS,IAAI;AAAA,EAClD;AAEA,MAAI,OAAO,QAAQ,SAAS,GAAG;AAC7B,SAAK,YAAY;AACjB,eAAW,QAAQ,OAAO,QAAS,UAAS,IAAI;AAAA,EAClD;AAEA,MAAI,OAAO,iBAAiB,SAAS,GAAG;AACtC,SAAK;AAAA,EAAK,OAAO,iBAAiB,MAAM,wDAAwD;AAChG,eAAW,OAAO,OAAO,iBAAkB,UAAS,GAAG;AACvD,SAAK,0DAA0D;AAC/D,aAAS,iBAAiB,OAAO,iBAAiB,KAAK,GAAG,CAAC,EAAE;AAAA,EAC/D;AAEA,UAAQ;AAAA,wBAA2B,OAAO,EAAE;AAC9C;AAEA,eAAsB,UAAyB;AAC7C,QAAM,MAAM,QAAQ,IAAI;AACxB,QAAM,oBAAoB,SAAS,KAAK,KAAK,WAAW;AAExD,MAAI,CAAC,OAAO,iBAAiB,GAAG;AAC9B,UAAM,6CAA6C;AACnD,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,iBAAiB,kBAAkB,iBAAiB;AAE1D,MAAI,gBAAgB,SAAS,cAAc,IAAI,GAAG;AAChD,UAAM,QAAQ,OAAO,2BAA2B,cAAc,GAAG;AACjE,UAAM,+CAA+C;AACrD,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,SAAO,kBAAkB;AACzB,OAAK,mBAAmB,cAAc,QAAQ,OAAO,EAAE;AAEvD,MAAI;AACF,UAAM,MAAM,qBAAqB,GAAG;AACpC,UAAM,SAAS,MAAM,UAAU,iBAAiB,WAAW,GAAG;AAC9D,wBAAoB,QAAQ,cAAc;AAAA,EAC5C,SAAS,QAAQ;AACf,UAAM,mBAAmB,kBAAkB,QAAQ,OAAO,UAAU,eAAe,EAAE;AACrF,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;","names":[]}
|
package/package.json
CHANGED
package/templates/SAFEWORD.md
CHANGED
|
@@ -86,6 +86,7 @@ Training data is stale. Follow this sequence:
|
|
|
86
86
|
| Test definitions | `.safeword/planning/test-definitions/` | `feature-*.md` (L2 features only) |
|
|
87
87
|
| Design docs | `.safeword/planning/design/` | Complex features (3+ components) |
|
|
88
88
|
| Issues | `.safeword/planning/issues/` | Issue tracking |
|
|
89
|
+
| Execution plans | `.safeword/planning/plans/` | LLM-ready task breakdowns |
|
|
89
90
|
|
|
90
91
|
**Artifact Levels:**
|
|
91
92
|
|
|
@@ -4,14 +4,13 @@ Commands for managing safeword in projects.
|
|
|
4
4
|
|
|
5
5
|
## Commands
|
|
6
6
|
|
|
7
|
-
| Command | Purpose
|
|
8
|
-
| ----------------------------- |
|
|
9
|
-
| `npx safeword@latest setup` | Install safeword in current project
|
|
10
|
-
| `npx safeword@latest check` | Check project health and versions
|
|
11
|
-
| `npx safeword@latest upgrade` | Upgrade to latest version
|
|
12
|
-
| `npx safeword@latest diff` | Preview changes before upgrading
|
|
13
|
-
| `npx safeword
|
|
14
|
-
| `npx safeword reset` | Remove safeword from project |
|
|
7
|
+
| Command | Purpose |
|
|
8
|
+
| ----------------------------- | --------------------------------- |
|
|
9
|
+
| `npx safeword@latest setup` | Install safeword in current project |
|
|
10
|
+
| `npx safeword@latest check` | Check project health and versions |
|
|
11
|
+
| `npx safeword@latest upgrade` | Upgrade to latest version |
|
|
12
|
+
| `npx safeword@latest diff` | Preview changes before upgrading |
|
|
13
|
+
| `npx safeword reset` | Remove safeword from project |
|
|
15
14
|
|
|
16
15
|
## When to Use
|
|
17
16
|
|
|
@@ -21,7 +20,6 @@ Commands for managing safeword in projects.
|
|
|
21
20
|
| Check if update available | `npx safeword@latest check` |
|
|
22
21
|
| Update after CLI release | `npx safeword@latest upgrade` |
|
|
23
22
|
| See what upgrade changes | `npx safeword@latest diff` |
|
|
24
|
-
| Added/removed framework | `npx safeword sync` |
|
|
25
23
|
| Remove safeword completely | `npx safeword reset --full` |
|
|
26
24
|
|
|
27
25
|
## Options
|
|
@@ -32,12 +30,12 @@ Common flags:
|
|
|
32
30
|
|
|
33
31
|
- `-y, --yes` - Skip confirmations (setup, reset)
|
|
34
32
|
- `-v, --verbose` - Show detailed output (diff)
|
|
35
|
-
-
|
|
33
|
+
- `--offline` - Skip remote version check (check)
|
|
34
|
+
- `--full` - Also remove linting config + packages (reset)
|
|
36
35
|
|
|
37
36
|
---
|
|
38
37
|
|
|
39
38
|
## Key Takeaways
|
|
40
39
|
|
|
41
40
|
- Always use `@latest` for setup/check/upgrade/diff to get current CLI
|
|
42
|
-
- Run `sync` after adding/removing frameworks to update linting plugins
|
|
43
41
|
- Use `diff` before `upgrade` to preview changes
|
package/dist/chunk-4URRFBUS.js
DELETED
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
detectProjectType,
|
|
3
|
-
exists,
|
|
4
|
-
getBaseEslintPackages,
|
|
5
|
-
getConditionalEslintPackages,
|
|
6
|
-
readJson
|
|
7
|
-
} from "./chunk-CLSGXTOL.js";
|
|
8
|
-
|
|
9
|
-
// src/commands/sync.ts
|
|
10
|
-
import { execSync } from "child_process";
|
|
11
|
-
import nodePath from "path";
|
|
12
|
-
function getRequiredPlugins(projectType) {
|
|
13
|
-
const plugins = [...getBaseEslintPackages()];
|
|
14
|
-
for (const [key, isActive] of Object.entries(projectType)) {
|
|
15
|
-
if (isActive) {
|
|
16
|
-
plugins.push(...getConditionalEslintPackages(key));
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
return plugins;
|
|
20
|
-
}
|
|
21
|
-
function getMissingPackages(required, installed) {
|
|
22
|
-
return required.filter((pkg) => !(pkg in installed));
|
|
23
|
-
}
|
|
24
|
-
async function sync(options = {}) {
|
|
25
|
-
const cwd = process.cwd();
|
|
26
|
-
const safewordDirectory = nodePath.join(cwd, ".safeword");
|
|
27
|
-
const packageJsonPath = nodePath.join(cwd, "package.json");
|
|
28
|
-
if (!exists(safewordDirectory)) {
|
|
29
|
-
if (!options.quiet) {
|
|
30
|
-
console.error("Not a safeword project. Run `safeword setup` first.");
|
|
31
|
-
}
|
|
32
|
-
process.exit(1);
|
|
33
|
-
}
|
|
34
|
-
if (!exists(packageJsonPath)) {
|
|
35
|
-
if (!options.quiet) {
|
|
36
|
-
console.error("No package.json found.");
|
|
37
|
-
}
|
|
38
|
-
process.exit(1);
|
|
39
|
-
}
|
|
40
|
-
const packageJson = readJson(packageJsonPath);
|
|
41
|
-
if (!packageJson) {
|
|
42
|
-
process.exit(1);
|
|
43
|
-
}
|
|
44
|
-
const projectType = detectProjectType(packageJson);
|
|
45
|
-
const developmentDeps = packageJson.devDependencies || {};
|
|
46
|
-
const requiredPlugins = getRequiredPlugins(projectType);
|
|
47
|
-
const missingPlugins = getMissingPackages(requiredPlugins, developmentDeps);
|
|
48
|
-
if (missingPlugins.length === 0) {
|
|
49
|
-
return;
|
|
50
|
-
}
|
|
51
|
-
if (!options.quiet) {
|
|
52
|
-
console.log(`Installing missing ESLint plugins: ${missingPlugins.join(", ")}`);
|
|
53
|
-
}
|
|
54
|
-
try {
|
|
55
|
-
execSync(`npm install -D ${missingPlugins.join(" ")}`, {
|
|
56
|
-
cwd,
|
|
57
|
-
stdio: options.quiet ? "pipe" : "inherit"
|
|
58
|
-
});
|
|
59
|
-
} catch (caughtError) {
|
|
60
|
-
const pluginList = missingPlugins.join(" ");
|
|
61
|
-
console.error(`
|
|
62
|
-
\u2717 Failed to install ESLint plugins
|
|
63
|
-
`);
|
|
64
|
-
console.error(`Your project needs: ${pluginList}`);
|
|
65
|
-
console.error(`
|
|
66
|
-
Run manually when online:`);
|
|
67
|
-
console.error(` npm install -D ${pluginList}
|
|
68
|
-
`);
|
|
69
|
-
throw caughtError;
|
|
70
|
-
}
|
|
71
|
-
if (options.stage) {
|
|
72
|
-
try {
|
|
73
|
-
execSync("git add package.json package-lock.json", {
|
|
74
|
-
cwd,
|
|
75
|
-
stdio: "pipe"
|
|
76
|
-
});
|
|
77
|
-
} catch {
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
if (!options.quiet) {
|
|
81
|
-
console.log(`\u2713 Installed ${missingPlugins.length} ESLint plugin(s)`);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
export {
|
|
86
|
-
sync
|
|
87
|
-
};
|
|
88
|
-
//# sourceMappingURL=chunk-4URRFBUS.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/commands/sync.ts"],"sourcesContent":["/**\n * Sync command - Keep linting plugins in sync with project dependencies\n *\n * Detects frameworks in package.json and ensures the corresponding ESLint plugins\n * are installed. Designed to be called from Husky pre-commit hook.\n *\n * Behavior:\n * - Fast exit when nothing needs to change\n * - Installs missing plugins\n * - Optionally stages modified files (--stage flag for pre-commit)\n * - Clear error message if installation fails\n */\n\nimport { execSync } from 'node:child_process';\nimport nodePath from 'node:path';\n\nimport { getBaseEslintPackages, getConditionalEslintPackages } from '../schema.js';\nimport { exists, readJson } from '../utils/fs.js';\nimport {\n detectProjectType,\n type PackageJson,\n type ProjectType,\n} from '../utils/project-detector.js';\n\nexport interface SyncOptions {\n quiet?: boolean;\n stage?: boolean;\n}\n\n/**\n * Get required ESLint packages based on project type.\n * Derives from schema - single source of truth, no separate list to maintain.\n * @param projectType\n */\nfunction getRequiredPlugins(projectType: ProjectType): string[] {\n const plugins: string[] = [...getBaseEslintPackages()];\n\n // Add conditional ESLint packages based on detected project type\n // Note: Next.js already sets react=true in project-detector.ts\n for (const [key, isActive] of Object.entries(projectType)) {\n if (isActive) {\n plugins.push(...getConditionalEslintPackages(key));\n }\n }\n\n return plugins;\n}\n\n/**\n * Check which packages are missing from devDependencies\n * @param required\n * @param installed\n */\nfunction getMissingPackages(required: string[], installed: Record<string, string>): string[] {\n return required.filter(pkg => !(pkg in installed));\n}\n\n/**\n * Sync linting configuration with current project dependencies\n * @param options\n */\nexport async function sync(options: SyncOptions = {}): Promise<void> {\n const cwd = process.cwd();\n const safewordDirectory = nodePath.join(cwd, '.safeword');\n const packageJsonPath = nodePath.join(cwd, 'package.json');\n\n // Must be in a safeword project\n if (!exists(safewordDirectory)) {\n if (!options.quiet) {\n console.error('Not a safeword project. Run `safeword setup` first.');\n }\n process.exit(1);\n }\n\n if (!exists(packageJsonPath)) {\n if (!options.quiet) {\n console.error('No package.json found.');\n }\n process.exit(1);\n }\n\n const packageJson = readJson<PackageJson>(packageJsonPath);\n if (!packageJson) {\n process.exit(1);\n }\n\n // Detect current project type\n const projectType = detectProjectType(packageJson);\n const developmentDeps = packageJson.devDependencies || {};\n\n // Check for missing plugins\n const requiredPlugins = getRequiredPlugins(projectType);\n const missingPlugins = getMissingPackages(requiredPlugins, developmentDeps);\n\n // Fast exit if nothing to install\n if (missingPlugins.length === 0) {\n return;\n }\n\n // Install missing plugins\n if (!options.quiet) {\n console.log(`Installing missing ESLint plugins: ${missingPlugins.join(', ')}`);\n }\n\n try {\n execSync(`npm install -D ${missingPlugins.join(' ')}`, {\n cwd,\n stdio: options.quiet ? 'pipe' : 'inherit',\n });\n } catch (caughtError) {\n // Clear error message for network/install failures\n const pluginList = missingPlugins.join(' ');\n console.error(`\\n✗ Failed to install ESLint plugins\\n`);\n console.error(`Your project needs: ${pluginList}`);\n console.error(`\\nRun manually when online:`);\n console.error(` npm install -D ${pluginList}\\n`);\n throw caughtError;\n }\n\n // Stage modified files if --stage flag is set (for pre-commit hook)\n if (options.stage) {\n try {\n execSync('git add package.json package-lock.json', {\n cwd,\n stdio: 'pipe',\n });\n } catch {\n // Not in a git repo or git add failed - ignore\n }\n }\n\n if (!options.quiet) {\n console.log(`✓ Installed ${missingPlugins.length} ESLint plugin(s)`);\n }\n}\n"],"mappings":";;;;;;;;;AAaA,SAAS,gBAAgB;AACzB,OAAO,cAAc;AAoBrB,SAAS,mBAAmB,aAAoC;AAC9D,QAAM,UAAoB,CAAC,GAAG,sBAAsB,CAAC;AAIrD,aAAW,CAAC,KAAK,QAAQ,KAAK,OAAO,QAAQ,WAAW,GAAG;AACzD,QAAI,UAAU;AACZ,cAAQ,KAAK,GAAG,6BAA6B,GAAG,CAAC;AAAA,IACnD;AAAA,EACF;AAEA,SAAO;AACT;AAOA,SAAS,mBAAmB,UAAoB,WAA6C;AAC3F,SAAO,SAAS,OAAO,SAAO,EAAE,OAAO,UAAU;AACnD;AAMA,eAAsB,KAAK,UAAuB,CAAC,GAAkB;AACnE,QAAM,MAAM,QAAQ,IAAI;AACxB,QAAM,oBAAoB,SAAS,KAAK,KAAK,WAAW;AACxD,QAAM,kBAAkB,SAAS,KAAK,KAAK,cAAc;AAGzD,MAAI,CAAC,OAAO,iBAAiB,GAAG;AAC9B,QAAI,CAAC,QAAQ,OAAO;AAClB,cAAQ,MAAM,qDAAqD;AAAA,IACrE;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,MAAI,CAAC,OAAO,eAAe,GAAG;AAC5B,QAAI,CAAC,QAAQ,OAAO;AAClB,cAAQ,MAAM,wBAAwB;AAAA,IACxC;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,cAAc,SAAsB,eAAe;AACzD,MAAI,CAAC,aAAa;AAChB,YAAQ,KAAK,CAAC;AAAA,EAChB;AAGA,QAAM,cAAc,kBAAkB,WAAW;AACjD,QAAM,kBAAkB,YAAY,mBAAmB,CAAC;AAGxD,QAAM,kBAAkB,mBAAmB,WAAW;AACtD,QAAM,iBAAiB,mBAAmB,iBAAiB,eAAe;AAG1E,MAAI,eAAe,WAAW,GAAG;AAC/B;AAAA,EACF;AAGA,MAAI,CAAC,QAAQ,OAAO;AAClB,YAAQ,IAAI,sCAAsC,eAAe,KAAK,IAAI,CAAC,EAAE;AAAA,EAC/E;AAEA,MAAI;AACF,aAAS,kBAAkB,eAAe,KAAK,GAAG,CAAC,IAAI;AAAA,MACrD;AAAA,MACA,OAAO,QAAQ,QAAQ,SAAS;AAAA,IAClC,CAAC;AAAA,EACH,SAAS,aAAa;AAEpB,UAAM,aAAa,eAAe,KAAK,GAAG;AAC1C,YAAQ,MAAM;AAAA;AAAA,CAAwC;AACtD,YAAQ,MAAM,uBAAuB,UAAU,EAAE;AACjD,YAAQ,MAAM;AAAA,0BAA6B;AAC3C,YAAQ,MAAM,oBAAoB,UAAU;AAAA,CAAI;AAChD,UAAM;AAAA,EACR;AAGA,MAAI,QAAQ,OAAO;AACjB,QAAI;AACF,eAAS,0CAA0C;AAAA,QACjD;AAAA,QACA,OAAO;AAAA,MACT,CAAC;AAAA,IACH,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,MAAI,CAAC,QAAQ,OAAO;AAClB,YAAQ,IAAI,oBAAe,eAAe,MAAM,mBAAmB;AAAA,EACrE;AACF;","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils/fs.ts","../src/templates/config.ts","../src/templates/content.ts","../src/utils/hooks.ts","../src/utils/install.ts","../src/schema.ts","../src/utils/project-detector.ts"],"sourcesContent":["/**\n * File system utilities for CLI operations\n */\n\nimport {\n chmodSync,\n existsSync,\n mkdirSync,\n readdirSync,\n readFileSync,\n rmdirSync,\n rmSync,\n writeFileSync,\n} from 'node:fs';\nimport nodePath from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\n// Get the directory of this module (for locating templates)\nconst __dirname = nodePath.dirname(fileURLToPath(import.meta.url));\n\n/**\n * Get path to bundled templates directory.\n * Works in both development (src/) and production (dist/) contexts.\n *\n * Note: We check for SAFEWORD.md to distinguish from src/templates/ which\n * contains TypeScript source files (config.ts, content.ts).\n *\n * Path resolution (bundled with tsup):\n * - From dist/chunk-*.js: __dirname = packages/cli/dist/ → ../templates\n */\nexport function getTemplatesDirectory(): string {\n const knownTemplateFile = 'SAFEWORD.md';\n\n // Try different relative paths - the bundled code ends up in dist/ directly (flat)\n // while source is in src/utils/\n const candidates = [\n nodePath.join(__dirname, '..', 'templates'), // From dist/ (flat bundled)\n nodePath.join(__dirname, '..', '..', 'templates'), // From src/utils/ or dist/utils/\n nodePath.join(__dirname, 'templates'), // Direct sibling (unlikely but safe)\n ];\n\n for (const candidate of candidates) {\n if (existsSync(nodePath.join(candidate, knownTemplateFile))) {\n return candidate;\n }\n }\n\n throw new Error('Templates directory not found');\n}\n\n/**\n * Check if a path exists\n * @param path\n */\nexport function exists(path: string): boolean {\n return existsSync(path);\n}\n\n/**\n * Create directory recursively\n * @param path\n */\nexport function ensureDirectory(path: string): void {\n if (!existsSync(path)) {\n mkdirSync(path, { recursive: true });\n }\n}\n\n/**\n * Read file as string\n * @param path\n */\nexport function readFile(path: string): string {\n return readFileSync(path, 'utf8');\n}\n\n/**\n * Read file as string, return null if not exists\n * @param path\n */\nexport function readFileSafe(path: string): string | undefined {\n if (!existsSync(path)) return undefined;\n return readFileSync(path, 'utf8');\n}\n\n/**\n * Write file, creating parent directories if needed\n * @param path\n * @param content\n */\nexport function writeFile(path: string, content: string): void {\n ensureDirectory(nodePath.dirname(path));\n writeFileSync(path, content);\n}\n\n/**\n * Remove file or directory recursively\n * @param path\n */\nexport function remove(path: string): void {\n if (existsSync(path)) {\n rmSync(path, { recursive: true, force: true });\n }\n}\n\n/**\n * Remove directory only if empty, returns true if removed\n * @param path\n */\nexport function removeIfEmpty(path: string): boolean {\n if (!existsSync(path)) return false;\n try {\n rmdirSync(path); // Non-recursive, throws if not empty\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Make all shell scripts in a directory executable\n * @param dirPath\n */\nexport function makeScriptsExecutable(dirPath: string): void {\n if (!existsSync(dirPath)) return;\n for (const file of readdirSync(dirPath)) {\n if (file.endsWith('.sh')) {\n chmodSync(nodePath.join(dirPath, file), 0o755);\n }\n }\n}\n\n/**\n * Read JSON file\n * @param path\n */\nexport function readJson(path: string): unknown {\n const content = readFileSafe(path);\n if (!content) return undefined;\n try {\n return JSON.parse(content) as unknown;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Write JSON file with formatting\n * @param path\n * @param data\n */\nexport function writeJson(path: string, data: unknown): void {\n writeFile(path, `${JSON.stringify(data, undefined, 2)}\\n`);\n}\n","/**\n * Configuration templates - ESLint config generation and hook settings\n *\n * ESLint flat config (v9+) using eslint-plugin-safeword for all rules.\n * Framework detection from package.json at runtime selects the appropriate config.\n *\n * See: https://eslint.org/docs/latest/use/configure/configuration-files\n */\n\n/**\n * Generates an ESLint config using eslint-plugin-safeword.\n *\n * The generated config reads package.json to detect frameworks and selects\n * the appropriate safeword config. Dynamic imports handle frameworks not\n * yet in the safeword plugin (Vue, Svelte, Electron).\n * @returns ESLint config file content as a string\n */\nexport function getEslintConfig(): string {\n return `/* eslint-disable import-x/no-unresolved, no-undef -- dynamic imports for optional framework plugins */\nimport { readFileSync } from \"fs\";\nimport { dirname, join } from \"path\";\nimport { fileURLToPath } from \"url\";\nimport safeword from \"eslint-plugin-safeword\";\nimport eslintConfigPrettier from \"eslint-config-prettier\";\n\n// Read package.json relative to this config file (not CWD)\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst pkg = JSON.parse(readFileSync(join(__dirname, \"package.json\"), \"utf8\"));\nconst deps = { ...pkg.dependencies, ...pkg.devDependencies };\n\n// Helper for dynamic imports with actionable error messages\nasync function tryImport(pkgName, frameworkName) {\n try {\n return await import(pkgName);\n } catch (err) {\n if (err.code === \"ERR_MODULE_NOT_FOUND\") {\n console.error(\\`\\\\n✗ Missing ESLint plugin for \\${frameworkName}\\\\n\\`);\n console.error(\\`Your package.json has \\${frameworkName} but the ESLint plugin is not installed.\\`);\n console.error(\\`Run: npm install -D \\${pkgName}\\\\n\\`);\n console.error(\\`Or run: npx safeword sync\\\\n\\`);\n }\n throw err;\n }\n}\n\n// Build dynamic ignores based on detected frameworks\nconst ignores = [\"**/node_modules/\", \"**/dist/\", \"**/build/\", \"**/coverage/\"];\nif (deps[\"next\"]) ignores.push(\".next/\");\nif (deps[\"astro\"]) ignores.push(\".astro/\");\nif (deps[\"vue\"] || deps[\"nuxt\"]) ignores.push(\".nuxt/\");\nif (deps[\"svelte\"] || deps[\"@sveltejs/kit\"]) ignores.push(\".svelte-kit/\");\n\n// Select appropriate safeword config based on detected framework\n// Order matters: most specific first\nlet baseConfig;\nif (deps[\"next\"]) {\n baseConfig = safeword.configs.recommendedTypeScriptNext;\n} else if (deps[\"react\"]) {\n baseConfig = safeword.configs.recommendedTypeScriptReact;\n} else if (deps[\"astro\"]) {\n baseConfig = safeword.configs.astro;\n} else if (deps[\"typescript\"] || deps[\"typescript-eslint\"]) {\n baseConfig = safeword.configs.recommendedTypeScript;\n} else {\n baseConfig = safeword.configs.recommended;\n}\n\n// Start with ignores + safeword config\nconst configs = [\n { ignores },\n ...baseConfig,\n];\n\n// Add test configs if testing frameworks detected\nif (deps[\"vitest\"]) {\n configs.push(...safeword.configs.vitest);\n}\nif (deps[\"playwright\"] || deps[\"@playwright/test\"]) {\n configs.push(...safeword.configs.playwright);\n}\n\n// Frameworks NOT in eslint-plugin-safeword (dynamic imports)\nif (deps[\"vue\"] || deps[\"nuxt\"]) {\n const vue = await tryImport(\"eslint-plugin-vue\", \"Vue\");\n configs.push(...vue.default.configs[\"flat/recommended\"]);\n}\n\nif (deps[\"svelte\"] || deps[\"@sveltejs/kit\"]) {\n const svelte = await tryImport(\"eslint-plugin-svelte\", \"Svelte\");\n configs.push(...svelte.default.configs.recommended);\n}\n\nif (deps[\"electron\"]) {\n const electron = await tryImport(\"@electron-toolkit/eslint-config\", \"Electron\");\n configs.push(electron.default);\n}\n\n// eslint-config-prettier must be last to disable conflicting rules\nconfigs.push(eslintConfigPrettier);\n\nexport default configs;\n`;\n}\n\n// Cursor hooks configuration (.cursor/hooks.json format)\n// See: https://cursor.com/docs/agent/hooks\nexport const CURSOR_HOOKS = {\n afterFileEdit: [{ command: './.safeword/hooks/cursor/after-file-edit.sh' }],\n stop: [{ command: './.safeword/hooks/cursor/stop.sh' }],\n};\n\n// Claude Code hooks configuration (.claude/settings.json format)\nexport const SETTINGS_HOOKS = {\n SessionStart: [\n {\n hooks: [\n {\n type: 'command',\n command: '\"$CLAUDE_PROJECT_DIR\"/.safeword/hooks/session-verify-agents.sh',\n },\n ],\n },\n {\n hooks: [\n {\n type: 'command',\n command: '\"$CLAUDE_PROJECT_DIR\"/.safeword/hooks/session-version.sh',\n },\n ],\n },\n {\n hooks: [\n {\n type: 'command',\n command: '\"$CLAUDE_PROJECT_DIR\"/.safeword/hooks/session-lint-check.sh',\n },\n ],\n },\n ],\n UserPromptSubmit: [\n {\n hooks: [\n {\n type: 'command',\n command: '\"$CLAUDE_PROJECT_DIR\"/.safeword/hooks/prompt-timestamp.sh',\n },\n ],\n },\n {\n hooks: [\n {\n type: 'command',\n command: '\"$CLAUDE_PROJECT_DIR\"/.safeword/hooks/prompt-questions.sh',\n },\n ],\n },\n ],\n Stop: [\n {\n hooks: [\n {\n type: 'command',\n command: '\"$CLAUDE_PROJECT_DIR\"/.safeword/hooks/stop-quality.sh',\n },\n ],\n },\n ],\n PostToolUse: [\n {\n matcher: 'Write|Edit|MultiEdit|NotebookEdit',\n hooks: [\n {\n type: 'command',\n command: '\"$CLAUDE_PROJECT_DIR\"/.safeword/hooks/post-tool-lint.sh',\n },\n ],\n },\n ],\n};\n","/**\n * Content templates - static string content\n *\n * Note: Most templates (SAFEWORD.md, hooks, skills, guides, etc.) are now\n * file-based in the templates/ directory. This file contains only small\n * string constants that are used inline.\n */\n\nimport type { ProjectType } from '../utils/project-detector.js';\n\nexport const AGENTS_MD_LINK = `**⚠️ ALWAYS READ FIRST:** \\`.safeword/SAFEWORD.md\\`\n\nThe SAFEWORD.md file contains core development patterns, workflows, and conventions.\nRead it BEFORE working on any task in this project.\n\n---`;\n\ninterface PrettierConfig {\n semi: boolean;\n singleQuote: boolean;\n tabWidth: number;\n trailingComma: string;\n printWidth: number;\n endOfLine: string;\n useTabs: boolean;\n bracketSpacing: boolean;\n arrowParens: string;\n plugins?: string[];\n}\n\n/**\n * Generate .prettierrc content based on project type.\n * Explicitly lists plugins to ensure compatibility with pnpm/Yarn PnP.\n * @param projectType\n */\nexport function getPrettierConfig(projectType: ProjectType): string {\n const config: PrettierConfig = {\n semi: true,\n singleQuote: true,\n tabWidth: 2,\n trailingComma: 'all',\n printWidth: 100,\n endOfLine: 'lf',\n useTabs: false,\n bracketSpacing: true,\n arrowParens: 'avoid',\n };\n\n const plugins: string[] = [];\n\n if (projectType.astro) plugins.push('prettier-plugin-astro');\n if (projectType.svelte) plugins.push('prettier-plugin-svelte');\n if (projectType.shell) plugins.push('prettier-plugin-sh');\n // Tailwind must be last for proper class sorting\n if (projectType.tailwind) plugins.push('prettier-plugin-tailwindcss');\n\n if (plugins.length > 0) {\n config.plugins = plugins;\n }\n\n return `${JSON.stringify(config, undefined, 2)}\\n`;\n}\n\n/**\n * Generate lint-staged configuration based on project type.\n * Only includes shell patterns when shell scripts are detected.\n *\n * SYNC: Keep file patterns in sync with post-tool-lint.sh in:\n * packages/cli/templates/hooks/post-tool-lint.sh\n * @param projectType\n */\nexport function getLintStagedConfig(projectType: ProjectType): Record<string, string[]> {\n const config: Record<string, string[]> = {\n '*.{js,jsx,ts,tsx,mjs,mts,cjs,cts}': ['eslint --fix', 'prettier --write'],\n '*.{vue,svelte,astro}': ['eslint --fix', 'prettier --write'],\n '*.{json,css,scss,html,yaml,yml,graphql}': ['prettier --write'],\n '*.md': ['markdownlint-cli2 --fix', 'prettier --write'],\n };\n\n if (projectType.shell) {\n config['*.sh'] = ['shellcheck', 'prettier --write'];\n }\n\n return config;\n}\n","/**\n * Hook utilities for Claude Code settings\n */\n\ninterface HookCommand {\n type: string;\n command: string;\n}\n\ninterface HookEntry {\n matcher?: string;\n hooks: HookCommand[];\n}\n\n/**\n * Type guard to check if a value is a hook entry with hooks array\n * @param h\n */\nexport function isHookEntry(h: unknown): h is HookEntry {\n return (\n typeof h === 'object' &&\n h !== undefined &&\n 'hooks' in h &&\n Array.isArray((h as HookEntry).hooks)\n );\n}\n\n/**\n * Check if a hook entry contains a safeword hook (command contains '.safeword')\n * @param h\n */\nexport function isSafewordHook(h: unknown): boolean {\n if (!isHookEntry(h)) return false;\n return h.hooks.some(cmd => typeof cmd.command === 'string' && cmd.command.includes('.safeword'));\n}\n\n/**\n * Filter out safeword hooks from an array of hook entries\n * @param hooks\n */\nexport function filterOutSafewordHooks(hooks: unknown[]): unknown[] {\n return hooks.filter(h => !isSafewordHook(h));\n}\n","/**\n * Shared installation constants\n *\n * These constants are used by schema.ts to define the single source of truth.\n * All functions have been removed - reconcile.ts now handles all operations.\n */\n\n/**\n * Husky pre-commit hook content - sync + lint-staged\n * This is prepended to existing hooks, preserving user customizations\n */\nexport const HUSKY_PRE_COMMIT_CONTENT =\n '# safeword:pre-commit\\nnpx safeword sync --quiet --stage\\nnpx lint-staged\\n';\n\n/**\n * MCP servers installed by safeword\n */\nexport const MCP_SERVERS = {\n context7: {\n command: 'npx',\n args: ['-y', '@upstash/context7-mcp@latest'],\n },\n playwright: {\n command: 'npx',\n args: ['@playwright/mcp@latest'],\n },\n} as const;\n\n// NOTE: All other constants and functions were removed in the declarative schema refactor.\n// The single source of truth is now SAFEWORD_SCHEMA in src/schema.ts.\n// Operations are handled by reconcile() in src/reconcile.ts.\n","/**\n * SAFEWORD Schema - Single Source of Truth\n *\n * All files, directories, configurations, and packages managed by safeword\n * are defined here. Commands use this schema via the reconciliation engine.\n *\n * Adding a new file? Add it here and it will be handled by setup/upgrade/reset.\n */\n\nimport { CURSOR_HOOKS, getEslintConfig, SETTINGS_HOOKS } from './templates/config.js';\nimport { AGENTS_MD_LINK, getPrettierConfig } from './templates/content.js';\nimport { filterOutSafewordHooks } from './utils/hooks.js';\nimport { MCP_SERVERS } from './utils/install.js';\nimport { type ProjectType } from './utils/project-detector.js';\nimport { VERSION } from './version.js';\n\n// ============================================================================\n// Interfaces\n// ============================================================================\n\nexport interface ProjectContext {\n cwd: string;\n projectType: ProjectType;\n developmentDeps: Record<string, string>;\n isGitRepo: boolean;\n}\n\nexport interface FileDefinition {\n template?: string; // Path in templates/ dir\n content?: string | (() => string); // Static content or factory\n generator?: (ctx: ProjectContext) => string; // Dynamic generator needing context\n}\n\n// managedFiles: created if missing, updated only if content === current template output\nexport type ManagedFileDefinition = FileDefinition;\n\nexport interface JsonMergeDefinition {\n keys: string[]; // Dot-notation keys we manage\n conditionalKeys?: Record<string, string[]>; // Keys added based on project type\n merge: (existing: Record<string, unknown>, ctx: ProjectContext) => Record<string, unknown>;\n unmerge: (existing: Record<string, unknown>) => Record<string, unknown>;\n removeFileIfEmpty?: boolean; // Delete file if our keys were the only content\n}\n\nexport interface TextPatchDefinition {\n operation: 'prepend' | 'append';\n content: string;\n marker: string; // Used to detect if already applied & for removal\n createIfMissing: boolean;\n}\n\nexport interface SafewordSchema {\n version: string;\n ownedDirs: string[]; // Fully owned - create on setup, delete on reset\n sharedDirs: string[]; // We add to but don't own\n preservedDirs: string[]; // Created on setup, NOT deleted on reset (user data)\n deprecatedFiles: string[]; // Files to delete on upgrade (renamed or removed)\n deprecatedPackages: string[]; // Packages to uninstall on upgrade (consolidated into safeword plugin)\n deprecatedDirs: string[]; // Directories to delete on upgrade (no longer managed)\n ownedFiles: Record<string, FileDefinition>; // Overwrite on upgrade (if changed)\n managedFiles: Record<string, ManagedFileDefinition>; // Create if missing, update if safeword content\n jsonMerges: Record<string, JsonMergeDefinition>;\n textPatches: Record<string, TextPatchDefinition>;\n packages: {\n base: string[];\n conditional: Record<string, string[]>;\n };\n}\n\n// ============================================================================\n// SAFEWORD_SCHEMA - The Single Source of Truth\n// ============================================================================\n\n/**\n * Check if a package name is an ESLint-related package.\n * Used by sync command to filter packages for pre-commit installation.\n * @param pkg\n */\nfunction isEslintPackage(pkg: string): boolean {\n return (\n pkg.startsWith('eslint') ||\n pkg.startsWith('@eslint/') ||\n pkg.startsWith('@microsoft/eslint') ||\n pkg.startsWith('@next/eslint') ||\n pkg.startsWith('@vitest/eslint') ||\n pkg.startsWith('@electron-toolkit/eslint') ||\n pkg === 'typescript-eslint'\n );\n}\n\n/**\n * Get ESLint packages from schema base packages.\n * Single source of truth - no separate list to maintain.\n */\nexport function getBaseEslintPackages(): string[] {\n return SAFEWORD_SCHEMA.packages.base.filter(pkg => isEslintPackage(pkg));\n}\n\n/**\n * Get conditional ESLint packages for a specific project type key.\n * @param key\n */\nexport function getConditionalEslintPackages(key: string): string[] {\n const deps = SAFEWORD_SCHEMA.packages.conditional[key];\n return deps ? deps.filter(pkg => isEslintPackage(pkg)) : [];\n}\n\nexport const SAFEWORD_SCHEMA: SafewordSchema = {\n version: VERSION,\n\n // Directories fully owned by safeword (created on setup, deleted on reset)\n ownedDirs: [\n '.safeword',\n '.safeword/hooks',\n '.safeword/hooks/cursor',\n '.safeword/lib',\n '.safeword/guides',\n '.safeword/templates',\n '.safeword/prompts',\n '.safeword/planning',\n '.safeword/planning/specs',\n '.safeword/planning/test-definitions',\n '.safeword/planning/design',\n '.safeword/planning/issues',\n '.safeword/planning/plans',\n '.safeword/scripts',\n '.cursor',\n '.cursor/rules',\n '.cursor/commands',\n ],\n\n // Directories we add to but don't own (not deleted on reset)\n sharedDirs: ['.claude', '.claude/skills', '.claude/commands'],\n\n // Created on setup but NOT deleted on reset (preserves user data)\n preservedDirs: [\n '.safeword/learnings',\n '.safeword/tickets',\n '.safeword/tickets/completed',\n '.safeword/logs',\n ],\n\n // Files to delete on upgrade (renamed or removed in newer versions)\n deprecatedFiles: [\n '.safeword/templates/user-stories-template.md',\n // Consolidated into planning-guide.md and testing-guide.md (v0.8.0)\n '.safeword/guides/development-workflow.md',\n '.safeword/guides/tdd-best-practices.md',\n '.safeword/guides/user-story-guide.md',\n '.safeword/guides/test-definitions-guide.md',\n // Boundaries config now project-specific (v0.9.0)\n '.safeword/eslint-boundaries.config.mjs',\n ],\n\n // Packages to uninstall on upgrade (consolidated into eslint-plugin-safeword v0.9.0)\n deprecatedPackages: [\n // Individual ESLint plugins now bundled in eslint-plugin-safeword\n '@eslint/js',\n 'eslint-plugin-import-x',\n 'eslint-import-resolver-typescript',\n 'eslint-plugin-sonarjs',\n 'eslint-plugin-unicorn',\n 'eslint-plugin-boundaries',\n 'eslint-plugin-playwright',\n 'eslint-plugin-promise',\n 'eslint-plugin-regexp',\n 'eslint-plugin-jsdoc',\n 'eslint-plugin-simple-import-sort',\n 'eslint-plugin-security',\n // Conditional ESLint plugins now in safeword\n 'typescript-eslint',\n 'eslint-plugin-react',\n 'eslint-plugin-react-hooks',\n 'eslint-plugin-jsx-a11y',\n '@next/eslint-plugin-next',\n 'eslint-plugin-astro',\n '@vitest/eslint-plugin',\n // Pre-commit hooks no longer managed by safeword\n 'husky',\n 'lint-staged',\n ],\n\n // Directories to delete on upgrade (no longer managed by safeword)\n deprecatedDirs: [\n '.husky', // Pre-commit hooks no longer managed by safeword\n ],\n\n // Files owned by safeword (overwritten on upgrade if content changed)\n ownedFiles: {\n // Core files\n '.safeword/SAFEWORD.md': { template: 'SAFEWORD.md' },\n '.safeword/version': { content: () => VERSION },\n\n // Hooks (7 files)\n '.safeword/hooks/session-verify-agents.sh': { template: 'hooks/session-verify-agents.sh' },\n '.safeword/hooks/session-version.sh': { template: 'hooks/session-version.sh' },\n '.safeword/hooks/session-lint-check.sh': { template: 'hooks/session-lint-check.sh' },\n '.safeword/hooks/prompt-timestamp.sh': { template: 'hooks/prompt-timestamp.sh' },\n '.safeword/hooks/prompt-questions.sh': { template: 'hooks/prompt-questions.sh' },\n '.safeword/hooks/post-tool-lint.sh': { template: 'hooks/post-tool-lint.sh' },\n '.safeword/hooks/stop-quality.sh': { template: 'hooks/stop-quality.sh' },\n\n // Lib (2 files)\n '.safeword/lib/common.sh': { template: 'lib/common.sh' },\n '.safeword/lib/jq-fallback.sh': { template: 'lib/jq-fallback.sh' },\n\n // Guides (11 files)\n '.safeword/guides/architecture-guide.md': { template: 'guides/architecture-guide.md' },\n '.safeword/guides/cli-reference.md': { template: 'guides/cli-reference.md' },\n '.safeword/guides/code-philosophy.md': { template: 'guides/code-philosophy.md' },\n '.safeword/guides/context-files-guide.md': { template: 'guides/context-files-guide.md' },\n '.safeword/guides/data-architecture-guide.md': {\n template: 'guides/data-architecture-guide.md',\n },\n '.safeword/guides/design-doc-guide.md': { template: 'guides/design-doc-guide.md' },\n '.safeword/guides/learning-extraction.md': { template: 'guides/learning-extraction.md' },\n '.safeword/guides/llm-guide.md': { template: 'guides/llm-guide.md' },\n '.safeword/guides/planning-guide.md': { template: 'guides/planning-guide.md' },\n '.safeword/guides/testing-guide.md': { template: 'guides/testing-guide.md' },\n '.safeword/guides/zombie-process-cleanup.md': { template: 'guides/zombie-process-cleanup.md' },\n\n // Templates (7 files)\n '.safeword/templates/architecture-template.md': {\n template: 'doc-templates/architecture-template.md',\n },\n '.safeword/templates/design-doc-template.md': {\n template: 'doc-templates/design-doc-template.md',\n },\n '.safeword/templates/task-spec-template.md': {\n template: 'doc-templates/task-spec-template.md',\n },\n '.safeword/templates/test-definitions-feature.md': {\n template: 'doc-templates/test-definitions-feature.md',\n },\n '.safeword/templates/ticket-template.md': { template: 'doc-templates/ticket-template.md' },\n '.safeword/templates/feature-spec-template.md': {\n template: 'doc-templates/feature-spec-template.md',\n },\n '.safeword/templates/work-log-template.md': { template: 'doc-templates/work-log-template.md' },\n\n // Prompts (2 files)\n '.safeword/prompts/architecture.md': { template: 'prompts/architecture.md' },\n '.safeword/prompts/quality-review.md': { template: 'prompts/quality-review.md' },\n\n // Scripts (4 files)\n '.safeword/scripts/bisect-test-pollution.sh': { template: 'scripts/bisect-test-pollution.sh' },\n '.safeword/scripts/bisect-zombie-processes.sh': {\n template: 'scripts/bisect-zombie-processes.sh',\n },\n '.safeword/scripts/cleanup-zombies.sh': { template: 'scripts/cleanup-zombies.sh' },\n '.safeword/scripts/lint-md.sh': { template: 'scripts/lint-md.sh' },\n\n // Claude skills and commands (9 files)\n '.claude/skills/safeword-brainstorming/SKILL.md': {\n template: 'skills/safeword-brainstorming/SKILL.md',\n },\n '.claude/skills/safeword-debugging/SKILL.md': {\n template: 'skills/safeword-debugging/SKILL.md',\n },\n '.claude/skills/safeword-enforcing-tdd/SKILL.md': {\n template: 'skills/safeword-enforcing-tdd/SKILL.md',\n },\n '.claude/skills/safeword-quality-reviewer/SKILL.md': {\n template: 'skills/safeword-quality-reviewer/SKILL.md',\n },\n '.claude/skills/safeword-refactoring/SKILL.md': {\n template: 'skills/safeword-refactoring/SKILL.md',\n },\n '.claude/skills/safeword-writing-plans/SKILL.md': {\n template: 'skills/safeword-writing-plans/SKILL.md',\n },\n '.claude/commands/architecture.md': { template: 'commands/architecture.md' },\n '.claude/commands/cleanup-zombies.md': { template: 'commands/cleanup-zombies.md' },\n '.claude/commands/lint.md': { template: 'commands/lint.md' },\n '.claude/commands/quality-review.md': { template: 'commands/quality-review.md' },\n\n // Cursor rules (7 files)\n '.cursor/rules/safeword-core.mdc': { template: 'cursor/rules/safeword-core.mdc' },\n '.cursor/rules/safeword-brainstorming.mdc': {\n template: 'cursor/rules/safeword-brainstorming.mdc',\n },\n '.cursor/rules/safeword-debugging.mdc': {\n template: 'cursor/rules/safeword-debugging.mdc',\n },\n '.cursor/rules/safeword-enforcing-tdd.mdc': {\n template: 'cursor/rules/safeword-enforcing-tdd.mdc',\n },\n '.cursor/rules/safeword-quality-reviewer.mdc': {\n template: 'cursor/rules/safeword-quality-reviewer.mdc',\n },\n '.cursor/rules/safeword-refactoring.mdc': {\n template: 'cursor/rules/safeword-refactoring.mdc',\n },\n '.cursor/rules/safeword-writing-plans.mdc': {\n template: 'cursor/rules/safeword-writing-plans.mdc',\n },\n\n // Cursor commands (4 files - same as Claude)\n '.cursor/commands/architecture.md': { template: 'commands/architecture.md' },\n '.cursor/commands/cleanup-zombies.md': { template: 'commands/cleanup-zombies.md' },\n '.cursor/commands/lint.md': { template: 'commands/lint.md' },\n '.cursor/commands/quality-review.md': { template: 'commands/quality-review.md' },\n\n // Cursor hooks adapters (2 files)\n '.safeword/hooks/cursor/after-file-edit.sh': { template: 'hooks/cursor/after-file-edit.sh' },\n '.safeword/hooks/cursor/stop.sh': { template: 'hooks/cursor/stop.sh' },\n },\n\n // Files created if missing, updated only if content matches current template\n managedFiles: {\n 'eslint.config.mjs': {\n generator: () => getEslintConfig(),\n },\n '.prettierrc': { generator: ctx => getPrettierConfig(ctx.projectType) },\n '.markdownlint-cli2.jsonc': { template: 'markdownlint-cli2.jsonc' },\n // Minimal tsconfig for ESLint type-checked linting (only if missing)\n 'tsconfig.json': {\n generator: ctx => {\n // Only create for TypeScript projects\n if (!ctx.developmentDeps.typescript && !ctx.developmentDeps['typescript-eslint']) {\n return ''; // Empty = skip this file\n }\n return JSON.stringify(\n {\n compilerOptions: {\n target: 'ES2022',\n module: 'NodeNext',\n moduleResolution: 'NodeNext',\n strict: true,\n esModuleInterop: true,\n skipLibCheck: true,\n noEmit: true,\n },\n include: ['**/*.ts', '**/*.tsx'],\n exclude: ['node_modules', 'dist', 'build'],\n },\n undefined,\n 2,\n );\n },\n },\n },\n\n // JSON files where we merge specific keys\n jsonMerges: {\n 'package.json': {\n keys: [\n 'scripts.lint',\n 'scripts.lint:md',\n 'scripts.format',\n 'scripts.format:check',\n 'scripts.knip',\n ],\n conditionalKeys: {\n publishableLibrary: ['scripts.publint'],\n shell: ['scripts.lint:sh'],\n },\n merge: (existing, ctx) => {\n const scripts = { ...(existing.scripts as Record<string, string>) };\n const result = { ...existing };\n\n // Add scripts if not present\n if (!scripts.lint) scripts.lint = 'eslint .';\n if (!scripts['lint:md']) scripts['lint:md'] = 'markdownlint-cli2 \"**/*.md\" \"#node_modules\"';\n if (!scripts.format) scripts.format = 'prettier --write .';\n if (!scripts['format:check']) scripts['format:check'] = 'prettier --check .';\n if (!scripts.knip) scripts.knip = 'knip';\n\n // Conditional: publint for publishable libraries\n if (ctx.projectType.publishableLibrary && !scripts.publint) {\n scripts.publint = 'publint';\n }\n\n // Conditional: lint:sh for projects with shell scripts\n if (ctx.projectType.shell && !scripts['lint:sh']) {\n scripts['lint:sh'] = 'shellcheck **/*.sh';\n }\n\n result.scripts = scripts;\n\n return result;\n },\n unmerge: existing => {\n const result = { ...existing };\n const scripts = { ...(existing.scripts as Record<string, string>) };\n\n // Remove safeword-specific scripts but preserve lint/format (useful standalone)\n delete scripts['lint:md'];\n delete scripts['lint:sh'];\n delete scripts['format:check'];\n delete scripts.knip;\n delete scripts.publint;\n\n if (Object.keys(scripts).length > 0) {\n result.scripts = scripts;\n } else {\n delete result.scripts;\n }\n\n return result;\n },\n },\n\n '.claude/settings.json': {\n keys: ['hooks'],\n merge: existing => {\n // Preserve non-safeword hooks while adding/updating safeword hooks\n const existingHooks = (existing.hooks as Record<string, unknown[]>) ?? {};\n const mergedHooks: Record<string, unknown[]> = { ...existingHooks };\n\n for (const [event, newHooks] of Object.entries(SETTINGS_HOOKS)) {\n const eventHooks = mergedHooks[event] ?? [];\n const nonSafewordHooks = filterOutSafewordHooks(eventHooks);\n mergedHooks[event] = [...nonSafewordHooks, ...newHooks];\n }\n\n return { ...existing, hooks: mergedHooks };\n },\n unmerge: existing => {\n // Remove only safeword hooks, preserve custom hooks\n const existingHooks = (existing.hooks as Record<string, unknown[]>) ?? {};\n const cleanedHooks: Record<string, unknown[]> = {};\n\n for (const [event, eventHooks] of Object.entries(existingHooks)) {\n const nonSafewordHooks = filterOutSafewordHooks(eventHooks);\n if (nonSafewordHooks.length > 0) {\n cleanedHooks[event] = nonSafewordHooks;\n }\n }\n\n const result = { ...existing };\n if (Object.keys(cleanedHooks).length > 0) {\n result.hooks = cleanedHooks;\n } else {\n delete result.hooks;\n }\n return result;\n },\n },\n\n '.mcp.json': {\n keys: ['mcpServers.context7', 'mcpServers.playwright'],\n removeFileIfEmpty: true,\n merge: existing => {\n const mcpServers = (existing.mcpServers as Record<string, unknown>) ?? {};\n return {\n ...existing,\n mcpServers: {\n ...mcpServers,\n context7: MCP_SERVERS.context7,\n playwright: MCP_SERVERS.playwright,\n },\n };\n },\n unmerge: existing => {\n const result = { ...existing };\n const mcpServers = { ...(existing.mcpServers as Record<string, unknown>) };\n\n delete mcpServers.context7;\n delete mcpServers.playwright;\n\n if (Object.keys(mcpServers).length > 0) {\n result.mcpServers = mcpServers;\n } else {\n delete result.mcpServers;\n }\n\n return result;\n },\n },\n\n '.cursor/mcp.json': {\n keys: ['mcpServers.context7', 'mcpServers.playwright'],\n removeFileIfEmpty: true,\n merge: existing => {\n const mcpServers = (existing.mcpServers as Record<string, unknown>) ?? {};\n return {\n ...existing,\n mcpServers: {\n ...mcpServers,\n context7: MCP_SERVERS.context7,\n playwright: MCP_SERVERS.playwright,\n },\n };\n },\n unmerge: existing => {\n const result = { ...existing };\n const mcpServers = { ...(existing.mcpServers as Record<string, unknown>) };\n\n delete mcpServers.context7;\n delete mcpServers.playwright;\n\n if (Object.keys(mcpServers).length > 0) {\n result.mcpServers = mcpServers;\n } else {\n delete result.mcpServers;\n }\n\n return result;\n },\n },\n\n '.cursor/hooks.json': {\n keys: ['version', 'hooks.afterFileEdit', 'hooks.stop'],\n removeFileIfEmpty: true,\n merge: existing => {\n const hooks = (existing.hooks as Record<string, unknown[]>) ?? {};\n return {\n ...existing,\n version: 1, // Required by Cursor\n hooks: {\n ...hooks,\n ...CURSOR_HOOKS,\n },\n };\n },\n unmerge: existing => {\n const result = { ...existing };\n const hooks = { ...(existing.hooks as Record<string, unknown[]>) };\n\n delete hooks.afterFileEdit;\n delete hooks.stop;\n\n if (Object.keys(hooks).length > 0) {\n result.hooks = hooks;\n } else {\n delete result.hooks;\n delete result.version;\n }\n\n return result;\n },\n },\n },\n\n // Text files where we patch specific content\n textPatches: {\n 'AGENTS.md': {\n operation: 'prepend',\n content: AGENTS_MD_LINK,\n marker: '.safeword/SAFEWORD.md',\n createIfMissing: true,\n },\n 'CLAUDE.md': {\n operation: 'prepend',\n content: AGENTS_MD_LINK,\n marker: '.safeword/SAFEWORD.md',\n createIfMissing: false, // Only patch if exists, don't create (AGENTS.md is primary)\n },\n },\n\n // NPM packages to install\n packages: {\n base: [\n // Core tools\n 'eslint',\n 'prettier',\n 'eslint-config-prettier',\n // Safeword plugin (bundles all ESLint plugins)\n 'eslint-plugin-safeword',\n // Non-ESLint tools\n 'markdownlint-cli2',\n 'knip',\n ],\n conditional: {\n // Frameworks NOT in eslint-plugin-safeword\n vue: ['eslint-plugin-vue'],\n svelte: ['eslint-plugin-svelte', 'prettier-plugin-svelte'],\n electron: ['@electron-toolkit/eslint-config'],\n // Prettier plugins\n astro: ['prettier-plugin-astro'],\n tailwind: ['prettier-plugin-tailwindcss'],\n // Non-ESLint tools\n publishableLibrary: ['publint'],\n shell: ['shellcheck', 'prettier-plugin-sh'],\n },\n },\n};\n","/**\n * Project type detection from package.json\n *\n * Detects frameworks and tools used in the project to configure\n * appropriate linting rules.\n */\n\nimport { readdirSync } from 'node:fs';\nimport nodePath from 'node:path';\n\nexport interface PackageJson {\n name?: string;\n version?: string;\n private?: boolean;\n main?: string;\n module?: string;\n exports?: unknown;\n types?: string;\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n}\n\nexport interface ProjectType {\n typescript: boolean;\n react: boolean;\n nextjs: boolean;\n astro: boolean;\n vue: boolean;\n nuxt: boolean;\n svelte: boolean;\n sveltekit: boolean;\n electron: boolean;\n vitest: boolean;\n playwright: boolean;\n tailwind: boolean;\n publishableLibrary: boolean;\n shell: boolean;\n}\n\n/**\n * Checks if a directory contains any .sh files up to specified depth.\n * Excludes node_modules and .git directories.\n * @param cwd\n * @param maxDepth\n */\nexport function hasShellScripts(cwd: string, maxDepth = 4): boolean {\n const excludeDirectories = new Set(['node_modules', '.git', '.safeword']);\n\n /**\n *\n * @param dir\n * @param depth\n */\n function scan(dir: string, depth: number): boolean {\n if (depth > maxDepth) return false;\n\n try {\n const entries = readdirSync(dir, { withFileTypes: true });\n for (const entry of entries) {\n if (entry.isFile() && entry.name.endsWith('.sh')) {\n return true;\n }\n if (\n entry.isDirectory() &&\n !excludeDirectories.has(entry.name) &&\n scan(nodePath.join(dir, entry.name), depth + 1)\n ) {\n return true;\n }\n }\n } catch {\n // Ignore permission errors\n }\n return false;\n }\n\n return scan(cwd, 0);\n}\n\n/**\n * Detects project type from package.json contents and optional file scanning\n * @param packageJson\n * @param cwd\n */\nexport function detectProjectType(packageJson: PackageJson, cwd?: string): ProjectType {\n const deps = packageJson.dependencies || {};\n const developmentDeps = packageJson.devDependencies || {};\n const allDeps = { ...deps, ...developmentDeps };\n\n const hasTypescript = 'typescript' in allDeps;\n const hasReact = 'react' in deps || 'react' in developmentDeps;\n const hasNextJs = 'next' in deps;\n const hasAstro = 'astro' in deps || 'astro' in developmentDeps;\n const hasVue = 'vue' in deps || 'vue' in developmentDeps;\n const hasNuxt = 'nuxt' in deps;\n const hasSvelte = 'svelte' in deps || 'svelte' in developmentDeps;\n const hasSvelteKit = '@sveltejs/kit' in deps || '@sveltejs/kit' in developmentDeps;\n const hasElectron = 'electron' in deps || 'electron' in developmentDeps;\n const hasVitest = 'vitest' in developmentDeps;\n const hasPlaywright = '@playwright/test' in developmentDeps;\n const hasTailwind = 'tailwindcss' in allDeps;\n\n // Publishable library: has entry points and is not marked private\n const hasEntryPoints = !!(packageJson.main || packageJson.module || packageJson.exports);\n const isPublishable = hasEntryPoints && packageJson.private !== true;\n\n // Shell scripts: detected by scanning for .sh files\n const hasShell = cwd ? hasShellScripts(cwd) : false;\n\n return {\n typescript: hasTypescript,\n react: hasReact || hasNextJs, // Next.js implies React\n nextjs: hasNextJs,\n astro: hasAstro,\n vue: hasVue || hasNuxt, // Nuxt implies Vue\n nuxt: hasNuxt,\n svelte: hasSvelte || hasSvelteKit, // SvelteKit implies Svelte\n sveltekit: hasSvelteKit,\n electron: hasElectron,\n vitest: hasVitest,\n playwright: hasPlaywright,\n tailwind: hasTailwind,\n publishableLibrary: isPublishable,\n shell: hasShell,\n };\n}\n"],"mappings":"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","names":["readdirSync","nodePath"]}
|