safeword 0.8.10 → 0.9.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.
@@ -12,7 +12,7 @@ import {
12
12
  reconcile,
13
13
  success,
14
14
  warn
15
- } from "./chunk-POPS3ZRQ.js";
15
+ } from "./chunk-UUKED7KU.js";
16
16
  import {
17
17
  VERSION
18
18
  } from "./chunk-ORQHKDT2.js";
@@ -162,4 +162,4 @@ async function check(options) {
162
162
  export {
163
163
  check
164
164
  };
165
- //# sourceMappingURL=check-4HX4SNVV.js.map
165
+ //# sourceMappingURL=check-MLYBKA5Z.js.map
@@ -139,16 +139,17 @@ function planManagedFileWrites(files, ctx) {
139
139
  }
140
140
  return { actions, created };
141
141
  }
142
- function planTextPatchesWithCreation(patches, ctx, wouldCreate) {
142
+ function planTextPatchesWithCreation(patches, ctx) {
143
143
  const actions = [];
144
+ const created = [];
144
145
  for (const [filePath, definition] of Object.entries(patches)) {
145
146
  if (shouldSkipForNonGit(filePath, ctx.isGitRepo)) continue;
146
147
  actions.push({ type: "text-patch", path: filePath, definition });
147
148
  if (definition.createIfMissing && !exists(nodePath2.join(ctx.cwd, filePath))) {
148
- wouldCreate.push(filePath);
149
+ created.push(filePath);
149
150
  }
150
151
  }
151
- return actions;
152
+ return { actions, created };
152
153
  }
153
154
  function planExistingDirectoriesRemoval(directories, cwd) {
154
155
  const actions = [];
@@ -255,7 +256,9 @@ function computeInstallPlan(schema, ctx) {
255
256
  for (const [filePath, definition] of Object.entries(schema.jsonMerges)) {
256
257
  actions.push({ type: "json-merge", path: filePath, definition });
257
258
  }
258
- actions.push(...planTextPatchesWithCreation(schema.textPatches, ctx, wouldCreate));
259
+ const patches = planTextPatchesWithCreation(schema.textPatches, ctx);
260
+ actions.push(...patches.actions);
261
+ wouldCreate.push(...patches.created);
259
262
  const packagesToInstall = computePackagesToInstall(schema, ctx.projectType, ctx.developmentDeps, ctx.isGitRepo);
260
263
  return { actions, wouldCreate, wouldUpdate: [], wouldRemove: [], packagesToInstall, packagesToRemove: [] };
261
264
  }
@@ -1216,4 +1219,4 @@ export {
1216
1219
  listItem,
1217
1220
  keyValue
1218
1221
  };
1219
- //# sourceMappingURL=chunk-POPS3ZRQ.js.map
1222
+ //# sourceMappingURL=chunk-UUKED7KU.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils/fs.ts","../src/reconcile.ts","../src/templates/config.ts","../src/templates/content.ts","../src/utils/hooks.ts","../src/utils/install.ts","../src/schema.ts","../src/utils/git.ts","../src/utils/context.ts","../src/utils/project-detector.ts","../src/utils/output.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 * Reconciliation Engine\n *\n * Computes and executes plans based on SAFEWORD_SCHEMA and project state.\n * This is the single source of truth for all file/dir/config operations.\n */\n\nimport nodePath from 'node:path';\n\nimport type {\n FileDefinition,\n JsonMergeDefinition,\n ProjectContext,\n SafewordSchema,\n TextPatchDefinition,\n} from './schema.js';\nimport {\n ensureDirectory,\n exists,\n getTemplatesDirectory,\n makeScriptsExecutable,\n readFile,\n readFileSafe,\n readJson,\n remove,\n removeIfEmpty,\n writeFile,\n writeJson,\n} from './utils/fs.js';\nimport type { ProjectType } from './utils/project-detector.js';\n\n// ============================================================================\n// Constants\n// ============================================================================\n\nconst HUSKY_DIR = '.husky';\n\n/**\n * Check if path should be skipped in non-git repos (husky files)\n * @param path\n * @param isGitRepo\n */\nfunction shouldSkipForNonGit(path: string, isGitRepo: boolean): boolean {\n return path.startsWith(HUSKY_DIR) && !isGitRepo;\n}\n\n/**\n * Plan mkdir actions for directories that don't exist\n * @param dirs\n * @param cwd\n * @param isGitRepo\n */\nfunction planMissingDirectories(\n directories: string[],\n cwd: string,\n isGitRepo: boolean,\n): { actions: Action[]; created: string[] } {\n const actions: Action[] = [];\n const created: string[] = [];\n for (const dir of directories) {\n if (shouldSkipForNonGit(dir, isGitRepo)) continue;\n if (!exists(nodePath.join(cwd, dir))) {\n actions.push({ type: 'mkdir', path: dir });\n created.push(dir);\n }\n }\n return { actions, created };\n}\n\n/**\n * Plan text-patch actions for files missing the marker\n * @param patches\n * @param cwd\n * @param isGitRepo\n */\nfunction planTextPatches(\n patches: Record<string, TextPatchDefinition>,\n cwd: string,\n isGitRepo: boolean,\n): Action[] {\n const actions: Action[] = [];\n for (const [filePath, definition] of Object.entries(patches)) {\n if (shouldSkipForNonGit(filePath, isGitRepo)) continue;\n const content = readFileSafe(nodePath.join(cwd, filePath)) ?? '';\n if (!content.includes(definition.marker)) {\n actions.push({ type: 'text-patch', path: filePath, definition });\n }\n }\n return actions;\n}\n\nfunction planOwnedFileWrites(\n files: Record<string, FileDefinition>,\n ctx: ProjectContext,\n): { actions: Action[]; created: string[] } {\n const actions: Action[] = [];\n const created: string[] = [];\n for (const [filePath, definition] of Object.entries(files)) {\n if (shouldSkipForNonGit(filePath, ctx.isGitRepo)) continue;\n const content = resolveFileContent(definition, ctx);\n actions.push({ type: 'write', path: filePath, content });\n created.push(filePath);\n }\n return { actions, created };\n}\n\nfunction planManagedFileWrites(\n files: Record<string, FileDefinition>,\n ctx: ProjectContext,\n): { actions: Action[]; created: string[] } {\n const actions: Action[] = [];\n const created: string[] = [];\n for (const [filePath, definition] of Object.entries(files)) {\n if (exists(nodePath.join(ctx.cwd, filePath))) continue;\n const content = resolveFileContent(definition, ctx);\n actions.push({ type: 'write', path: filePath, content });\n created.push(filePath);\n }\n return { actions, created };\n}\n\nfunction planTextPatchesWithCreation(\n patches: Record<string, TextPatchDefinition>,\n ctx: ProjectContext,\n): { actions: Action[]; created: string[] } {\n const actions: Action[] = [];\n const created: string[] = [];\n for (const [filePath, definition] of Object.entries(patches)) {\n if (shouldSkipForNonGit(filePath, ctx.isGitRepo)) continue;\n actions.push({ type: 'text-patch', path: filePath, definition });\n if (definition.createIfMissing && !exists(nodePath.join(ctx.cwd, filePath))) {\n created.push(filePath);\n }\n }\n return { actions, created };\n}\n\n/**\n * Plan rmdir actions for directories that exist\n * @param dirs\n * @param cwd\n */\nfunction planExistingDirectoriesRemoval(\n directories: string[],\n cwd: string,\n): { actions: Action[]; removed: string[] } {\n const actions: Action[] = [];\n const removed: string[] = [];\n for (const dir of directories) {\n if (exists(nodePath.join(cwd, dir))) {\n actions.push({ type: 'rmdir', path: dir });\n removed.push(dir);\n }\n }\n return { actions, removed };\n}\n\n/**\n * Plan rm actions for files that exist\n * @param files\n * @param cwd\n */\nfunction planExistingFilesRemoval(\n files: string[],\n cwd: string,\n): { actions: Action[]; removed: string[] } {\n const actions: Action[] = [];\n const removed: string[] = [];\n for (const filePath of files) {\n if (exists(nodePath.join(cwd, filePath))) {\n actions.push({ type: 'rm', path: filePath });\n removed.push(filePath);\n }\n }\n return { actions, removed };\n}\n\n/**\n * Check if a .claude path needs parent dir cleanup\n * @param filePath\n */\nfunction getClaudeParentDirectoryForCleanup(filePath: string): string | undefined {\n if (!filePath.startsWith('.claude/')) return undefined;\n const parentDirectory = filePath.slice(0, Math.max(0, filePath.lastIndexOf('/')));\n if (\n !parentDirectory ||\n parentDirectory === '.claude' ||\n parentDirectory === '.claude/skills' ||\n parentDirectory === '.claude/commands'\n ) {\n return undefined;\n }\n return parentDirectory;\n}\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type ReconcileMode = 'install' | 'upgrade' | 'uninstall' | 'uninstall-full';\n\nexport type Action =\n | { type: 'mkdir'; path: string }\n | { type: 'rmdir'; path: string }\n | { type: 'write'; path: string; content: string }\n | { type: 'rm'; path: string }\n | { type: 'chmod'; paths: string[] }\n | { type: 'json-merge'; path: string; definition: JsonMergeDefinition }\n | { type: 'json-unmerge'; path: string; definition: JsonMergeDefinition }\n | { type: 'text-patch'; path: string; definition: TextPatchDefinition }\n | { type: 'text-unpatch'; path: string; definition: TextPatchDefinition };\n\nexport interface ReconcileResult {\n actions: Action[];\n applied: boolean;\n created: string[];\n updated: string[];\n removed: string[];\n packagesToInstall: string[];\n packagesToRemove: string[];\n}\n\nexport interface ReconcileOptions {\n dryRun?: boolean;\n}\n\n// ============================================================================\n// Main reconcile function\n// ============================================================================\n\n/**\n *\n * @param schema\n * @param mode\n * @param ctx\n * @param options\n */\nexport async function reconcile(\n schema: SafewordSchema,\n mode: ReconcileMode,\n ctx: ProjectContext,\n options?: ReconcileOptions,\n): Promise<ReconcileResult> {\n const dryRun = options?.dryRun ?? false;\n\n const plan = computePlan(schema, mode, ctx);\n\n if (dryRun) {\n return {\n actions: plan.actions,\n applied: false,\n created: plan.wouldCreate,\n updated: plan.wouldUpdate,\n removed: plan.wouldRemove,\n packagesToInstall: plan.packagesToInstall,\n packagesToRemove: plan.packagesToRemove,\n };\n }\n\n const result = executePlan(plan, ctx);\n\n return {\n actions: plan.actions,\n applied: true,\n created: result.created,\n updated: result.updated,\n removed: result.removed,\n packagesToInstall: plan.packagesToInstall,\n packagesToRemove: plan.packagesToRemove,\n };\n}\n\n// ============================================================================\n// Plan computation\n// ============================================================================\n\ninterface ReconcilePlan {\n actions: Action[];\n wouldCreate: string[];\n wouldUpdate: string[];\n wouldRemove: string[];\n packagesToInstall: string[];\n packagesToRemove: string[];\n}\n\n/**\n *\n * @param deprecatedFiles\n * @param cwd\n */\nfunction planDeprecatedFilesRemoval(\n deprecatedFiles: string[],\n cwd: string,\n): { actions: Action[]; removed: string[] } {\n const actions: Action[] = [];\n const removed: string[] = [];\n for (const filePath of deprecatedFiles) {\n if (exists(nodePath.join(cwd, filePath))) {\n actions.push({ type: 'rm', path: filePath });\n removed.push(filePath);\n }\n }\n return { actions, removed };\n}\n\n/**\n *\n * @param schema\n * @param mode\n * @param ctx\n */\nfunction computePlan(\n schema: SafewordSchema,\n mode: ReconcileMode,\n ctx: ProjectContext,\n): ReconcilePlan {\n switch (mode) {\n case 'install': {\n return computeInstallPlan(schema, ctx);\n }\n case 'upgrade': {\n return computeUpgradePlan(schema, ctx);\n }\n case 'uninstall': {\n return computeUninstallPlan(schema, ctx, false);\n }\n case 'uninstall-full': {\n return computeUninstallPlan(schema, ctx, true);\n }\n default: {\n // Exhaustive check - TypeScript ensures all cases are handled\n const _exhaustiveCheck: never = mode;\n return _exhaustiveCheck;\n }\n }\n}\n\n/**\n *\n * @param schema\n * @param ctx\n */\nfunction computeInstallPlan(schema: SafewordSchema, ctx: ProjectContext): ReconcilePlan {\n const actions: Action[] = [];\n const wouldCreate: string[] = [];\n\n // 1. Create all directories\n const allDirectories = [...schema.ownedDirs, ...schema.sharedDirs, ...schema.preservedDirs];\n const dirs = planMissingDirectories(allDirectories, ctx.cwd, ctx.isGitRepo);\n actions.push(...dirs.actions);\n wouldCreate.push(...dirs.created);\n\n // 2. Write owned files\n const owned = planOwnedFileWrites(schema.ownedFiles, ctx);\n actions.push(...owned.actions);\n wouldCreate.push(...owned.created);\n\n // 3. Write managed files (only if missing)\n const managed = planManagedFileWrites(schema.managedFiles, ctx);\n actions.push(...managed.actions);\n wouldCreate.push(...managed.created);\n\n // 4. chmod hook/lib/scripts directories\n const chmodPaths = ['.safeword/hooks', '.safeword/hooks/cursor', '.safeword/lib', '.safeword/scripts'];\n if (ctx.isGitRepo) chmodPaths.push(HUSKY_DIR);\n actions.push({ type: 'chmod', paths: chmodPaths });\n\n // 5. JSON merges\n for (const [filePath, definition] of Object.entries(schema.jsonMerges)) {\n actions.push({ type: 'json-merge', path: filePath, definition });\n }\n\n // 6. Text patches\n const patches = planTextPatchesWithCreation(schema.textPatches, ctx);\n actions.push(...patches.actions);\n wouldCreate.push(...patches.created);\n\n // 7. Compute packages to install\n const packagesToInstall = computePackagesToInstall(schema, ctx.projectType, ctx.developmentDeps, ctx.isGitRepo);\n\n return { actions, wouldCreate, wouldUpdate: [], wouldRemove: [], packagesToInstall, packagesToRemove: [] };\n}\n\n/**\n *\n * @param schema\n * @param ctx\n */\nfunction computeUpgradePlan(schema: SafewordSchema, ctx: ProjectContext): ReconcilePlan {\n const actions: Action[] = [];\n const wouldCreate: string[] = [];\n const wouldUpdate: string[] = [];\n\n // 1. Ensure directories exist (skip .husky if not a git repo)\n const allDirectories = [...schema.ownedDirs, ...schema.sharedDirs, ...schema.preservedDirs];\n const missingDirectories = planMissingDirectories(allDirectories, ctx.cwd, ctx.isGitRepo);\n actions.push(...missingDirectories.actions);\n wouldCreate.push(...missingDirectories.created);\n\n // 2. Update owned files if content changed (skip .husky files if not a git repo)\n for (const [filePath, definition] of Object.entries(schema.ownedFiles)) {\n if (shouldSkipForNonGit(filePath, ctx.isGitRepo)) continue;\n\n const fullPath = nodePath.join(ctx.cwd, filePath);\n const newContent = resolveFileContent(definition, ctx);\n\n if (!fileNeedsUpdate(fullPath, newContent)) continue;\n\n actions.push({ type: 'write', path: filePath, content: newContent });\n if (exists(fullPath)) {\n wouldUpdate.push(filePath);\n } else {\n wouldCreate.push(filePath);\n }\n }\n\n // 3. Update managed files only if content matches current template\n for (const [filePath, definition] of Object.entries(schema.managedFiles)) {\n const fullPath = nodePath.join(ctx.cwd, filePath);\n const newContent = resolveFileContent(definition, ctx);\n\n if (!exists(fullPath)) {\n // Missing - create it\n actions.push({ type: 'write', path: filePath, content: newContent });\n wouldCreate.push(filePath);\n }\n // If file exists, don't update during upgrade - user may have customized it\n }\n\n // 4. Remove deprecated files (renamed or removed in newer versions)\n const deprecatedFiles = planDeprecatedFilesRemoval(schema.deprecatedFiles, ctx.cwd);\n actions.push(...deprecatedFiles.actions);\n const wouldRemove = deprecatedFiles.removed;\n\n // 4b. Remove deprecated directories (no longer managed by safeword)\n const deprecatedDirectories = planExistingDirectoriesRemoval(schema.deprecatedDirs, ctx.cwd);\n actions.push(...deprecatedDirectories.actions);\n wouldRemove.push(...deprecatedDirectories.removed);\n\n // 5. chmod\n const chmodPathsUpgrade = [\n '.safeword/hooks',\n '.safeword/hooks/cursor',\n '.safeword/lib',\n '.safeword/scripts',\n ];\n actions.push({ type: 'chmod', paths: chmodPathsUpgrade });\n\n // 6. JSON merges (always apply to ensure keys are present)\n for (const [filePath, definition] of Object.entries(schema.jsonMerges)) {\n actions.push({ type: 'json-merge', path: filePath, definition });\n }\n\n // 7. Text patches (only if marker missing, skip .husky in non-git repos)\n actions.push(...planTextPatches(schema.textPatches, ctx.cwd, ctx.isGitRepo));\n\n // 8. Compute packages to install (husky/lint-staged skipped if no git repo)\n const packagesToInstall = computePackagesToInstall(\n schema,\n ctx.projectType,\n ctx.developmentDeps,\n ctx.isGitRepo,\n );\n\n // 9. Compute deprecated packages to remove (only those actually installed)\n const packagesToRemove = schema.deprecatedPackages.filter(pkg => pkg in ctx.developmentDeps);\n\n return {\n actions,\n wouldCreate,\n wouldUpdate,\n wouldRemove,\n packagesToInstall,\n packagesToRemove,\n };\n}\n\n/**\n *\n * @param schema\n * @param ctx\n * @param full\n */\nfunction computeUninstallPlan(\n schema: SafewordSchema,\n ctx: ProjectContext,\n full: boolean,\n): ReconcilePlan {\n const actions: Action[] = [];\n const wouldRemove: string[] = [];\n\n // 1. Remove all owned files and track parent dirs for cleanup\n const ownedFiles = planExistingFilesRemoval(Object.keys(schema.ownedFiles), ctx.cwd);\n actions.push(...ownedFiles.actions);\n wouldRemove.push(...ownedFiles.removed);\n\n // Collect parent dirs that need cleanup (for .claude/* skill dirs)\n const directoriesToCleanup = new Set<string>();\n for (const filePath of ownedFiles.removed) {\n const parentDirectory = getClaudeParentDirectoryForCleanup(filePath);\n if (parentDirectory) directoriesToCleanup.add(parentDirectory);\n }\n const cleanupDirectories = planExistingDirectoriesRemoval([...directoriesToCleanup], ctx.cwd);\n actions.push(...cleanupDirectories.actions);\n wouldRemove.push(...cleanupDirectories.removed);\n\n // 2. JSON unmerges\n for (const [filePath, definition] of Object.entries(schema.jsonMerges)) {\n actions.push({ type: 'json-unmerge', path: filePath, definition });\n }\n\n // 3. Text unpatches\n for (const [filePath, definition] of Object.entries(schema.textPatches)) {\n const fullPath = nodePath.join(ctx.cwd, filePath);\n if (exists(fullPath)) {\n const content = readFileSafe(fullPath) ?? '';\n if (content.includes(definition.marker)) {\n actions.push({ type: 'text-unpatch', path: filePath, definition });\n }\n }\n }\n\n // 4. Remove preserved directories first (reverse order, only if empty)\n const preserved = planExistingDirectoriesRemoval(schema.preservedDirs.toReversed(), ctx.cwd);\n actions.push(...preserved.actions);\n wouldRemove.push(...preserved.removed);\n\n // 5. Remove owned directories (reverse order ensures children before parents)\n const owned = planExistingDirectoriesRemoval(schema.ownedDirs.toReversed(), ctx.cwd);\n actions.push(...owned.actions);\n wouldRemove.push(...owned.removed);\n\n // 6. Full uninstall: remove managed files\n if (full) {\n const managed = planExistingFilesRemoval(Object.keys(schema.managedFiles), ctx.cwd);\n actions.push(...managed.actions);\n wouldRemove.push(...managed.removed);\n }\n\n // 7. Compute packages to remove (full only)\n const packagesToRemove = full\n ? computePackagesToRemove(schema, ctx.projectType, ctx.developmentDeps)\n : [];\n\n return {\n actions,\n wouldCreate: [],\n wouldUpdate: [],\n wouldRemove,\n packagesToInstall: [],\n packagesToRemove,\n };\n}\n\n// ============================================================================\n// Plan execution\n// ============================================================================\n\ninterface ExecutionResult {\n created: string[];\n updated: string[];\n removed: string[];\n}\n\n/**\n *\n * @param plan\n * @param ctx\n */\nfunction executePlan(plan: ReconcilePlan, ctx: ProjectContext): ExecutionResult {\n const created: string[] = [];\n const updated: string[] = [];\n const removed: string[] = [];\n const result = { created, updated, removed };\n\n for (const action of plan.actions) {\n executeAction(action, ctx, result);\n }\n\n return result;\n}\n\n/**\n *\n * @param action\n * @param ctx\n * @param result\n */\nfunction executeChmod(cwd: string, paths: string[]): void {\n for (const path of paths) {\n const fullPath = nodePath.join(cwd, path);\n if (exists(fullPath)) makeScriptsExecutable(fullPath);\n }\n}\n\nfunction executeRmdir(cwd: string, path: string, result: ExecutionResult): void {\n if (removeIfEmpty(nodePath.join(cwd, path))) result.removed.push(path);\n}\n\nfunction executeAction(action: Action, ctx: ProjectContext, result: ExecutionResult): void {\n switch (action.type) {\n case 'mkdir':\n ensureDirectory(nodePath.join(ctx.cwd, action.path));\n result.created.push(action.path);\n break;\n case 'rmdir':\n executeRmdir(ctx.cwd, action.path, result);\n break;\n case 'write':\n executeWrite(ctx.cwd, action.path, action.content, result);\n break;\n case 'rm':\n remove(nodePath.join(ctx.cwd, action.path));\n result.removed.push(action.path);\n break;\n case 'chmod':\n executeChmod(ctx.cwd, action.paths);\n break;\n case 'json-merge':\n executeJsonMerge(ctx.cwd, action.path, action.definition, ctx);\n break;\n case 'json-unmerge':\n executeJsonUnmerge(ctx.cwd, action.path, action.definition);\n break;\n case 'text-patch':\n executeTextPatch(ctx.cwd, action.path, action.definition);\n break;\n case 'text-unpatch':\n executeTextUnpatch(ctx.cwd, action.path, action.definition);\n break;\n }\n}\n\n/**\n *\n * @param cwd\n * @param path\n * @param content\n * @param result\n */\nfunction executeWrite(cwd: string, path: string, content: string, result: ExecutionResult): void {\n const fullPath = nodePath.join(cwd, path);\n const existed = exists(fullPath);\n writeFile(fullPath, content);\n (existed ? result.updated : result.created).push(path);\n}\n\n// ============================================================================\n// Helper functions\n// ============================================================================\n\n/**\n *\n * @param definition\n * @param ctx\n */\nfunction resolveFileContent(definition: FileDefinition, ctx: ProjectContext): string {\n if (definition.template) {\n const templatesDirectory = getTemplatesDirectory();\n return readFile(nodePath.join(templatesDirectory, definition.template));\n }\n\n if (definition.content) {\n return typeof definition.content === 'function' ? definition.content() : definition.content;\n }\n\n if (definition.generator) {\n return definition.generator(ctx);\n }\n\n throw new Error('FileDefinition must have template, content, or generator');\n}\n\n/**\n *\n * @param installedPath\n * @param newContent\n */\nfunction fileNeedsUpdate(installedPath: string, newContent: string): boolean {\n if (!exists(installedPath)) return true;\n const currentContent = readFileSafe(installedPath);\n return currentContent?.trim() !== newContent.trim();\n}\n\n// Packages that require git repo\nconst GIT_ONLY_PACKAGES = new Set(['husky', 'lint-staged']);\n\n/**\n *\n * @param schema\n * @param projectType\n * @param installedDevDeps\n * @param isGitRepo\n */\nexport function computePackagesToInstall(\n schema: SafewordSchema,\n projectType: ProjectType,\n installedDevelopmentDeps: Record<string, string>,\n isGitRepo = true,\n): string[] {\n let needed = [...schema.packages.base];\n\n // Filter out git-only packages when not in a git repo\n if (!isGitRepo) {\n needed = needed.filter(pkg => !GIT_ONLY_PACKAGES.has(pkg));\n }\n\n for (const [key, deps] of Object.entries(schema.packages.conditional)) {\n if (projectType[key as keyof ProjectType]) {\n needed.push(...deps);\n }\n }\n\n return needed.filter(pkg => !(pkg in installedDevelopmentDeps));\n}\n\n/**\n *\n * @param schema\n * @param projectType\n * @param installedDevDeps\n */\nfunction computePackagesToRemove(\n schema: SafewordSchema,\n projectType: ProjectType,\n installedDevelopmentDeps: Record<string, string>,\n): string[] {\n const safewordPackages = [...schema.packages.base];\n\n for (const [key, deps] of Object.entries(schema.packages.conditional)) {\n if (projectType[key as keyof ProjectType]) {\n safewordPackages.push(...deps);\n }\n }\n\n // Only remove packages that are actually installed\n return safewordPackages.filter(pkg => pkg in installedDevelopmentDeps);\n}\n\n/**\n *\n * @param cwd\n * @param path\n * @param definition\n * @param ctx\n */\nfunction executeJsonMerge(\n cwd: string,\n path: string,\n definition: JsonMergeDefinition,\n ctx: ProjectContext,\n): void {\n const fullPath = nodePath.join(cwd, path);\n const existing = readJson<Record<string, unknown>>(fullPath) ?? {};\n const merged = definition.merge(existing, ctx);\n\n // Skip write if content is unchanged (avoids formatting churn)\n if (JSON.stringify(existing) === JSON.stringify(merged)) return;\n\n writeJson(fullPath, merged);\n}\n\n/**\n *\n * @param cwd\n * @param path\n * @param definition\n */\nfunction executeJsonUnmerge(cwd: string, path: string, definition: JsonMergeDefinition): void {\n const fullPath = nodePath.join(cwd, path);\n if (!exists(fullPath)) return;\n\n const existing = readJson<Record<string, unknown>>(fullPath);\n if (!existing) return;\n\n const unmerged = definition.unmerge(existing);\n\n // Check if file should be removed\n if (definition.removeFileIfEmpty) {\n const remainingKeys = Object.keys(unmerged).filter(k => unmerged[k] !== undefined);\n if (remainingKeys.length === 0) {\n remove(fullPath);\n return;\n }\n }\n\n writeJson(fullPath, unmerged);\n}\n\n/**\n *\n * @param cwd\n * @param path\n * @param definition\n */\nfunction executeTextPatch(cwd: string, path: string, definition: TextPatchDefinition): void {\n const fullPath = nodePath.join(cwd, path);\n let content = readFileSafe(fullPath) ?? '';\n\n // Check if already patched\n if (content.includes(definition.marker)) return;\n\n // Apply patch\n content =\n definition.operation === 'prepend'\n ? definition.content + content\n : content + definition.content;\n\n writeFile(fullPath, content);\n}\n\n/**\n *\n * @param cwd\n * @param path\n * @param definition\n */\nfunction executeTextUnpatch(cwd: string, path: string, definition: TextPatchDefinition): void {\n const fullPath = nodePath.join(cwd, path);\n const content = readFileSafe(fullPath);\n if (!content) return;\n\n // Remove the patched content\n // First try to remove the full content block\n let unpatched = content.replace(definition.content, '');\n\n // If full content wasn't found but marker exists, remove lines containing the marker\n if (unpatched === content && content.includes(definition.marker)) {\n // Remove lines containing the marker\n const lines = content.split('\\n');\n const filtered = lines.filter(line => !line.includes(definition.marker));\n unpatched = filtered.join('\\n').replace(/^\\n+/, ''); // Remove leading empty lines\n }\n\n writeFile(fullPath, unpatched);\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.\n * @returns ESLint config file content as a string\n */\nexport function getEslintConfig(): string {\n return `import { 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// 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/\");\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// 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.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 '*.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 * Operations are handled by reconcile() in src/reconcile.ts.\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 * 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\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 // Safeword plugin (bundles eslint-config-prettier + all ESLint plugins)\n 'eslint-plugin-safeword',\n // Non-ESLint tools\n 'markdownlint-cli2',\n 'knip',\n ],\n conditional: {\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 * Git utilities for CLI operations\n */\n\nimport nodePath from 'node:path';\n\nimport { exists } from './fs.js';\n\n/**\n * Check if directory is a git repository\n * @param cwd\n */\nexport function isGitRepo(cwd: string): boolean {\n return exists(nodePath.join(cwd, '.git'));\n}\n","/**\n * Project Context Utilities\n *\n * Shared helpers for creating ProjectContext objects used by reconcile().\n */\n\nimport nodePath from 'node:path';\n\nimport type { ProjectContext } from '../schema.js';\nimport { readJson } from './fs.js';\nimport { isGitRepo } from './git.js';\nimport { detectProjectType, type PackageJson } from './project-detector.js';\n\n/**\n * Create a ProjectContext from the current working directory.\n *\n * Reads package.json and detects project type for use with reconcile().\n * @param cwd\n */\nexport function createProjectContext(cwd: string): ProjectContext {\n const packageJson = readJson<PackageJson>(nodePath.join(cwd, 'package.json'));\n\n return {\n cwd,\n projectType: detectProjectType(packageJson ?? {}, cwd),\n developmentDeps: packageJson?.devDependencies ?? {},\n isGitRepo: isGitRepo(cwd),\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 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 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 vitest: hasVitest,\n playwright: hasPlaywright,\n tailwind: hasTailwind,\n publishableLibrary: isPublishable,\n shell: hasShell,\n };\n}\n","/**\n * Console output utilities for consistent CLI messaging\n */\n\n/**\n * Print info message\n * @param message\n */\nexport function info(message: string): void {\n console.log(message);\n}\n\n/**\n * Print success message\n * @param message\n */\nexport function success(message: string): void {\n console.log(`✓ ${message}`);\n}\n\n/**\n * Print warning message\n * @param message\n */\nexport function warn(message: string): void {\n console.warn(`⚠ ${message}`);\n}\n\n/**\n * Print error message to stderr\n * @param message\n */\nexport function error(message: string): void {\n console.error(`✗ ${message}`);\n}\n\n/**\n * Print a blank line\n */\nexport function blank(): void {\n console.log('');\n}\n\n/**\n * Print a section header\n * @param title\n */\nexport function header(title: string): void {\n console.log(`\\n${title}`);\n console.log('─'.repeat(title.length));\n}\n\n/**\n * Print a list item\n * @param item\n * @param indent\n */\nexport function listItem(item: string, indent = 2): void {\n console.log(`${' '.repeat(indent)}• ${item}`);\n}\n\n/**\n * Print key-value pair\n * @param key\n * @param value\n */\nexport function keyValue(key: string, value: string): void {\n console.log(` ${key}: ${value}`);\n}\n"],"mappings":"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","names":["nodePath","isGitRepo","nodePath","nodePath","nodePath","nodePath","readdirSync","nodePath","nodePath"]}
package/dist/cli.js CHANGED
@@ -8,23 +8,23 @@ import { Command } from "commander";
8
8
  var program = new Command();
9
9
  program.name("safeword").description("CLI for setting up and managing safeword development environments").version(VERSION);
10
10
  program.command("setup").description("Set up safeword in the current project").option("-y, --yes", "Accept all defaults (non-interactive mode)").action(async (options) => {
11
- const { setup } = await import("./setup-ZYRPDTQI.js");
11
+ const { setup } = await import("./setup-WZ3F25KX.js");
12
12
  await setup(options);
13
13
  });
14
14
  program.command("check").description("Check project health and versions").option("--offline", "Skip remote version check").action(async (options) => {
15
- const { check } = await import("./check-4HX4SNVV.js");
15
+ const { check } = await import("./check-MLYBKA5Z.js");
16
16
  await check(options);
17
17
  });
18
18
  program.command("upgrade").description("Upgrade safeword configuration to latest version").action(async () => {
19
- const { upgrade } = await import("./upgrade-K2FFESUH.js");
19
+ const { upgrade } = await import("./upgrade-WB7N3GWG.js");
20
20
  await upgrade();
21
21
  });
22
22
  program.command("diff").description("Preview changes that would be made by upgrade").option("-v, --verbose", "Show full diff output").action(async (options) => {
23
- const { diff } = await import("./diff-7QIV6Z5B.js");
23
+ const { diff } = await import("./diff-Q44YDA2W.js");
24
24
  await diff(options);
25
25
  });
26
26
  program.command("reset").description("Remove safeword configuration from project").option("-y, --yes", "Skip confirmation prompt").option("--full", "Also remove linting config and uninstall npm packages").action(async (options) => {
27
- const { reset } = await import("./reset-RP7AGR2Y.js");
27
+ const { reset } = await import("./reset-EEFVJ5GB.js");
28
28
  await reset(options);
29
29
  });
30
30
  if (process.argv.length === 2) {
@@ -9,7 +9,7 @@ import {
9
9
  readFileSafe,
10
10
  reconcile,
11
11
  success
12
- } from "./chunk-POPS3ZRQ.js";
12
+ } from "./chunk-UUKED7KU.js";
13
13
  import {
14
14
  VERSION
15
15
  } from "./chunk-ORQHKDT2.js";
@@ -161,4 +161,4 @@ Packages to install: ${result.packagesToInstall.length}`);
161
161
  export {
162
162
  diff
163
163
  };
164
- //# sourceMappingURL=diff-7QIV6Z5B.js.map
164
+ //# sourceMappingURL=diff-Q44YDA2W.js.map
@@ -9,7 +9,7 @@ import {
9
9
  reconcile,
10
10
  success,
11
11
  warn
12
- } from "./chunk-POPS3ZRQ.js";
12
+ } from "./chunk-UUKED7KU.js";
13
13
  import "./chunk-ORQHKDT2.js";
14
14
 
15
15
  // src/commands/reset.ts
@@ -70,4 +70,4 @@ async function reset(options) {
70
70
  export {
71
71
  reset
72
72
  };
73
- //# sourceMappingURL=reset-RP7AGR2Y.js.map
73
+ //# sourceMappingURL=reset-EEFVJ5GB.js.map
@@ -11,7 +11,7 @@ import {
11
11
  success,
12
12
  warn,
13
13
  writeJson
14
- } from "./chunk-POPS3ZRQ.js";
14
+ } from "./chunk-UUKED7KU.js";
15
15
  import {
16
16
  VERSION
17
17
  } from "./chunk-ORQHKDT2.js";
@@ -88,4 +88,4 @@ async function setup(options) {
88
88
  export {
89
89
  setup
90
90
  };
91
- //# sourceMappingURL=setup-ZYRPDTQI.js.map
91
+ //# sourceMappingURL=setup-WZ3F25KX.js.map
@@ -13,7 +13,7 @@ import {
13
13
  reconcile,
14
14
  success,
15
15
  warn
16
- } from "./chunk-POPS3ZRQ.js";
16
+ } from "./chunk-UUKED7KU.js";
17
17
  import {
18
18
  VERSION
19
19
  } from "./chunk-ORQHKDT2.js";
@@ -73,4 +73,4 @@ async function upgrade() {
73
73
  export {
74
74
  upgrade
75
75
  };
76
- //# sourceMappingURL=upgrade-K2FFESUH.js.map
76
+ //# sourceMappingURL=upgrade-WB7N3GWG.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "safeword",
3
- "version": "0.8.10",
3
+ "version": "0.9.0",
4
4
  "description": "CLI for setting up and managing safeword development environments",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/utils/fs.ts","../src/reconcile.ts","../src/templates/config.ts","../src/templates/content.ts","../src/utils/hooks.ts","../src/utils/install.ts","../src/schema.ts","../src/utils/git.ts","../src/utils/context.ts","../src/utils/project-detector.ts","../src/utils/output.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 * Reconciliation Engine\n *\n * Computes and executes plans based on SAFEWORD_SCHEMA and project state.\n * This is the single source of truth for all file/dir/config operations.\n */\n\nimport nodePath from 'node:path';\n\nimport type {\n FileDefinition,\n JsonMergeDefinition,\n ProjectContext,\n SafewordSchema,\n TextPatchDefinition,\n} from './schema.js';\nimport {\n ensureDirectory,\n exists,\n getTemplatesDirectory,\n makeScriptsExecutable,\n readFile,\n readFileSafe,\n readJson,\n remove,\n removeIfEmpty,\n writeFile,\n writeJson,\n} from './utils/fs.js';\nimport type { ProjectType } from './utils/project-detector.js';\n\n// ============================================================================\n// Constants\n// ============================================================================\n\nconst HUSKY_DIR = '.husky';\n\n/**\n * Check if path should be skipped in non-git repos (husky files)\n * @param path\n * @param isGitRepo\n */\nfunction shouldSkipForNonGit(path: string, isGitRepo: boolean): boolean {\n return path.startsWith(HUSKY_DIR) && !isGitRepo;\n}\n\n/**\n * Plan mkdir actions for directories that don't exist\n * @param dirs\n * @param cwd\n * @param isGitRepo\n */\nfunction planMissingDirectories(\n directories: string[],\n cwd: string,\n isGitRepo: boolean,\n): { actions: Action[]; created: string[] } {\n const actions: Action[] = [];\n const created: string[] = [];\n for (const dir of directories) {\n if (shouldSkipForNonGit(dir, isGitRepo)) continue;\n if (!exists(nodePath.join(cwd, dir))) {\n actions.push({ type: 'mkdir', path: dir });\n created.push(dir);\n }\n }\n return { actions, created };\n}\n\n/**\n * Plan text-patch actions for files missing the marker\n * @param patches\n * @param cwd\n * @param isGitRepo\n */\nfunction planTextPatches(\n patches: Record<string, TextPatchDefinition>,\n cwd: string,\n isGitRepo: boolean,\n): Action[] {\n const actions: Action[] = [];\n for (const [filePath, definition] of Object.entries(patches)) {\n if (shouldSkipForNonGit(filePath, isGitRepo)) continue;\n const content = readFileSafe(nodePath.join(cwd, filePath)) ?? '';\n if (!content.includes(definition.marker)) {\n actions.push({ type: 'text-patch', path: filePath, definition });\n }\n }\n return actions;\n}\n\nfunction planOwnedFileWrites(\n files: Record<string, FileDefinition>,\n ctx: ProjectContext,\n): { actions: Action[]; created: string[] } {\n const actions: Action[] = [];\n const created: string[] = [];\n for (const [filePath, definition] of Object.entries(files)) {\n if (shouldSkipForNonGit(filePath, ctx.isGitRepo)) continue;\n const content = resolveFileContent(definition, ctx);\n actions.push({ type: 'write', path: filePath, content });\n created.push(filePath);\n }\n return { actions, created };\n}\n\nfunction planManagedFileWrites(\n files: Record<string, FileDefinition>,\n ctx: ProjectContext,\n): { actions: Action[]; created: string[] } {\n const actions: Action[] = [];\n const created: string[] = [];\n for (const [filePath, definition] of Object.entries(files)) {\n if (exists(nodePath.join(ctx.cwd, filePath))) continue;\n const content = resolveFileContent(definition, ctx);\n actions.push({ type: 'write', path: filePath, content });\n created.push(filePath);\n }\n return { actions, created };\n}\n\nfunction planTextPatchesWithCreation(\n patches: Record<string, TextPatchDefinition>,\n ctx: ProjectContext,\n wouldCreate: string[],\n): Action[] {\n const actions: Action[] = [];\n for (const [filePath, definition] of Object.entries(patches)) {\n if (shouldSkipForNonGit(filePath, ctx.isGitRepo)) continue;\n actions.push({ type: 'text-patch', path: filePath, definition });\n if (definition.createIfMissing && !exists(nodePath.join(ctx.cwd, filePath))) {\n wouldCreate.push(filePath);\n }\n }\n return actions;\n}\n\n/**\n * Plan rmdir actions for directories that exist\n * @param dirs\n * @param cwd\n */\nfunction planExistingDirectoriesRemoval(\n directories: string[],\n cwd: string,\n): { actions: Action[]; removed: string[] } {\n const actions: Action[] = [];\n const removed: string[] = [];\n for (const dir of directories) {\n if (exists(nodePath.join(cwd, dir))) {\n actions.push({ type: 'rmdir', path: dir });\n removed.push(dir);\n }\n }\n return { actions, removed };\n}\n\n/**\n * Plan rm actions for files that exist\n * @param files\n * @param cwd\n */\nfunction planExistingFilesRemoval(\n files: string[],\n cwd: string,\n): { actions: Action[]; removed: string[] } {\n const actions: Action[] = [];\n const removed: string[] = [];\n for (const filePath of files) {\n if (exists(nodePath.join(cwd, filePath))) {\n actions.push({ type: 'rm', path: filePath });\n removed.push(filePath);\n }\n }\n return { actions, removed };\n}\n\n/**\n * Check if a .claude path needs parent dir cleanup\n * @param filePath\n */\nfunction getClaudeParentDirectoryForCleanup(filePath: string): string | undefined {\n if (!filePath.startsWith('.claude/')) return undefined;\n const parentDirectory = filePath.slice(0, Math.max(0, filePath.lastIndexOf('/')));\n if (\n !parentDirectory ||\n parentDirectory === '.claude' ||\n parentDirectory === '.claude/skills' ||\n parentDirectory === '.claude/commands'\n ) {\n return undefined;\n }\n return parentDirectory;\n}\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type ReconcileMode = 'install' | 'upgrade' | 'uninstall' | 'uninstall-full';\n\nexport type Action =\n | { type: 'mkdir'; path: string }\n | { type: 'rmdir'; path: string }\n | { type: 'write'; path: string; content: string }\n | { type: 'rm'; path: string }\n | { type: 'chmod'; paths: string[] }\n | { type: 'json-merge'; path: string; definition: JsonMergeDefinition }\n | { type: 'json-unmerge'; path: string; definition: JsonMergeDefinition }\n | { type: 'text-patch'; path: string; definition: TextPatchDefinition }\n | { type: 'text-unpatch'; path: string; definition: TextPatchDefinition };\n\nexport interface ReconcileResult {\n actions: Action[];\n applied: boolean;\n created: string[];\n updated: string[];\n removed: string[];\n packagesToInstall: string[];\n packagesToRemove: string[];\n}\n\nexport interface ReconcileOptions {\n dryRun?: boolean;\n}\n\n// ============================================================================\n// Main reconcile function\n// ============================================================================\n\n/**\n *\n * @param schema\n * @param mode\n * @param ctx\n * @param options\n */\nexport async function reconcile(\n schema: SafewordSchema,\n mode: ReconcileMode,\n ctx: ProjectContext,\n options?: ReconcileOptions,\n): Promise<ReconcileResult> {\n const dryRun = options?.dryRun ?? false;\n\n const plan = computePlan(schema, mode, ctx);\n\n if (dryRun) {\n return {\n actions: plan.actions,\n applied: false,\n created: plan.wouldCreate,\n updated: plan.wouldUpdate,\n removed: plan.wouldRemove,\n packagesToInstall: plan.packagesToInstall,\n packagesToRemove: plan.packagesToRemove,\n };\n }\n\n const result = executePlan(plan, ctx);\n\n return {\n actions: plan.actions,\n applied: true,\n created: result.created,\n updated: result.updated,\n removed: result.removed,\n packagesToInstall: plan.packagesToInstall,\n packagesToRemove: plan.packagesToRemove,\n };\n}\n\n// ============================================================================\n// Plan computation\n// ============================================================================\n\ninterface ReconcilePlan {\n actions: Action[];\n wouldCreate: string[];\n wouldUpdate: string[];\n wouldRemove: string[];\n packagesToInstall: string[];\n packagesToRemove: string[];\n}\n\n/**\n *\n * @param deprecatedFiles\n * @param cwd\n */\nfunction planDeprecatedFilesRemoval(\n deprecatedFiles: string[],\n cwd: string,\n): { actions: Action[]; removed: string[] } {\n const actions: Action[] = [];\n const removed: string[] = [];\n for (const filePath of deprecatedFiles) {\n if (exists(nodePath.join(cwd, filePath))) {\n actions.push({ type: 'rm', path: filePath });\n removed.push(filePath);\n }\n }\n return { actions, removed };\n}\n\n/**\n *\n * @param schema\n * @param mode\n * @param ctx\n */\nfunction computePlan(\n schema: SafewordSchema,\n mode: ReconcileMode,\n ctx: ProjectContext,\n): ReconcilePlan {\n switch (mode) {\n case 'install': {\n return computeInstallPlan(schema, ctx);\n }\n case 'upgrade': {\n return computeUpgradePlan(schema, ctx);\n }\n case 'uninstall': {\n return computeUninstallPlan(schema, ctx, false);\n }\n case 'uninstall-full': {\n return computeUninstallPlan(schema, ctx, true);\n }\n default: {\n // Exhaustive check - TypeScript ensures all cases are handled\n const _exhaustiveCheck: never = mode;\n return _exhaustiveCheck;\n }\n }\n}\n\n/**\n *\n * @param schema\n * @param ctx\n */\nfunction computeInstallPlan(schema: SafewordSchema, ctx: ProjectContext): ReconcilePlan {\n const actions: Action[] = [];\n const wouldCreate: string[] = [];\n\n // 1. Create all directories\n const allDirectories = [...schema.ownedDirs, ...schema.sharedDirs, ...schema.preservedDirs];\n const dirs = planMissingDirectories(allDirectories, ctx.cwd, ctx.isGitRepo);\n actions.push(...dirs.actions);\n wouldCreate.push(...dirs.created);\n\n // 2. Write owned files\n const owned = planOwnedFileWrites(schema.ownedFiles, ctx);\n actions.push(...owned.actions);\n wouldCreate.push(...owned.created);\n\n // 3. Write managed files (only if missing)\n const managed = planManagedFileWrites(schema.managedFiles, ctx);\n actions.push(...managed.actions);\n wouldCreate.push(...managed.created);\n\n // 4. chmod hook/lib/scripts directories\n const chmodPaths = ['.safeword/hooks', '.safeword/hooks/cursor', '.safeword/lib', '.safeword/scripts'];\n if (ctx.isGitRepo) chmodPaths.push(HUSKY_DIR);\n actions.push({ type: 'chmod', paths: chmodPaths });\n\n // 5. JSON merges\n for (const [filePath, definition] of Object.entries(schema.jsonMerges)) {\n actions.push({ type: 'json-merge', path: filePath, definition });\n }\n\n // 6. Text patches\n actions.push(...planTextPatchesWithCreation(schema.textPatches, ctx, wouldCreate));\n\n // 7. Compute packages to install\n const packagesToInstall = computePackagesToInstall(schema, ctx.projectType, ctx.developmentDeps, ctx.isGitRepo);\n\n return { actions, wouldCreate, wouldUpdate: [], wouldRemove: [], packagesToInstall, packagesToRemove: [] };\n}\n\n/**\n *\n * @param schema\n * @param ctx\n */\nfunction computeUpgradePlan(schema: SafewordSchema, ctx: ProjectContext): ReconcilePlan {\n const actions: Action[] = [];\n const wouldCreate: string[] = [];\n const wouldUpdate: string[] = [];\n\n // 1. Ensure directories exist (skip .husky if not a git repo)\n const allDirectories = [...schema.ownedDirs, ...schema.sharedDirs, ...schema.preservedDirs];\n const missingDirectories = planMissingDirectories(allDirectories, ctx.cwd, ctx.isGitRepo);\n actions.push(...missingDirectories.actions);\n wouldCreate.push(...missingDirectories.created);\n\n // 2. Update owned files if content changed (skip .husky files if not a git repo)\n for (const [filePath, definition] of Object.entries(schema.ownedFiles)) {\n if (shouldSkipForNonGit(filePath, ctx.isGitRepo)) continue;\n\n const fullPath = nodePath.join(ctx.cwd, filePath);\n const newContent = resolveFileContent(definition, ctx);\n\n if (!fileNeedsUpdate(fullPath, newContent)) continue;\n\n actions.push({ type: 'write', path: filePath, content: newContent });\n if (exists(fullPath)) {\n wouldUpdate.push(filePath);\n } else {\n wouldCreate.push(filePath);\n }\n }\n\n // 3. Update managed files only if content matches current template\n for (const [filePath, definition] of Object.entries(schema.managedFiles)) {\n const fullPath = nodePath.join(ctx.cwd, filePath);\n const newContent = resolveFileContent(definition, ctx);\n\n if (!exists(fullPath)) {\n // Missing - create it\n actions.push({ type: 'write', path: filePath, content: newContent });\n wouldCreate.push(filePath);\n }\n // If file exists, don't update during upgrade - user may have customized it\n }\n\n // 4. Remove deprecated files (renamed or removed in newer versions)\n const deprecatedFiles = planDeprecatedFilesRemoval(schema.deprecatedFiles, ctx.cwd);\n actions.push(...deprecatedFiles.actions);\n const wouldRemove = deprecatedFiles.removed;\n\n // 4b. Remove deprecated directories (no longer managed by safeword)\n const deprecatedDirectories = planExistingDirectoriesRemoval(schema.deprecatedDirs, ctx.cwd);\n actions.push(...deprecatedDirectories.actions);\n wouldRemove.push(...deprecatedDirectories.removed);\n\n // 5. chmod\n const chmodPathsUpgrade = [\n '.safeword/hooks',\n '.safeword/hooks/cursor',\n '.safeword/lib',\n '.safeword/scripts',\n ];\n actions.push({ type: 'chmod', paths: chmodPathsUpgrade });\n\n // 6. JSON merges (always apply to ensure keys are present)\n for (const [filePath, definition] of Object.entries(schema.jsonMerges)) {\n actions.push({ type: 'json-merge', path: filePath, definition });\n }\n\n // 7. Text patches (only if marker missing, skip .husky in non-git repos)\n actions.push(...planTextPatches(schema.textPatches, ctx.cwd, ctx.isGitRepo));\n\n // 8. Compute packages to install (husky/lint-staged skipped if no git repo)\n const packagesToInstall = computePackagesToInstall(\n schema,\n ctx.projectType,\n ctx.developmentDeps,\n ctx.isGitRepo,\n );\n\n // 9. Compute deprecated packages to remove (only those actually installed)\n const packagesToRemove = schema.deprecatedPackages.filter(pkg => pkg in ctx.developmentDeps);\n\n return {\n actions,\n wouldCreate,\n wouldUpdate,\n wouldRemove,\n packagesToInstall,\n packagesToRemove,\n };\n}\n\n/**\n *\n * @param schema\n * @param ctx\n * @param full\n */\nfunction computeUninstallPlan(\n schema: SafewordSchema,\n ctx: ProjectContext,\n full: boolean,\n): ReconcilePlan {\n const actions: Action[] = [];\n const wouldRemove: string[] = [];\n\n // 1. Remove all owned files and track parent dirs for cleanup\n const ownedFiles = planExistingFilesRemoval(Object.keys(schema.ownedFiles), ctx.cwd);\n actions.push(...ownedFiles.actions);\n wouldRemove.push(...ownedFiles.removed);\n\n // Collect parent dirs that need cleanup (for .claude/* skill dirs)\n const directoriesToCleanup = new Set<string>();\n for (const filePath of ownedFiles.removed) {\n const parentDirectory = getClaudeParentDirectoryForCleanup(filePath);\n if (parentDirectory) directoriesToCleanup.add(parentDirectory);\n }\n const cleanupDirectories = planExistingDirectoriesRemoval([...directoriesToCleanup], ctx.cwd);\n actions.push(...cleanupDirectories.actions);\n wouldRemove.push(...cleanupDirectories.removed);\n\n // 2. JSON unmerges\n for (const [filePath, definition] of Object.entries(schema.jsonMerges)) {\n actions.push({ type: 'json-unmerge', path: filePath, definition });\n }\n\n // 3. Text unpatches\n for (const [filePath, definition] of Object.entries(schema.textPatches)) {\n const fullPath = nodePath.join(ctx.cwd, filePath);\n if (exists(fullPath)) {\n const content = readFileSafe(fullPath) ?? '';\n if (content.includes(definition.marker)) {\n actions.push({ type: 'text-unpatch', path: filePath, definition });\n }\n }\n }\n\n // 4. Remove preserved directories first (reverse order, only if empty)\n const preserved = planExistingDirectoriesRemoval(schema.preservedDirs.toReversed(), ctx.cwd);\n actions.push(...preserved.actions);\n wouldRemove.push(...preserved.removed);\n\n // 5. Remove owned directories (reverse order ensures children before parents)\n const owned = planExistingDirectoriesRemoval(schema.ownedDirs.toReversed(), ctx.cwd);\n actions.push(...owned.actions);\n wouldRemove.push(...owned.removed);\n\n // 6. Full uninstall: remove managed files\n if (full) {\n const managed = planExistingFilesRemoval(Object.keys(schema.managedFiles), ctx.cwd);\n actions.push(...managed.actions);\n wouldRemove.push(...managed.removed);\n }\n\n // 7. Compute packages to remove (full only)\n const packagesToRemove = full\n ? computePackagesToRemove(schema, ctx.projectType, ctx.developmentDeps)\n : [];\n\n return {\n actions,\n wouldCreate: [],\n wouldUpdate: [],\n wouldRemove,\n packagesToInstall: [],\n packagesToRemove,\n };\n}\n\n// ============================================================================\n// Plan execution\n// ============================================================================\n\ninterface ExecutionResult {\n created: string[];\n updated: string[];\n removed: string[];\n}\n\n/**\n *\n * @param plan\n * @param ctx\n */\nfunction executePlan(plan: ReconcilePlan, ctx: ProjectContext): ExecutionResult {\n const created: string[] = [];\n const updated: string[] = [];\n const removed: string[] = [];\n const result = { created, updated, removed };\n\n for (const action of plan.actions) {\n executeAction(action, ctx, result);\n }\n\n return result;\n}\n\n/**\n *\n * @param action\n * @param ctx\n * @param result\n */\nfunction executeChmod(cwd: string, paths: string[]): void {\n for (const path of paths) {\n const fullPath = nodePath.join(cwd, path);\n if (exists(fullPath)) makeScriptsExecutable(fullPath);\n }\n}\n\nfunction executeRmdir(cwd: string, path: string, result: ExecutionResult): void {\n if (removeIfEmpty(nodePath.join(cwd, path))) result.removed.push(path);\n}\n\nfunction executeAction(action: Action, ctx: ProjectContext, result: ExecutionResult): void {\n switch (action.type) {\n case 'mkdir':\n ensureDirectory(nodePath.join(ctx.cwd, action.path));\n result.created.push(action.path);\n break;\n case 'rmdir':\n executeRmdir(ctx.cwd, action.path, result);\n break;\n case 'write':\n executeWrite(ctx.cwd, action.path, action.content, result);\n break;\n case 'rm':\n remove(nodePath.join(ctx.cwd, action.path));\n result.removed.push(action.path);\n break;\n case 'chmod':\n executeChmod(ctx.cwd, action.paths);\n break;\n case 'json-merge':\n executeJsonMerge(ctx.cwd, action.path, action.definition, ctx);\n break;\n case 'json-unmerge':\n executeJsonUnmerge(ctx.cwd, action.path, action.definition);\n break;\n case 'text-patch':\n executeTextPatch(ctx.cwd, action.path, action.definition);\n break;\n case 'text-unpatch':\n executeTextUnpatch(ctx.cwd, action.path, action.definition);\n break;\n }\n}\n\n/**\n *\n * @param cwd\n * @param path\n * @param content\n * @param result\n */\nfunction executeWrite(cwd: string, path: string, content: string, result: ExecutionResult): void {\n const fullPath = nodePath.join(cwd, path);\n const existed = exists(fullPath);\n writeFile(fullPath, content);\n (existed ? result.updated : result.created).push(path);\n}\n\n// ============================================================================\n// Helper functions\n// ============================================================================\n\n/**\n *\n * @param definition\n * @param ctx\n */\nfunction resolveFileContent(definition: FileDefinition, ctx: ProjectContext): string {\n if (definition.template) {\n const templatesDirectory = getTemplatesDirectory();\n return readFile(nodePath.join(templatesDirectory, definition.template));\n }\n\n if (definition.content) {\n return typeof definition.content === 'function' ? definition.content() : definition.content;\n }\n\n if (definition.generator) {\n return definition.generator(ctx);\n }\n\n throw new Error('FileDefinition must have template, content, or generator');\n}\n\n/**\n *\n * @param installedPath\n * @param newContent\n */\nfunction fileNeedsUpdate(installedPath: string, newContent: string): boolean {\n if (!exists(installedPath)) return true;\n const currentContent = readFileSafe(installedPath);\n return currentContent?.trim() !== newContent.trim();\n}\n\n// Packages that require git repo\nconst GIT_ONLY_PACKAGES = new Set(['husky', 'lint-staged']);\n\n/**\n *\n * @param schema\n * @param projectType\n * @param installedDevDeps\n * @param isGitRepo\n */\nexport function computePackagesToInstall(\n schema: SafewordSchema,\n projectType: ProjectType,\n installedDevelopmentDeps: Record<string, string>,\n isGitRepo = true,\n): string[] {\n let needed = [...schema.packages.base];\n\n // Filter out git-only packages when not in a git repo\n if (!isGitRepo) {\n needed = needed.filter(pkg => !GIT_ONLY_PACKAGES.has(pkg));\n }\n\n for (const [key, deps] of Object.entries(schema.packages.conditional)) {\n if (projectType[key as keyof ProjectType]) {\n needed.push(...deps);\n }\n }\n\n return needed.filter(pkg => !(pkg in installedDevelopmentDeps));\n}\n\n/**\n *\n * @param schema\n * @param projectType\n * @param installedDevDeps\n */\nfunction computePackagesToRemove(\n schema: SafewordSchema,\n projectType: ProjectType,\n installedDevelopmentDeps: Record<string, string>,\n): string[] {\n const safewordPackages = [...schema.packages.base];\n\n for (const [key, deps] of Object.entries(schema.packages.conditional)) {\n if (projectType[key as keyof ProjectType]) {\n safewordPackages.push(...deps);\n }\n }\n\n // Only remove packages that are actually installed\n return safewordPackages.filter(pkg => pkg in installedDevelopmentDeps);\n}\n\n/**\n *\n * @param cwd\n * @param path\n * @param definition\n * @param ctx\n */\nfunction executeJsonMerge(\n cwd: string,\n path: string,\n definition: JsonMergeDefinition,\n ctx: ProjectContext,\n): void {\n const fullPath = nodePath.join(cwd, path);\n const existing = readJson<Record<string, unknown>>(fullPath) ?? {};\n const merged = definition.merge(existing, ctx);\n\n // Skip write if content is unchanged (avoids formatting churn)\n if (JSON.stringify(existing) === JSON.stringify(merged)) return;\n\n writeJson(fullPath, merged);\n}\n\n/**\n *\n * @param cwd\n * @param path\n * @param definition\n */\nfunction executeJsonUnmerge(cwd: string, path: string, definition: JsonMergeDefinition): void {\n const fullPath = nodePath.join(cwd, path);\n if (!exists(fullPath)) return;\n\n const existing = readJson<Record<string, unknown>>(fullPath);\n if (!existing) return;\n\n const unmerged = definition.unmerge(existing);\n\n // Check if file should be removed\n if (definition.removeFileIfEmpty) {\n const remainingKeys = Object.keys(unmerged).filter(k => unmerged[k] !== undefined);\n if (remainingKeys.length === 0) {\n remove(fullPath);\n return;\n }\n }\n\n writeJson(fullPath, unmerged);\n}\n\n/**\n *\n * @param cwd\n * @param path\n * @param definition\n */\nfunction executeTextPatch(cwd: string, path: string, definition: TextPatchDefinition): void {\n const fullPath = nodePath.join(cwd, path);\n let content = readFileSafe(fullPath) ?? '';\n\n // Check if already patched\n if (content.includes(definition.marker)) return;\n\n // Apply patch\n content =\n definition.operation === 'prepend'\n ? definition.content + content\n : content + definition.content;\n\n writeFile(fullPath, content);\n}\n\n/**\n *\n * @param cwd\n * @param path\n * @param definition\n */\nfunction executeTextUnpatch(cwd: string, path: string, definition: TextPatchDefinition): void {\n const fullPath = nodePath.join(cwd, path);\n const content = readFileSafe(fullPath);\n if (!content) return;\n\n // Remove the patched content\n // First try to remove the full content block\n let unpatched = content.replace(definition.content, '');\n\n // If full content wasn't found but marker exists, remove lines containing the marker\n if (unpatched === content && content.includes(definition.marker)) {\n // Remove lines containing the marker\n const lines = content.split('\\n');\n const filtered = lines.filter(line => !line.includes(definition.marker));\n unpatched = filtered.join('\\n').replace(/^\\n+/, ''); // Remove leading empty lines\n }\n\n writeFile(fullPath, unpatched);\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.\n * @returns ESLint config file content as a string\n */\nexport function getEslintConfig(): string {\n return `import { 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// 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/\");\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// 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.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 '*.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 * Operations are handled by reconcile() in src/reconcile.ts.\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 * 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\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 // Safeword plugin (bundles eslint-config-prettier + all ESLint plugins)\n 'eslint-plugin-safeword',\n // Non-ESLint tools\n 'markdownlint-cli2',\n 'knip',\n ],\n conditional: {\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 * Git utilities for CLI operations\n */\n\nimport nodePath from 'node:path';\n\nimport { exists } from './fs.js';\n\n/**\n * Check if directory is a git repository\n * @param cwd\n */\nexport function isGitRepo(cwd: string): boolean {\n return exists(nodePath.join(cwd, '.git'));\n}\n","/**\n * Project Context Utilities\n *\n * Shared helpers for creating ProjectContext objects used by reconcile().\n */\n\nimport nodePath from 'node:path';\n\nimport type { ProjectContext } from '../schema.js';\nimport { readJson } from './fs.js';\nimport { isGitRepo } from './git.js';\nimport { detectProjectType, type PackageJson } from './project-detector.js';\n\n/**\n * Create a ProjectContext from the current working directory.\n *\n * Reads package.json and detects project type for use with reconcile().\n * @param cwd\n */\nexport function createProjectContext(cwd: string): ProjectContext {\n const packageJson = readJson<PackageJson>(nodePath.join(cwd, 'package.json'));\n\n return {\n cwd,\n projectType: detectProjectType(packageJson ?? {}, cwd),\n developmentDeps: packageJson?.devDependencies ?? {},\n isGitRepo: isGitRepo(cwd),\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 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 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 vitest: hasVitest,\n playwright: hasPlaywright,\n tailwind: hasTailwind,\n publishableLibrary: isPublishable,\n shell: hasShell,\n };\n}\n","/**\n * Console output utilities for consistent CLI messaging\n */\n\n/**\n * Print info message\n * @param message\n */\nexport function info(message: string): void {\n console.log(message);\n}\n\n/**\n * Print success message\n * @param message\n */\nexport function success(message: string): void {\n console.log(`✓ ${message}`);\n}\n\n/**\n * Print warning message\n * @param message\n */\nexport function warn(message: string): void {\n console.warn(`⚠ ${message}`);\n}\n\n/**\n * Print error message to stderr\n * @param message\n */\nexport function error(message: string): void {\n console.error(`✗ ${message}`);\n}\n\n/**\n * Print a blank line\n */\nexport function blank(): void {\n console.log('');\n}\n\n/**\n * Print a section header\n * @param title\n */\nexport function header(title: string): void {\n console.log(`\\n${title}`);\n console.log('─'.repeat(title.length));\n}\n\n/**\n * Print a list item\n * @param item\n * @param indent\n */\nexport function listItem(item: string, indent = 2): void {\n console.log(`${' '.repeat(indent)}• ${item}`);\n}\n\n/**\n * Print key-value pair\n * @param key\n * @param value\n */\nexport function keyValue(key: string, value: string): void {\n console.log(` ${key}: ${value}`);\n}\n"],"mappings":"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","names":["nodePath","isGitRepo","nodePath","nodePath","nodePath","nodePath","readdirSync","nodePath","nodePath"]}