safeword 0.10.1 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,16 +1,18 @@
1
1
  import {
2
2
  SAFEWORD_SCHEMA,
3
3
  createProjectContext,
4
+ reconcile
5
+ } from "./chunk-KL2JTWK6.js";
6
+ import "./chunk-ORQHKDT2.js";
7
+ import {
4
8
  error,
5
9
  exists,
6
10
  header,
7
11
  info,
8
12
  listItem,
9
- reconcile,
10
13
  success,
11
14
  warn
12
- } from "./chunk-H7PCVPAC.js";
13
- import "./chunk-ORQHKDT2.js";
15
+ } from "./chunk-DYLHQBW3.js";
14
16
 
15
17
  // src/commands/reset.ts
16
18
  import { execSync } from "child_process";
@@ -71,4 +73,4 @@ async function reset(options) {
71
73
  export {
72
74
  reset
73
75
  };
74
- //# sourceMappingURL=reset-AEEUFODC.js.map
76
+ //# sourceMappingURL=reset-HJBALSYG.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/commands/reset.ts"],"sourcesContent":["/**\n * Reset command - Remove safeword configuration from project\n *\n * Uses reconcile() with mode='uninstall' or 'uninstall-full' to remove configuration.\n *\n * By default, preserves linting configuration (eslint, prettier, etc.)\n * Use --full to also remove linting config and uninstall npm packages\n */\n\nimport { execSync } from 'node:child_process';\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 } from '../utils/fs.js';\nimport { error, header, info, listItem, success, warn } from '../utils/output.js';\n\nexport interface ResetOptions {\n yes?: boolean;\n full?: boolean;\n}\n\nfunction uninstallPackages(cwd: string, packages: string[]): void {\n if (packages.length === 0) return;\n\n info('\\nUninstalling devDependencies...');\n const uninstallCmd = `npm uninstall ${packages.join(' ')}`;\n info(`Running: ${uninstallCmd}`);\n\n try {\n execSync(uninstallCmd, { cwd, stdio: 'inherit' });\n success('Uninstalled safeword devDependencies');\n } catch {\n warn('Failed to uninstall some packages. Run manually:');\n listItem(uninstallCmd);\n }\n}\n\nfunction printResetSummary(result: ReconcileResult, fullReset: boolean): void {\n header('Reset Complete');\n\n if (result.removed.length > 0) {\n info('\\nRemoved:');\n for (const item of result.removed) {\n listItem(item);\n }\n }\n\n if (!fullReset) {\n info('\\nPreserved (use --full to remove):');\n listItem('eslint.config.mjs');\n listItem('.prettierrc');\n listItem('package.json (scripts)');\n listItem('devDependencies (eslint, prettier, etc.)');\n }\n\n success('\\nSafeword configuration removed');\n}\n\nexport async function reset(options: ResetOptions): Promise<void> {\n const cwd = process.cwd();\n const safewordDirectory = nodePath.join(cwd, '.safeword');\n\n if (!exists(safewordDirectory)) {\n info('Nothing to remove. Project is not configured with safeword.');\n return;\n }\n\n const fullReset = options.full ?? false;\n const mode = fullReset ? 'uninstall-full' : 'uninstall';\n\n header('Safeword Reset');\n info(\n fullReset\n ? 'Performing full reset (including linting configuration)...'\n : 'Removing safeword configuration...',\n );\n\n try {\n const ctx = createProjectContext(cwd);\n const result = await reconcile(SAFEWORD_SCHEMA, mode, ctx);\n\n if (fullReset) uninstallPackages(cwd, result.packagesToRemove);\n printResetSummary(result, fullReset);\n } catch (error_) {\n error(`Reset failed: ${error_ instanceof Error ? error_.message : 'Unknown error'}`);\n process.exit(1);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;AASA,SAAS,gBAAgB;AACzB,OAAO,cAAc;AAarB,SAAS,kBAAkB,KAAa,UAA0B;AAChE,MAAI,SAAS,WAAW,EAAG;AAE3B,OAAK,mCAAmC;AACxC,QAAM,eAAe,iBAAiB,SAAS,KAAK,GAAG,CAAC;AACxD,OAAK,YAAY,YAAY,EAAE;AAE/B,MAAI;AACF,aAAS,cAAc,EAAE,KAAK,OAAO,UAAU,CAAC;AAChD,YAAQ,sCAAsC;AAAA,EAChD,QAAQ;AACN,SAAK,kDAAkD;AACvD,aAAS,YAAY;AAAA,EACvB;AACF;AAEA,SAAS,kBAAkB,QAAyB,WAA0B;AAC5E,SAAO,gBAAgB;AAEvB,MAAI,OAAO,QAAQ,SAAS,GAAG;AAC7B,SAAK,YAAY;AACjB,eAAW,QAAQ,OAAO,SAAS;AACjC,eAAS,IAAI;AAAA,IACf;AAAA,EACF;AAEA,MAAI,CAAC,WAAW;AACd,SAAK,qCAAqC;AAC1C,aAAS,mBAAmB;AAC5B,aAAS,aAAa;AACtB,aAAS,wBAAwB;AACjC,aAAS,0CAA0C;AAAA,EACrD;AAEA,UAAQ,kCAAkC;AAC5C;AAEA,eAAsB,MAAM,SAAsC;AAChE,QAAM,MAAM,QAAQ,IAAI;AACxB,QAAM,oBAAoB,SAAS,KAAK,KAAK,WAAW;AAExD,MAAI,CAAC,OAAO,iBAAiB,GAAG;AAC9B,SAAK,6DAA6D;AAClE;AAAA,EACF;AAEA,QAAM,YAAY,QAAQ,QAAQ;AAClC,QAAM,OAAO,YAAY,mBAAmB;AAE5C,SAAO,gBAAgB;AACvB;AAAA,IACE,YACI,+DACA;AAAA,EACN;AAEA,MAAI;AACF,UAAM,MAAM,qBAAqB,GAAG;AACpC,UAAM,SAAS,MAAM,UAAU,iBAAiB,MAAM,GAAG;AAEzD,QAAI,UAAW,mBAAkB,KAAK,OAAO,gBAAgB;AAC7D,sBAAkB,QAAQ,SAAS;AAAA,EACrC,SAAS,QAAQ;AACf,UAAM,iBAAiB,kBAAkB,QAAQ,OAAO,UAAU,eAAe,EAAE;AACnF,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;","names":[]}
1
+ {"version":3,"sources":["../src/commands/reset.ts"],"sourcesContent":["/**\n * Reset command - Remove safeword configuration from project\n *\n * Uses reconcile() with mode='uninstall' or 'uninstall-full' to remove configuration.\n *\n * By default, preserves linting configuration (eslint, prettier, etc.)\n * Use --full to also remove linting config and uninstall npm packages\n */\n\nimport { execSync } from 'node:child_process';\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 } from '../utils/fs.js';\nimport { error, header, info, listItem, success, warn } from '../utils/output.js';\n\nexport interface ResetOptions {\n yes?: boolean;\n full?: boolean;\n}\n\nfunction uninstallPackages(cwd: string, packages: string[]): void {\n if (packages.length === 0) return;\n\n info('\\nUninstalling devDependencies...');\n const uninstallCmd = `npm uninstall ${packages.join(' ')}`;\n info(`Running: ${uninstallCmd}`);\n\n try {\n execSync(uninstallCmd, { cwd, stdio: 'inherit' });\n success('Uninstalled safeword devDependencies');\n } catch {\n warn('Failed to uninstall some packages. Run manually:');\n listItem(uninstallCmd);\n }\n}\n\nfunction printResetSummary(result: ReconcileResult, fullReset: boolean): void {\n header('Reset Complete');\n\n if (result.removed.length > 0) {\n info('\\nRemoved:');\n for (const item of result.removed) {\n listItem(item);\n }\n }\n\n if (!fullReset) {\n info('\\nPreserved (use --full to remove):');\n listItem('eslint.config.mjs');\n listItem('.prettierrc');\n listItem('package.json (scripts)');\n listItem('devDependencies (eslint, prettier, etc.)');\n }\n\n success('\\nSafeword configuration removed');\n}\n\nexport async function reset(options: ResetOptions): Promise<void> {\n const cwd = process.cwd();\n const safewordDirectory = nodePath.join(cwd, '.safeword');\n\n if (!exists(safewordDirectory)) {\n info('Nothing to remove. Project is not configured with safeword.');\n return;\n }\n\n const fullReset = options.full ?? false;\n const mode = fullReset ? 'uninstall-full' : 'uninstall';\n\n header('Safeword Reset');\n info(\n fullReset\n ? 'Performing full reset (including linting configuration)...'\n : 'Removing safeword configuration...',\n );\n\n try {\n const ctx = createProjectContext(cwd);\n const result = await reconcile(SAFEWORD_SCHEMA, mode, ctx);\n\n if (fullReset) uninstallPackages(cwd, result.packagesToRemove);\n printResetSummary(result, fullReset);\n } catch (error_) {\n error(`Reset failed: ${error_ instanceof Error ? error_.message : 'Unknown error'}`);\n process.exit(1);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AASA,SAAS,gBAAgB;AACzB,OAAO,cAAc;AAarB,SAAS,kBAAkB,KAAa,UAA0B;AAChE,MAAI,SAAS,WAAW,EAAG;AAE3B,OAAK,mCAAmC;AACxC,QAAM,eAAe,iBAAiB,SAAS,KAAK,GAAG,CAAC;AACxD,OAAK,YAAY,YAAY,EAAE;AAE/B,MAAI;AACF,aAAS,cAAc,EAAE,KAAK,OAAO,UAAU,CAAC;AAChD,YAAQ,sCAAsC;AAAA,EAChD,QAAQ;AACN,SAAK,kDAAkD;AACvD,aAAS,YAAY;AAAA,EACvB;AACF;AAEA,SAAS,kBAAkB,QAAyB,WAA0B;AAC5E,SAAO,gBAAgB;AAEvB,MAAI,OAAO,QAAQ,SAAS,GAAG;AAC7B,SAAK,YAAY;AACjB,eAAW,QAAQ,OAAO,SAAS;AACjC,eAAS,IAAI;AAAA,IACf;AAAA,EACF;AAEA,MAAI,CAAC,WAAW;AACd,SAAK,qCAAqC;AAC1C,aAAS,mBAAmB;AAC5B,aAAS,aAAa;AACtB,aAAS,wBAAwB;AACjC,aAAS,0CAA0C;AAAA,EACrD;AAEA,UAAQ,kCAAkC;AAC5C;AAEA,eAAsB,MAAM,SAAsC;AAChE,QAAM,MAAM,QAAQ,IAAI;AACxB,QAAM,oBAAoB,SAAS,KAAK,KAAK,WAAW;AAExD,MAAI,CAAC,OAAO,iBAAiB,GAAG;AAC9B,SAAK,6DAA6D;AAClE;AAAA,EACF;AAEA,QAAM,YAAY,QAAQ,QAAQ;AAClC,QAAM,OAAO,YAAY,mBAAmB;AAE5C,SAAO,gBAAgB;AACvB;AAAA,IACE,YACI,+DACA;AAAA,EACN;AAEA,MAAI;AACF,UAAM,MAAM,qBAAqB,GAAG;AACpC,UAAM,SAAS,MAAM,UAAU,iBAAiB,MAAM,GAAG;AAEzD,QAAI,UAAW,mBAAkB,KAAK,OAAO,gBAAgB;AAC7D,sBAAkB,QAAQ,SAAS;AAAA,EACrC,SAAS,QAAQ;AACf,UAAM,iBAAiB,kBAAkB,QAAQ,OAAO,UAAU,eAAe,EAAE;AACnF,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;","names":[]}
@@ -1,20 +1,27 @@
1
+ import {
2
+ buildArchitecture,
3
+ hasArchitectureDetected,
4
+ syncConfigCore
5
+ } from "./chunk-NDY7IUE7.js";
1
6
  import {
2
7
  SAFEWORD_SCHEMA,
3
8
  createProjectContext,
9
+ isGitRepo,
10
+ reconcile
11
+ } from "./chunk-KL2JTWK6.js";
12
+ import {
13
+ VERSION
14
+ } from "./chunk-ORQHKDT2.js";
15
+ import {
4
16
  error,
5
17
  exists,
6
18
  header,
7
19
  info,
8
- isGitRepo,
9
20
  listItem,
10
- reconcile,
11
21
  success,
12
22
  warn,
13
23
  writeJson
14
- } from "./chunk-H7PCVPAC.js";
15
- import {
16
- VERSION
17
- } from "./chunk-ORQHKDT2.js";
24
+ } from "./chunk-DYLHQBW3.js";
18
25
 
19
26
  // src/commands/setup.ts
20
27
  import { execSync } from "child_process";
@@ -40,12 +47,13 @@ function installDependencies(cwd, packages) {
40
47
  listItem(installCmd);
41
48
  }
42
49
  }
43
- function printSetupSummary(result, packageJsonCreated) {
50
+ function printSetupSummary(result, packageJsonCreated, archFiles = []) {
44
51
  header("Setup Complete");
45
- if (result.created.length > 0 || packageJsonCreated) {
52
+ const allCreated = [...result.created, ...archFiles];
53
+ if (allCreated.length > 0 || packageJsonCreated) {
46
54
  info("\nCreated:");
47
55
  if (packageJsonCreated) listItem("package.json");
48
- for (const file of result.created) listItem(file);
56
+ for (const file of allCreated) listItem(file);
49
57
  }
50
58
  if (result.updated.length > 0) {
51
59
  info("\nModified:");
@@ -73,13 +81,33 @@ async function setup(options) {
73
81
  const ctx = createProjectContext(cwd);
74
82
  const result = await reconcile(SAFEWORD_SCHEMA, "install", ctx);
75
83
  success("Created .safeword directory and configuration");
84
+ const arch = buildArchitecture(cwd);
85
+ const archFiles = [];
86
+ if (hasArchitectureDetected(arch)) {
87
+ const syncResult = syncConfigCore(cwd, arch);
88
+ if (syncResult.generatedConfig) archFiles.push(".safeword/depcruise-config.js");
89
+ if (syncResult.createdMainConfig) archFiles.push(".dependency-cruiser.js");
90
+ const detected = [];
91
+ if (arch.elements.length > 0) {
92
+ detected.push(arch.elements.map((element) => element.location).join(", "));
93
+ }
94
+ if (arch.workspaces && arch.workspaces.length > 0) {
95
+ detected.push(`workspaces: ${arch.workspaces.join(", ")}`);
96
+ }
97
+ info(`
98
+ Architecture detected: ${detected.join("; ")}`);
99
+ info("Generated dependency-cruiser config for /audit command");
100
+ }
76
101
  installDependencies(cwd, result.packagesToInstall);
77
102
  if (!isGitRepo(cwd)) {
78
103
  const isNonInteractive = options.yes || !process.stdin.isTTY;
79
- warn(isNonInteractive ? "Skipped Husky setup (no git repository)" : "Skipped Husky setup (no .git directory)");
80
- if (!isNonInteractive) info("Initialize git and run safeword upgrade to enable pre-commit hooks");
104
+ warn(
105
+ isNonInteractive ? "Skipped Husky setup (no git repository)" : "Skipped Husky setup (no .git directory)"
106
+ );
107
+ if (!isNonInteractive)
108
+ info("Initialize git and run safeword upgrade to enable pre-commit hooks");
81
109
  }
82
- printSetupSummary(result, packageJsonCreated);
110
+ printSetupSummary(result, packageJsonCreated, archFiles);
83
111
  } catch (error_) {
84
112
  error(`Setup failed: ${error_ instanceof Error ? error_.message : "Unknown error"}`);
85
113
  process.exit(1);
@@ -88,4 +116,4 @@ async function setup(options) {
88
116
  export {
89
117
  setup
90
118
  };
91
- //# sourceMappingURL=setup-R5IC3GHJ.js.map
119
+ //# sourceMappingURL=setup-SOWUS7ZI.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/setup.ts"],"sourcesContent":["/**\n * Setup command - Initialize safeword in a project\n *\n * Uses reconcile() with mode='install' to create all managed files.\n */\n\nimport { execSync } from 'node:child_process';\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, writeJson } from '../utils/fs.js';\nimport { isGitRepo } from '../utils/git.js';\nimport { error, header, info, listItem, success, warn } from '../utils/output.js';\nimport { VERSION } from '../version.js';\nimport { buildArchitecture, hasArchitectureDetected, syncConfigCore } from './sync-config.js';\n\nexport interface SetupOptions {\n yes?: boolean;\n}\n\ninterface PackageJson {\n name?: string;\n version?: string;\n scripts?: Record<string, string>;\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n 'lint-staged'?: Record<string, string[]>;\n}\n\nfunction ensurePackageJson(cwd: string): boolean {\n const packageJsonPath = nodePath.join(cwd, 'package.json');\n if (exists(packageJsonPath)) return false;\n\n const dirName = nodePath.basename(cwd) || 'project';\n const defaultPackageJson: PackageJson = { name: dirName, version: '0.1.0', scripts: {} };\n writeJson(packageJsonPath, defaultPackageJson);\n return true;\n}\n\nfunction installDependencies(cwd: string, packages: string[]): void {\n if (packages.length === 0) return;\n\n info('\\nInstalling linting dependencies...');\n const installCmd = `npm install -D ${packages.join(' ')}`;\n info(`Running: ${installCmd}`);\n\n try {\n execSync(installCmd, { cwd, stdio: 'inherit' });\n success('Installed linting dependencies');\n } catch {\n warn('Failed to install dependencies. Run manually:');\n listItem(installCmd);\n }\n}\n\nfunction printSetupSummary(\n result: ReconcileResult,\n packageJsonCreated: boolean,\n archFiles: string[] = [],\n): void {\n header('Setup Complete');\n\n const allCreated = [...result.created, ...archFiles];\n if (allCreated.length > 0 || packageJsonCreated) {\n info('\\nCreated:');\n if (packageJsonCreated) listItem('package.json');\n for (const file of allCreated) listItem(file);\n }\n\n if (result.updated.length > 0) {\n info('\\nModified:');\n for (const file of result.updated) listItem(file);\n }\n\n info('\\nNext steps:');\n listItem('Run `safeword check` to verify setup');\n listItem('Commit the new files to git');\n\n success(`\\nSafeword ${VERSION} installed successfully!`);\n}\n\nexport async function setup(options: SetupOptions): Promise<void> {\n const cwd = process.cwd();\n const safewordDirectory = nodePath.join(cwd, '.safeword');\n\n if (exists(safewordDirectory)) {\n error('Already configured. Run `safeword upgrade` to update.');\n process.exit(1);\n }\n\n const packageJsonCreated = ensurePackageJson(cwd);\n\n header('Safeword Setup');\n info(`Version: ${VERSION}`);\n if (packageJsonCreated) info('Created package.json (none found)');\n\n try {\n info('\\nCreating safeword configuration...');\n const ctx = createProjectContext(cwd);\n const result = await reconcile(SAFEWORD_SCHEMA, 'install', ctx);\n success('Created .safeword directory and configuration');\n\n // Detect architecture and workspaces, generate depcruise configs if found\n const arch = buildArchitecture(cwd);\n const archFiles: string[] = [];\n\n if (hasArchitectureDetected(arch)) {\n const syncResult = syncConfigCore(cwd, arch);\n if (syncResult.generatedConfig) archFiles.push('.safeword/depcruise-config.js');\n if (syncResult.createdMainConfig) archFiles.push('.dependency-cruiser.js');\n\n const detected: string[] = [];\n if (arch.elements.length > 0) {\n detected.push(arch.elements.map(element => element.location).join(', '));\n }\n if (arch.workspaces && arch.workspaces.length > 0) {\n detected.push(`workspaces: ${arch.workspaces.join(', ')}`);\n }\n info(`\\nArchitecture detected: ${detected.join('; ')}`);\n info('Generated dependency-cruiser config for /audit command');\n }\n\n installDependencies(cwd, result.packagesToInstall);\n\n if (!isGitRepo(cwd)) {\n const isNonInteractive = options.yes || !process.stdin.isTTY;\n warn(\n isNonInteractive\n ? 'Skipped Husky setup (no git repository)'\n : 'Skipped Husky setup (no .git directory)',\n );\n if (!isNonInteractive)\n info('Initialize git and run safeword upgrade to enable pre-commit hooks');\n }\n\n printSetupSummary(result, packageJsonCreated, archFiles);\n } catch (error_) {\n error(`Setup failed: ${error_ instanceof Error ? error_.message : 'Unknown error'}`);\n process.exit(1);\n }\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,14 @@
1
+ import {
2
+ buildArchitecture,
3
+ hasArchitectureDetected,
4
+ syncConfig,
5
+ syncConfigCore
6
+ } from "./chunk-NDY7IUE7.js";
7
+ import "./chunk-DYLHQBW3.js";
8
+ export {
9
+ buildArchitecture,
10
+ hasArchitectureDetected,
11
+ syncConfig,
12
+ syncConfigCore
13
+ };
14
+ //# sourceMappingURL=sync-config-XTMQBCIH.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -4,19 +4,21 @@ import {
4
4
  import {
5
5
  SAFEWORD_SCHEMA,
6
6
  createProjectContext,
7
+ reconcile
8
+ } from "./chunk-KL2JTWK6.js";
9
+ import {
10
+ VERSION
11
+ } from "./chunk-ORQHKDT2.js";
12
+ import {
7
13
  error,
8
14
  exists,
9
15
  header,
10
16
  info,
11
17
  listItem,
12
18
  readFileSafe,
13
- reconcile,
14
19
  success,
15
20
  warn
16
- } from "./chunk-H7PCVPAC.js";
17
- import {
18
- VERSION
19
- } from "./chunk-ORQHKDT2.js";
21
+ } from "./chunk-DYLHQBW3.js";
20
22
 
21
23
  // src/commands/upgrade.ts
22
24
  import nodePath from "path";
@@ -73,4 +75,4 @@ async function upgrade() {
73
75
  export {
74
76
  upgrade
75
77
  };
76
- //# sourceMappingURL=upgrade-QXP3ONNQ.js.map
78
+ //# sourceMappingURL=upgrade-KJLOX4DD.js.map
@@ -1 +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":[]}
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "safeword",
3
- "version": "0.10.1",
3
+ "version": "0.11.0",
4
4
  "description": "CLI for setting up and managing safeword development environments",
5
5
  "type": "module",
6
6
  "bin": {
@@ -38,7 +38,7 @@
38
38
  "@types/node": "^20.10.0",
39
39
  "tsup": "^8.0.0",
40
40
  "typescript": "^5.3.0",
41
- "vitest": "^2.0.0"
41
+ "vitest": "^4.0.15"
42
42
  },
43
43
  "keywords": [
44
44
  "cli",
@@ -0,0 +1,41 @@
1
+ ---
2
+ description: Run comprehensive code audit for architecture and dead code
3
+ ---
4
+
5
+ # Audit
6
+
7
+ Run a comprehensive code audit. Execute these commands and report results.
8
+
9
+ ## Instructions
10
+
11
+ ```bash
12
+ # 1. Refresh config (detect current architecture)
13
+ npx safeword sync-config 2>&1
14
+
15
+ # 2. Architecture check (circular deps, layer violations)
16
+ npx depcruise --output-type err --config .dependency-cruiser.js . 2>&1 || true
17
+
18
+ # 3. Dead code check + auto-fix (unused exports, deps)
19
+ npx knip --fix 2>&1 || true
20
+
21
+ # 4. Outdated packages (informational)
22
+ npm outdated 2>&1 || true
23
+ ```
24
+
25
+ ## Report Format
26
+
27
+ After running, report in this format:
28
+
29
+ **Fixed:**
30
+
31
+ - [What knip auto-fixed - unused exports, dependencies]
32
+
33
+ **Errors (manual fix required):**
34
+
35
+ - [Circular dependencies - show the cycle path]
36
+ - [Layer violations - show the invalid import]
37
+
38
+ **Info:**
39
+
40
+ - [Unused files to review - may be intentional]
41
+ - [Outdated packages - optional to update]
@@ -34,7 +34,7 @@ Complete each phase before proceeding.
34
34
 
35
35
  **BEFORE attempting ANY fix:**
36
36
 
37
- **1. Read Error Messages Completely**
37
+ #### 1. Read Error Messages Completely
38
38
 
39
39
  ```text
40
40
  Don't skip past errors. They often contain the exact solution.
@@ -43,7 +43,7 @@ Don't skip past errors. They often contain the exact solution.
43
43
  - Warnings that preceded the error
44
44
  ```
45
45
 
46
- **2. Reproduce Consistently**
46
+ #### 2. Reproduce Consistently
47
47
 
48
48
  | Can reproduce? | Action |
49
49
  | --------------- | ---------------------------------------------------- |
@@ -51,7 +51,7 @@ Don't skip past errors. They often contain the exact solution.
51
51
  | Sometimes | Gather more data - when does it happen vs not? |
52
52
  | Never | Cannot debug what you cannot reproduce - gather logs |
53
53
 
54
- **3. Check Recent Changes**
54
+ #### 3. Check Recent Changes
55
55
 
56
56
  ```bash
57
57
  git diff HEAD~5 # Recent code changes
@@ -60,7 +60,7 @@ git log --oneline -10 # Recent commits
60
60
 
61
61
  What changed that could cause this? Dependencies? Config? Environment?
62
62
 
63
- **4. Trace Data Flow (Root Cause Tracing)**
63
+ #### 4. Trace Data Flow (Root Cause Tracing)
64
64
 
65
65
  When error is deep in call stack:
66
66
 
@@ -78,7 +78,7 @@ Symptom: Error at line 50 in utils.js
78
78
  3. Trace up until you find the SOURCE
79
79
  4. Fix at source, not at symptom
80
80
 
81
- **5. Multi-Component Systems**
81
+ #### 5. Multi-Component Systems
82
82
 
83
83
  When system has multiple layers (API → service → database):
84
84
 
@@ -93,11 +93,11 @@ Run once to find WHERE it breaks. Then investigate that layer.
93
93
 
94
94
  ### Phase 2: Pattern Analysis
95
95
 
96
- **1. Find Working Examples**
96
+ #### 1. Find Working Examples
97
97
 
98
98
  Locate similar working code in same codebase. What works that's similar?
99
99
 
100
- **2. Identify Differences**
100
+ #### 2. Identify Differences
101
101
 
102
102
  | Working code | Broken code | Could this matter? |
103
103
  | ---------------- | -------------- | ------------------ |
@@ -108,7 +108,7 @@ List ALL differences. Don't assume "that can't matter."
108
108
 
109
109
  ### Phase 3: Hypothesis Testing
110
110
 
111
- **1. Form Single Hypothesis**
111
+ #### 1. Form Single Hypothesis
112
112
 
113
113
  Write it down: "I think X is the root cause because Y"
114
114
 
@@ -117,7 +117,7 @@ Be specific:
117
117
  - ❌ "Something's wrong with the database"
118
118
  - ✅ "Connection pool exhausted because connections aren't released in error path"
119
119
 
120
- **2. Test Minimally**
120
+ #### 2. Test Minimally
121
121
 
122
122
  | Rule | Why |
123
123
  | ------------------------ | ---------------------- |
@@ -125,7 +125,7 @@ Be specific:
125
125
  | Smallest possible change | Avoid side effects |
126
126
  | Don't bundle fixes | Can't tell what helped |
127
127
 
128
- **3. Evaluate Result**
128
+ #### 3. Evaluate Result
129
129
 
130
130
  | Result | Action |
131
131
  | --------------- | --------------------------------------- |
@@ -135,7 +135,7 @@ Be specific:
135
135
 
136
136
  ### Phase 4: Implementation
137
137
 
138
- **1. Create Failing Test**
138
+ #### 1. Create Failing Test
139
139
 
140
140
  Before fixing, write test that fails due to the bug:
141
141
 
@@ -146,26 +146,26 @@ it('handles empty input without crashing', () => {
146
146
  });
147
147
  ```
148
148
 
149
- **2. Implement Fix**
149
+ #### 2. Implement Fix
150
150
 
151
151
  - Address ROOT CAUSE identified in Phase 1
152
152
  - ONE change
153
153
  - No "while I'm here" improvements
154
154
 
155
- **3. Verify**
155
+ #### 3. Verify
156
156
 
157
157
  - [ ] New test passes
158
158
  - [ ] Existing tests still pass
159
159
  - [ ] Issue actually resolved (not just test passing)
160
160
 
161
- **4. If Fix Doesn't Work**
161
+ #### 4. If Fix Doesn't Work
162
162
 
163
163
  | Fix attempts | Action |
164
164
  | ------------ | ---------------------------------------- |
165
165
  | 1-2 | Return to Phase 1 with new information |
166
166
  | 3+ | STOP - Question architecture (see below) |
167
167
 
168
- **5. After 3+ Failed Fixes: Question Architecture**
168
+ #### 5. After 3+ Failed Fixes: Question Architecture
169
169
 
170
170
  Pattern indicating architectural problem:
171
171